Base URL
Hosted API:Authentication
Send API keys as bearer tokens:Organizations and scope
Your account is an organization, and it is the isolation boundary: projects, sandboxes, runs, and telemetry all live in it. The edge stamps the caller’s organization from their credential, so a request can only ever touch its own organization’s data. Every request acts at one of two scopes:- Organization scope — the default, and where the whole day-to-day surface lives: sandboxes, telemetry, projects, annotations, members, and organization-wide automation.
- Sandbox scope — a per-sandbox credential, further confined to its own run lineage. It can read its own sandbox and snapshot lineage and act only on itself; it cannot create, update, or delete sandboxes, or touch siblings.
hiloop whoami prints your resolved principal (its kind, id, email, and key name)
and organization.
API keys carry a fixed scope from the moment you mint them — mint a key with
the scope it needs.
Deleting a project
DELETE /v1/projects/{id} deletes a project within your organization. By default a project that still has
resources — sandboxes, runs, scoped API keys, or scoped secrets — cannot be deleted:
the call returns a conflict, and you must remove those resources first.
To delete a project and everything in it in one call, set cascade to true. The cascade purges
the project’s supported records, then removes the project. It is scoped to your organization, so it can
only ever touch your own data, and it is irreversible.
What a cascade never does is tear down a sandbox that still exists: delete the project’s remaining
sandboxes first (DELETE /v1/sandboxes/{id} — the normal delete, which tears down the sandbox’s
compute), then cascade.
One guard keeps a cascade honest and refuses the whole call atomically: every sandbox in the
project must already be deleted. While one is not, the call returns a
conflict with error code sandboxes_not_deleted — delete the remaining sandboxes, then retry.
hiloop projects delete <id|slug> (add --cascade for the
cascade; it asks for confirmation unless you pass --yes).
The response reports what the delete actually removed, per resource, so scripts and audit logs can
verify the scope of the purge:
Idempotency
An idempotency key is optional and applies to create-style mutations: create sandbox, snapshot create, exec, and secret rotation. The SDKs generate one automatically. Direct API calls may omit it, but every unkeyed call is a fresh mutation and must not be retried after an ambiguous failure. Pass your own key when you want a retry to be safe across processes: reusing the same key with the same body replays the original result, while reusing it with a different body is rejected withidempotency_conflict (HTTP 409) — a key names one logical request, never a family of them.
The hiloop CLI takes the same key as --idempotency-key on these commands, and a key turns on
automatic retries for the request itself: an ambiguous failure — a timeout, a dropped connection,
a 5xx — is retried up to 3 times with the same key before the error surfaces. Without a key the
CLI never retries a mutation, because each attempt would be a fresh one.
Delete and the stop/start lifecycle transitions need no key: they are idempotent by sandbox id, so
repeating one converges on the same desired state rather than stacking up work.
To pass your own key, send it in the idempotency-key header:
Asynchronous state
Sandbox mutations are asynchronous, but there is no separate operation resource to poll. A create, update, or delete returns as soon as the request is accepted, and you poll the sandbox itself until its observedstate reaches the outcome you asked for:
requested, reserved, materializing, ready, running, stopped,
terminating, failed, terminated, quarantined, and attention. The state you read is
evidence of what the runtime is doing, not a record of what was asked for. A sandbox that reached
failed or quarantined carries a state_reason explaining why; lifecycle states that need no
explanation omit it.
The CLI polls for you: hiloop sandbox create returns once the sandbox is running.
Resource identifiers
Resource IDs are opaque. Do not parse them for meaning. Recommended application state:Runtime endpoints
The sandbox surface is nine routes over two resources, sandboxes and snapshots:
There is no capability-discovery route. A deployment states what it cannot serve by refusing the
request that needs it, with
unsupported_capability; see
resources and capabilities.
Retry strategy
Rate limits and quotas
Per-organization limits are checked when a request is submitted. A request over a limit is rejected immediately with HTTP 429 and a structured body naming the limit — work is never accepted and then failed later for capacity reasons.code, never on the message:
Every quota rejection uses the one
quota_exceeded code, whichever limit it was: read
details.quota.metric to tell them apart, and a limit added later needs no new code to branch on.
details.quota also carries the configured limit, the observed current usage (concurrency and
storage caps only), and retry_after_seconds (rate limits only).
Limited metrics: