Jobs and the API

Jobs and the API. The Hangar API lets a program start jobs, follow them and download the results. Each job that a request starts uses your prepaid credit, and each request key has its own spend limit.

The OpenAPI document docs/api/openapi.json lists every route, request and answer. docs/api/errors.json lists the three parts of every error (what failed, the next step and what to do if that fails) and says whether a client may retry the request. Every error body also contains reference, the id of the request. When support is the next step, the third part of the error shows reference.

Three pages go further. Releases and jobs explains packages, releases, channels, the envelope and the return. Pools explains where a job executes, and the customer-controlled form. The Hangar SDK explains request keys, tenants and the Python package gethangar.

Calling the API

Jobs

A job is one container command inside a booking. hangar run submits one job. A booking can contain several jobs. The jobs of a booking use one instance, in the order of their seq numbers.

CallWhat it does
POST /v1/slots/{id}/jobsSubmits a job into your confirmed booking.
GET /v1/jobs?limit=&cursor=&status=Lists every job in your organisation, newest first, 50 to a page by default and at most 100. Pass next_cursor as cursor for the next page.
GET /v1/slots/{id}/jobsLists the jobs in one booking, in order.
GET /v1/jobs/{id}Gets one job: the image and digest, the command, the state, the times the job was submitted, started and ended, the exit code (after the job finishes), the time Hangar signed the certificate, and the position of the job.
POST /v1/jobs/{id}/cancelCancels a job that has not started.

Jobs started by a request key

A request key with the jobs capability starts a GPU now, as a person does. A CI job or an agent can start a GPU with no person signed in.

CallWhat a jobs key may do
GET /v1/instant, POST /v1/instantRead what can start now, and start an H100, a Trainium2, an L4 or a fractional L4.
GET /v1/instant/{id}, POST /v1/instant/{id}/stopRead a session, and stop any session of your organisation, whoever started it.
GET /v1/jobs, GET /v1/jobs/{id}, /logs, /outputs, /events, /certificateRead the jobs of your organisation: the position, logs, outputs and certificate of each job.
GET /v1/slots, GET /v1/slots/{id}, /jobs, /certificate, GET /v1/certificates/{id}Read the bookings and sessions of your organisation: the jobs and certificates of each.
POST /v1/objects/{digest}/download, GET /v1/objects/{digest}/contentFetch an output that a job of your organisation wrote. Any other object needs uploads.

The rules:

Images pushed by a request key

A request key with the uploads capability sends the image that the jobs of the key use. A CI job can then build, send and start with no person signed in.

CallWhat an uploads key may do
POST /v1/images/pushGet a 15-minute credential to push one repository to your organisation's registry in Sydney. The CLI then sends the layers and the manifest to /v2/ with that credential.
POST /v1/images/push/complete, POST /v1/images/{name}/tagGive the pushed manifest its tag, and point another tag at a digest that you hold.
POST /v1/images/pullRegister a one-time pull of a public image by its digest.
GET /v1/images, GET /v1/images/resolveList your images and resolve a name and tag to a digest. A jobs key reads these too.

The rules:

Uploads

hangar upload PATH and the Python package send a file in chunks. Each chunk is checked, sealed under the file's own key and stored in Sydney. Hangar then checks the digest of the whole file and stores the file once.

CallWhat it does
POST /v1/uploadsBegins an upload. The body gives size_bytes and the sha384: digest of the whole file. The answer gives upload, chunk_bytes and chunk_count.
PUT /v1/uploads/{id}/chunks/{n}Sends chunk n (from 0), with its own digest in Hangar-Chunk-Digest.
POST /v1/uploads/{id}/completeAsks Hangar to check the whole digest and store the file.
GET /v1/uploads/{id}Gets the state of the upload and, when the file is stored, the object.

The chunk size is per upload. The size is 8 MiB while a file needs at most 9,000 chunks of 8 MiB (70.3 GiB). A larger file gets larger chunks, in whole MiB, so the file stays at 9,000 chunks or fewer: 43 MiB for 400 GB, and 59 MiB for 512 GiB. Use the chunk_bytes that POST /v1/uploads gives.

Hangar adds each chunk to the digest of the whole file as the chunk arrives in order. When the chunks arrive out of order, the chunk that fills a gap adds the chunks after the gap. So when you complete the upload, Hangar has usually checked every byte already.

POST /v1/uploads/{id}/complete answers in one of these ways:

