Documentation

Overview

Use the service

Billing

Reference

Reference

POST /jobs

Submit an analytical job: a container image, a command and the resources it may use.

Syntax

POST https://grid-lab.zyxio.xyz/jobs
x-api-key: <key>
content-type: application/json

{"image": "<image>", "command": [...], "args": [...], "resources": {...}, "runningDeadlineSeconds": <s>,
 "retries": <n>, "priority": <n>, "capabilities": {"networkProfile": "none"}, "env": {}, "labels": {},
 "idempotencyKey": "<your key>"}

Request

NameWhereRequiredMeaning
x-api-keyheaderyes, or AuthorizationYour API key, or Authorization: Bearer <token> from Zyxio sign-in.
imagebodyyesA tag or digest in a repository admitted on registry.grid.zyxio.xyz. It must have a linux/amd64 image.
commandbodyyes1 to 128 strings; replaces the image's entry point.
argsbodynoUp to 128 strings. Default [].
resourcesbodyyescpu, memory and ephemeralStorage, each with request and limit (request no more than limit). CPU 250m to 8; memory 256Mi to 16Gi; scratch 256Mi to 32Gi.
runningDeadlineSecondsbodyyes1 to 21,600: the longest one attempt may run.
retriesbodyno0 to 3 automatic replays of an attempt we lose because the machine it ran on ran short of resources (PLATFORM_EVICTED). An attempt that ends for any other reason is final; retry it yourself with POST /jobs/{jobId}/retry. Default 0.
prioritybodyno0 to 10; higher runs sooner. Default 0.
capabilitiesbodyyes{"networkProfile": "none"} or {"networkProfile": "public-https"}.
envbodyyesUp to 100 variables; names like MY_VAR. Names starting AWS_, AZURE_, BROWSERGRID_, COMPUTE_ or GOOGLE_, and the system names HOME, HOSTNAME, PATH, KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT, are reserved.
labelsbodyyesUp to 20 lower-case key and value pairs.
idempotencyKeybodyyes1 to 128 characters. The same key with the same body returns the existing job.

Any other field is refused; fields for capabilities that are not offered yet are refused with 422.

Response

202 Accepted with the new job's record, phase: "ACCEPTED". 200 OK with the existing record when you resend an idempotencyKey with the same body. The record's fields are on GET /jobs/{jobId}.

Errors

StatusBodyWhenWhat to do
400{"error": "INVALID_JOB_REQUEST"}A field is missing, out of bounds or unknown.Fix the body.
400{"error": "INVALID_IMAGE"}The image is not in an admitted repository, does not exist, or has no linux/amd64 image.Use an admitted image.
401{"error": "unauthorized"}No credential, or a key that is revoked, expired, wrong, or of a suspended account.Send a valid key.
503{"error": "accounting_unavailable"}Your key or Zyxio sign-in could not be checked because the account database did not answer in time. Nothing was done.Retry shortly; the same request is safe to resend.
402{"error": "insufficient_credit", "requiredMicros": ..., "availableMicros": ...}Your account is metered, credit enforcement is on, and the job's reservation exceeds your available credit (with monthly invoicing: what your monthly limit and the unpaid-usage ceiling leave; nothing while invoicing is paused or an invoice is past due).Top up, raise your monthly limit or pay the past-due invoice, or ask for less time or smaller resources.
402{"error": "daily_cap_exceeded", ...}The key's daily cap would be exceeded.Raise the cap, or wait for 00:00 UTC.
403{"error": "forbidden"}A valid Zyxio sign-in token whose identity has no account here, or whose account is suspended.Accept your invitation first, or use a key.
403{"error": "account_suspended"}Credit enforcement is on and the account a Zyxio-internal credential is billed to is suspended. Nothing was admitted. (A suspended customer's own keys and sign-in are refused before this, with 401 and 403 forbidden.)Ask Zyxio.
409{"error": "IDEMPOTENCY_CONFLICT"}You reused an idempotencyKey with a different body.Use a new key for a new job.
422{"error": "CAPABILITY_NOT_AVAILABLE", "capability": "..."}You asked for a capability that is not offered yet.Leave the field out.
503{"error": "COMPUTE_UNAVAILABLE"}Job tracking is not ready, or a dependency did not answer in time. Nothing was admitted.Retry after the retry-after seconds with the same idempotencyKey.

Example

curl -s https://grid-lab.zyxio.xyz/jobs \
  -H "x-api-key: $BROWSERGRID_API_KEY" \
  -H "content-type: application/json" \
  -d '{"image": "registry.grid.zyxio.xyz/<your-repository>:<tag>",
       "command": ["python", "-c", "print(6 * 7)"],
       "resources": {"cpu": {"request": "2", "limit": "2"}, "memory": {"request": "4Gi", "limit": "4Gi"},
                     "ephemeralStorage": {"request": "256Mi", "limit": "1Gi"}},
       "runningDeadlineSeconds": 3600, "retries": 1,
       "capabilities": {"networkProfile": "none"}, "env": {}, "labels": {"run": "demo"},
       "idempotencyKey": "demo-2026-10-10-1"}'
{
  "jobId": "cj_0123456789abcdef0123456789abcdef",
  "attempt": 0,
  "imageDigest": "registry.grid.zyxio.xyz/<your-repository>@sha256:<digest>",
  "phase": "ACCEPTED",
  "phaseTimestamps": {"ACCEPTED": "2026-10-10T12:00:00.000Z"},
  "executor": null,
  "attempts": [],
  "termination": null,
  "logsTruncated": false,
  "logs": {"available": false, "artifactId": null, "byteLength": null, "contentType": null},
  "artifacts": []
}

Billing

At submission the job reserves one attempt's longest cost, on the CPU and memory you request: (vCPU × €0.04 + GiB × €0.0064) per hour × runningDeadlineSeconds, whatever retries you set. The example reserves (2 × 40,000 + 4 × 6,400) µ€ × 1 hour = 105,600 µ€ (€0.1056).

One attempt is all a submission can be billed for: a replay follows only an eviction, which is free, and every billed reason ends the job. So the attempts before the billed one leave the reservation untouched, the billed one is charged against it, and what it does not use returns to your available credit when the job finishes. retries changes neither what is held nor what the job can cost.

Each attempt is charged for the time from its container's start until it finishes, up to runningDeadlineSeconds, rounded once to the micro-euro, when its termination.reason is one you caused: WORKLOAD_SUCCEEDED, WORKLOAD_FAILED, PLATFORM_OOM (your container went over its own memory limit), RUNNING_DEADLINE_EXCEEDED (your own deadline) or CANCELLED. Every other reason is a failure on our side and free, and so are queueing, start-up and our replays. Resending the same idempotencyKey reserves nothing. No attempt is ever charged more than the reservation set aside for it. Attempts are settled by a periodic pass over the grid's records, so a charge, and the return of what the job did not use to your available credit, appears up to one settlement interval (30 seconds) after the attempt or the job finishes.

See also

Analytical jobs, GET /jobs/{jobId}, GET /jobs/{jobId}/logs, POST /jobs/{jobId}/cancel.