Oru’el Developer documentationBack to console

Oru’el QC: customer quickstart

Base URL: https://kanook.oru-el.com. Your application uses the API; the Oru’el console is optional. Integrating the API does not replace your application's interface. The console provides a ready-made place to manage keys, follow jobs, review reports and inspect usage.

Before the first run

Oru’el creates your organization, connects an approved GCS source prefix, enrolls an execution profile and configures isolated results storage. You receive your organization ID, connection ID, results bucket/prefix, available profile and an invitation. Accept it at /console/sign-in; create a named machine key under **API keys**, with jobs:read, jobs:write, results:read, and usage:read as needed. Store the key in your backend secret manager. Never embed it in browser code. Keys are shown once, expire, and can be revoked immediately. Google sign-in is available only if enabled for your deployment and invited email.

Your application also needs its own Google identity for creating source/configuration manifests and reading result objects in the enrolled results prefix. An Oru’el API key grants no GCS permission. Use workload identity or Application Default Credentials, not uploaded service-account JSON keys. Oru’el workers get read-only access to the enrolled source prefix. The source and results locations may be in different cloud projects; use the supplied connection settings.

First successful run with the Python SDK

Use the versioned wheel supplied by Oru’el; do not assume an unrelated public package is this SDK. Python 3.10+ is supported. Install the supplied wheel with its gcs,customer extras in your own environment. This example assumes ./uploads/run-001/ is an exact local copy of the files uploaded to the source connection's run-001/ directory. The SDK hashes the local files; the worker verifies the actual GCS bytes against those hashes. Large/customer-specific datasets should use the supplied manifest-generation tooling rather than manually typing hashes.

import json
import os
import time
from pathlib import Path

from oruel.gcs import GCSObjects
from oruel.service.customer import ControlClient, ObjectManifestStore
from oruel.service.native_client import NativeQCClient

control = ControlClient("https://kanook.oru-el.com", os.environ["ORUEL_API_KEY"])
results = GCSObjects(os.environ["ORUEL_RESULTS_BUCKET"], os.environ["ORUEL_RESULTS_PREFIX"])
qc = NativeQCClient(
    control, ObjectManifestStore(results), os.environ["ORUEL_ORGANIZATION"],
    os.environ["ORUEL_CONNECTION"], source_root=Path("./uploads"),
)
source = qc.describe_source("run-001")
job = qc.submit_native(
    source, profile=os.environ["ORUEL_PROFILE"], request_id="run-001-v1",
    check_selection={"schema_version": 1, "mode": "all_applicable"},
    semantic=True, deadline_seconds=14400,
)
print("Job:", job["id"])
print("Console report:", "https://kanook.oru-el.com/reports/" + job["id"])
while not job["terminal"]:
    time.sleep(10)
    job = qc.status(job["id"])
    print(job["status"], job.get("stage"), job.get("completed_units"), job.get("total_units"))
if job["actions"]["results"]:
    report = qc.native_report(job["id"])
    Path("qc-report.json").write_text(json.dumps(report, indent=2))
else:
    raise RuntimeError("QC produced no report: " + str(job.get("error_code")))

The SDK writes source/specification envelopes into tenant storage, registers their immutable references, and submits POST /v1/qc-jobs. Video bytes, cloud credentials and customer filesystem paths are not uploaded to the regional API. all_applicable selects checks; readiness depends on the data, configuration, enrolled models and available sensors. A listed check can be blocked, unavailable or skipped. Inspect the report's coverage and acceptance separately from execution completion. semantic=True enables enrolled semantic checks; it does not override profile limits or create unconfigured model infrastructure.

Keep request_id stable when retrying an uncertain submission with identical inputs/configuration. Changing it creates a new job and can cause a new charge. A rerun is a separate job and is tracked separately. Automatic worker attempts stay within the original job. For custom checks use the versioned catalog and specification schema; do not guess metric names or configuration keys.

API sequence and payloads

Every call below uses Authorization: Bearer YOUR_API_KEY. Send Content-Type: application/json for JSON bodies and a unique, stable Idempotency-Key for mutations that require it.

ActionEndpointNotes
Identify accountGET /v1/meOrganization and credential identity.
Discover source connectionsGET /v1/connectionsFollow next_cursor with after.
Discover enrolled native profilesGET /v1/execution-profilesActive tenant Batch profiles, not a capacity guarantee.
Discover checksGET /v1/checks?limit=50Catalog availability does not establish worker readiness.
Register sourcePOST /v1/assets{connection_id, manifest_id, manifest_sha256}.
Register configurationPOST /v1/specificationsSame reference fields. SDK builds/validates envelopes.
SubmitPOST /v1/qc-jobsPayload below; returns 202.
Follow runGET /v1/qc-jobs/{job_id}State, stage, units, deadline and permitted actions.
List runsGET /v1/qc-jobs?limit=50Follow next_cursor with before.
Result handoffGET /v1/qc-jobs/{job_id}/resultsReferences to tenant objects; SDK verifies hashes/scope.
CancelPOST /v1/qc-jobs/{job_id}/cancel{} and an idempotency key.
Retry an unsuccessful terminal runPOST /v1/qc-jobs/{job_id}/retries{"deadline_seconds":14400} and an idempotency key.
Usage ledgerGET /v1/usage/runsPeriod totals plus paginated per-job hours.
Viewer accessPOST /v1/qc-jobs/{job_id}/report-accessShort-lived job-scoped viewer grant; see below.
Full schemasGET /openapi.jsonAuthenticated; download through the console.
{
  "asset_ids": ["REGISTERED_ASSET_ID"],
  "specification_id": "REGISTERED_SPECIFICATION_ID",
  "execution_profile": "YOUR_ENROLLED_PROFILE",
  "deadline_seconds": 14400
}

A successful submission means **queued**, not passed QC. Typical states are QUEUED, RUNNING, optionally CANCEL_REQUESTED, then COMPLETED, COMPLETED_WITH_ERRORS, FAILED, CANCELLED or EXPIRED. Read terminal and actions instead of guessing allowed transitions. Worker stages include claiming, planning, evaluating and publishing. Progress units are processing units, not input hours or a reliable time estimate. Poll every 5–15 seconds with jitter and back off on errors. Cold workers take minutes to start. The default four-hour deadline is a maximum job lifetime; it does not promise four-hour completion. Tenant runtime/data-size limits can be smaller, including on the restricted pilot.

Results can exist for a run with errors. Missing/blocked checks do not count as passes. A completed job is not a “good to use” verdict unless the configured acceptance policy and required coverage support that conclusion. Cancellation is cooperative; wait for a terminal state. A cancelled run can already have consumed compute/inference. It does not retract finished work.

Reports, settings and your own application

In the console, choose **Jobs & reports → Open report**. Overview, dimensions, findings, check coverage, evidence and methodology use the same underlying QC output. **Advanced · report settings** controls title, sections, recording/category filters and evidence presentation. Save/load a view configuration or export the configured report as HTML/JSON. Original acceptance, full-run coverage and limitations remain attached to filtered exports. These controls never rerun QC or make model calls.

Your own application may read dataset-report.json through NativeQCClient and render any interface you choose. A console report URL requires an invited user's own sign-in; it is not a public sharing link. An application can obtain a short-lived bearer grant from /report-access and pass it to the returned tenant viewer using its documented postMessage handshake. Pin both the returned viewer origin and iframe window, keep the token in memory, and never put it in a URL, logs or persistent browser storage. Grants expire within an hour and are checked against current account/key permissions on every report request. Browser grants also expire immediately after their source session is logged out. A dedicated tenant service reads reports; the regional control plane stores references and access metadata only.

Usage and billing preparation

GET /v1/usage/runs?since=UNIX_SECONDS&until=UNIX_SECONDS&limit=100 returns summary.first_run, summary.rerun, unmeasured_runs, individual jobs, and next_cursor. Continue with before, preserving the exact since/until. The interval is half-open [since, until) and selects **job submission time in UTC**, up to 366 days. Totals can increase as jobs in that period finish. Each row includes job/root ID, run type, status, measured input hours, measurement time and worker attempt count. Download the entire chosen period as CSV from either console.

Hours currently come from trusted completed engine-duration receipts. Missing duration is **unknown**, including pending/failed/cancelled work without a receipt. Dataset orchestration jobs without duration telemetry are reported separately. Rerun matching uses the same immutable source-manifest set or an explicit retry; changed manifests and overlapping subsets require human review. This is not content-based deduplication. Engine input hours are distinct from wall-clock processing time, per-camera stream-hours and complete check coverage. Establish the contractual duration definition before invoicing.

Oru’el can set customer-specific first-run and rerun prices later. Advances, invoices, currency, taxes, refunds and wallet balances are not implemented by the hour ledger. Do not infer monetary amounts from provider usage endpoints.

Operational behavior and troubleshooting

ResponseMeaning and next step
401Missing, expired or revoked credential. Refresh/replace it.
403Scope, role or configuration denies access. Correct permissions; do not retry unchanged.
404Resource is absent in this organization. Cross-tenant identifiers are never usable.
409Inspect error: result not published, invalid transition or idempotency conflict. An unchanged replay returns the original job; a changed body with the same key is rejected.
422Invalid request/selection/reference. Correct it using the schema. Unknown fields are rejected.
429Rate/queue limit. Honor Retry-After if present and use jittered exponential backoff. Retry the same mutation with its original key.
500, 502, 503, 504, timeoutThe outcome of a write may be uncertain. Retry with the same idempotency key, not a new one. Preserve the response request ID for support.

Regional requests are bounded to 256 KiB and credentials have request-rate, queue and key limits. Do not send raw media to these endpoints. GCS permission failures, changed/deleted source objects, unavailable dependencies/models and runtime limits can prevent execution. Source revision/hash mismatches must be fixed with a new immutable input; retrying unchanged input will not repair them. Report retention follows the enrolled storage lifecycle; export required reports before expiry. Account/key activity records route templates, actors, status and timing, not request bodies, media or report contents.

The older /v1/qc and /v1/dataset-jobs workflow serves separately enrolled dataset orchestration profiles. It is not interchangeable with native Batch execution and is not the recommended start for this deployment. Your onboarding specifies which contract/profile is supported. Native fanout, large-volume turnaround and high availability require separate capacity qualification beyond a successful small sample.