GET /v1/uploads/{id} gives:

FieldWhat it is
idThe upload.
statusopen, completing, done or failed.
completion_statequeued, checking, composing, done or failed, or null before you complete.
chunks_total, chunks_hashedThe chunks of the file, and the chunks that the digest covers so far.
resultWhen done: the object, the same body as the 201 of complete, with received_record.
errorWhen failed: an error body with code, sentence, next_step, if_that_fails and reference.

The errors at the end:

A person, or a request key with uploads, calls these routes. A key that belongs to a tenant sees the uploads of its tenant only. The upload of another organisation or another tenant is upload_not_found. The movement record of the receipt names the person or the key that completed the upload.

Jobs of a release

A job of a release runs a vendor's accepted application release for one tenant, on the CPU pool hosted-cpu-syd. Before the job, TALOS Warrant (the part of Hangar that decides what a job may do) compiles the envelope, the set of limits that the job cannot leave. hangar run --release or hangar run --package --channel starts the job. hangar status, hangar logs, hangar pull, hangar stop and hangar verify work on a job of a release as they work on any job. The Releases and jobs page explains the whole contract.

CallWhat it does
POST /v1/release-jobsStarts a job of a release, with the release id or a package and channel, the tenant, the inputs, an optional narrowing and your client_ref.
GET /v1/release-jobs?tenant=&release=&state=&prefix=&limit=&cursor=Lists your jobs of releases, newest first.
GET /v1/release-jobs/{id}Gets one job: the release as resolved, the tenant, the pool, the state and outcome, the compiled envelope, each attempt, the inputs and the artefacts.
GET /v1/release-jobs/{id}/events?after=&wait=Gives the events of the job after an offset, as newline-delimited JSON. The call waits up to 15 seconds for the next event.
POST /v1/release-jobs/{id}/cancelCancels the job. Cancellation is final.
GET /v1/release-jobs/{id}/artefactsLists the artefacts of the job, each with a content link.
GET /v1/release-jobs/{id}/returnGets the return of the job, as CBOR. The return is the job certificate of the release.

Following a job

GET /v1/jobs/{id}/events?after=&wait= follows a job as it prepares and runs. Each answer gives the position of the job now and the events since your last call:

The position shows the phase of the job, the preparation step and the elapsed time. It also shows what the worker reports:

GET /v1/jobs/{id} shows the same parts in position, with exit_code: 0 for a job that finished by itself, and the code of the process for a job that ended with another code or was stopped. certificate_signed is the time Hangar signed the certificate of the booking. That certificate covers the job.

Pass next from the answer as after in the next call. With wait (up to 25 seconds), Hangar delays the answer until new data exists or the job ends. When complete is true, the job has ended and you have the whole log.

Logs and outputs

Hangar stores each log chunk in Sydney, sealed under the key of the job.

Certificates

Every booking ends with a job certificate, signed by Hangar and anchored in the public log. One certificate covers every job in the booking.

CallWhat it does
GET /v1/certificates?kind=&limit=&cursor=Lists every certificate that your organisation holds, newest first. Each entry shows the kind (slot, sandbox_session, data or release_run), the booking or session, the jobs that the certificate covers and the public page.
GET /v1/certificates/{id}Gets the certificate, as CBOR.
GET /v1/jobs/{id}/certificateGets the certificate of the booking of the job.
GET /v1/certificates/{id}/reportGets the report of the verifier on the certificate: the verdict, each check and the facts.

The report comes from the same verifier as hangar verify --json. The verifier checks the certificate bytes against the published key set and tree heads. To check a certificate yourself, download the certificate and run the offline verifier. The offline verifier uses only the file and the published keys.

Each certificate has a public page at {public_origin}/c/{page_key}. The list shows the address as page. The download of a stored certificate shows the address in the hangar-certificate-url header. The page key is 32 hexadecimal characters, chosen at random when Hangar signs the certificate. The link is the permission. Anyone who has the link can read the certificate without a sign-in. To show a certificate to an assessor, give the assessor the link.

CallWhat it does
GET /v1/public/certificates/{page_key}Gets the certificate that the link points to, as CBOR. The bytes equal the bytes from GET /v1/certificates/{id}.
GET /v1/public/certificates/{page_key}/reportGets the report of the verifier on the certificate. The JSON equals the JSON from GET /v1/certificates/{id}/report.

These two routes find a certificate only by the page key, never by the id. A page key that matches no certificate gets not_found. Each answer has the headers Cache-Control: private, no-store and X-Robots-Tag: noindex. No shared cache keeps a copy, and no search engine lists the certificate.

Your account

CallWhat it does
GET /v1/meThe signed-in person, the role of that person, and the legal name and ABN or ACN of the organisation.
GET /v1/passkeysYour passkeys: the label of each passkey, and when you added it and last used it.
DELETE /v1/passkeys/{id}Removes one of your passkeys. You must keep at least one passkey, so you can always sign in.
POST /v1/passkeys/add/start, POST /v1/passkeys/add/finishAdds another passkey, such as a phone beside a hardware key. Add it within 15 minutes of signing in with the browser. With two passkeys, losing one device does not lock you out.
GET /v1/sessionsYour signed-in sessions, with the client of each session. One entry shows the session that you use now.
POST /v1/sessions/{id}/revokeEnds a session. You can end your own session. An owner can end any session in the organisation, for example after a lost laptop.
GET /v1/organisation/membersThe people in your organisation, the role of each person and whether the person has a passkey.
POST /v1/organisation/invitationsAn owner invites a person with the email, name and role of the person. Hangar emails the address. The answer is "Invitation sent" for every address. The person signs in at gethangar.au/login with the address, gets a code, and creates a passkey within seven days. When you invite the same address again, Hangar opens a new invitation and closes the old invitation.
POST /v1/organisation/members/{user}/resetAn owner resets a member who lost the passkeys of the member. Every passkey and session of the member ends, and a new invitation opens. The member signs in at gethangar.au/login and creates a new passkey. Every owner and the member get an email. An owner cannot use this route on the account of that owner. TALOS Defence support recovers the last owner.
GET /v1/organisation/recoveries, POST /v1/organisation/recoveries/{id}/cancelThe open recovery cases that TALOS Defence support started for a person in your organisation, and the cancellation of a case. Any member can cancel a recovery case during the 72-hour wait.
GET /v1/organisation/sealThe mode of the organisation: standard, or sealed. In a sealed organisation, TALOS Defence support cannot recover the accounts, and the owners hold a recovery kit instead. Hangar cannot help you recover a sealed organisation.
POST /v1/organisation/seal/requests, .../{id}/approve/start, .../{id}/approve/finish, .../{id}/cancelAn owner asks to seal or unseal the organisation. Every owner approves with a passkey. The last approval makes the change, and Hangar emails every member. Every owner needs two passkeys while the organisation is sealed. With two or more owners, the kit has three shares, and any two shares recover an owner. With one owner, the kit is one code, and the organisation gets only that code.
GET /v1/organisation/seal/shares, POST /v1/organisation/seal/shares/{id}/storedYour shares of the kit. Each share is sealed to a key that your browser made, so Hangar stores no share that Hangar can read. When you confirm that you stored a share, Hangar removes the copy of the share. Hangar shows a share for 24 hours after Hangar makes the share, and no longer.
POST /v1/auth/login/kitAfter the code at gethangar.au/login, an owner of a sealed organisation presents two shares, or the single code, and creates a new passkey. Every earlier passkey of that owner ends. A split kit that opened a recovery is spent. The shares of a spent kit open nothing again, and the organisation stays sealed. GET /v1/organisation/seal shows kit_reissue_due until the owners approve a new kit with a seal request. kit_reissue_due also shows when an owner did not collect a share within 24 hours. A new kit voids every share of the old kit.
POST /v1/organisation/wipeAn owner asks Hangar to wipe and close the organisation. The owner types the legal name of the organisation and must have signed in within the last 15 minutes. Hangar answers 202 with wipe: processing and the message that every wipe shows: "We are processing this. It may take up to 7 days. We will notify you when it is complete." Hangar emails the owners when the wipe is complete. Hangar keeps the tax invoices and the payment ledger, which the ATO requires for five years, the legal name and ABN on those records, and the record of the wipe. Hangar removes everything else: stored files, outputs, images, job logs, secrets, keys, passkeys, and the name and address of each person. Hangar returns the credit that is left to the card that paid for the credit.

Status and open nights

These two routes need no sign-in.

Records

Every change that you make through the API becomes a signed record in the record chain of your organisation, before Hangar changes a row in the database. A removed passkey, an ended session and an invitation are records too.

Read this page as Markdown