# Jean documentation > A metered API for scoring models of human behaviour against held-out human data. Every page of https://jeantechnologies.com/docs, in reading order: the guides first, then the API reference. The API pages are generated from the contract the API publishes (version 0.2.0); the contract itself is at https://jeantechnologies.com/docs/openapi.json. ## Contents - [What Jean does](https://jeantechnologies.com/docs/): A metered API for scoring models of human behaviour against held-out human data. - [Quickstart](https://jeantechnologies.com/docs/quickstart): From no account to a scored eval, in five commands. - [Evals](https://jeantechnologies.com/docs/evals): What a suite is, what the score means, and how a result is pinned to a version. - [API overview](https://jeantechnologies.com/docs/api/overview): Base URL, credentials, errors, limits and idempotency for the Jean Platform API. - [Liveness](https://jeantechnologies.com/docs/api/get-health): Liveness — Jean Platform API reference. - [Who am I](https://jeantechnologies.com/docs/api/get-me): Who am I — Jean Platform API reference. - [List API keys](https://jeantechnologies.com/docs/api/list-keys): List API keys — Jean Platform API reference. - [Create an API key (shown once)](https://jeantechnologies.com/docs/api/create-key): Create an API key (shown once) — Jean Platform API reference. - [Revoke an API key (rows are never deleted)](https://jeantechnologies.com/docs/api/revoke-key): Revoke an API key (rows are never deleted) — Jean Platform API reference. - [List suites](https://jeantechnologies.com/docs/api/list-suites): List suites — Jean Platform API reference. - [Submit predictions for scoring](https://jeantechnologies.com/docs/api/submit-eval): Submit predictions for scoring — Jean Platform API reference. - [List jobs, newest first](https://jeantechnologies.com/docs/api/list-jobs): List jobs, newest first — Jean Platform API reference. - [Get a job](https://jeantechnologies.com/docs/api/get-job): Get a job — Jean Platform API reference. - [Cancel a queued job](https://jeantechnologies.com/docs/api/cancel-job): Cancel a queued job — Jean Platform API reference. - [Fetch trace.json through the API](https://jeantechnologies.com/docs/api/get-job-trace): Fetch trace.json through the API — Jean Platform API reference. - [Usage this period](https://jeantechnologies.com/docs/api/get-usage): Usage this period — Jean Platform API reference. - [List org members](https://jeantechnologies.com/docs/api/list-members): List org members — Jean Platform API reference. - [Promote or demote a member](https://jeantechnologies.com/docs/api/set-member-role): Promote or demote a member — Jean Platform API reference. - [Remove a member from the org](https://jeantechnologies.com/docs/api/remove-member): Remove a member from the org — Jean Platform API reference. - [List invites](https://jeantechnologies.com/docs/api/list-invites): List invites — Jean Platform API reference. - [Invite a teammate by email](https://jeantechnologies.com/docs/api/create-invite): Invite a teammate by email — Jean Platform API reference. - [Revoke an invite](https://jeantechnologies.com/docs/api/revoke-invite): Revoke an invite — Jean Platform API reference. - [List claimed domains](https://jeantechnologies.com/docs/api/list-domains): List claimed domains — Jean Platform API reference. - [Claim an email domain](https://jeantechnologies.com/docs/api/claim-domain): Claim an email domain — Jean Platform API reference. - [Release a claimed domain](https://jeantechnologies.com/docs/api/release-domain): Release a claimed domain — Jean Platform API reference. - [The org's audit log](https://jeantechnologies.com/docs/api/list-audit-events): The org's audit log — Jean Platform API reference. - [Terms status](https://jeantechnologies.com/docs/api/get-terms): Terms status — Jean Platform API reference. - [Accept the current terms and set the org's data-use choice](https://jeantechnologies.com/docs/api/accept-terms): Accept the current terms and set the org's data-use choice — Jean Platform API reference. - [Reserve an upload and get a PUT URL](https://jeantechnologies.com/docs/api/create-upload): Reserve an upload and get a PUT URL — Jean Platform API reference. - [Upload bytes through the API (local artifact backend only)](https://jeantechnologies.com/docs/api/put-upload-bytes): Upload bytes through the API (local artifact backend only) — Jean Platform API reference. ============================================================================== # What Jean does Source: https://jeantechnologies.com/docs/ Summary: A metered API for scoring models of human behaviour against held-out human data. Docs Model humans. Jean scores a model of human behaviour against what people actually did. You send predictions for the items in a suite; Jean compares them to held-out human data it holds and never shows you, and returns a number, the count it was computed over, and a trace of how it got there. Everything runs through one API. Sign in, create a key, submit, poll, read the score. There is no SDK to install and no onboarding call to book. Quickstart From no account to a score, in five curl commands. Evals What a suite is, what the number means, and how versions are pinned. API reference Authentication, errors, limits, and every endpoint. OpenAPI The contract itself. These pages are generated from it. ## What it is not It is not a model host. Jean does not run your model, and it never sees it — you run it wherever it lives and send the predictions. It is not a dataset download either: the reference answers stay on our side, which is the only thing that makes a score mean anything. ## Where the data comes from Jean also sources the behavioural data underneath the suites: collected, structured to one schema, and delivered with a fidelity report and rights written for foundation models. That part is arranged directly with the team. [Talk to us about data](https://jeantechnologies.com/data). ============================================================================== # Quickstart Source: https://jeantechnologies.com/docs/quickstart Summary: From no account to a scored eval, in five commands. Five steps. The only thing you need first is a browser. ## 1. Get a key Sign in at [jeantechnologies.com/dashboard](https://www.jeantechnologies.com/dashboard) with Google or an email link. You get an organisation of your own on first sign-in, and every key, job and score below belongs to it. Create a key in the dashboard and copy it. It is shown once and never again; if you lose it, revoke it and make another. ```bash export JEAN_API_KEY="jean_live_..." ``` Keys are created from the dashboard, not from a key. An API key cannot mint another API key, so a leaked key cannot be used to grow itself a longer life. ## 2. See what you can be scored against ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/suites" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` Each suite names a metric, how many items it holds, and whether it returns per-item feedback. [More about suites](https://jeantechnologies.com/docs/evals). ## 3. Submit predictions One prediction per item, with the item id the suite gave you. Send an `Idempotency-Key` and a retry after a timeout returns the original job instead of queueing a second one. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/evals" \ -H "Authorization: Bearer $JEAN_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{ "suite_id": "suite:smoke-v1", "label": "first try", "predictions": [ {"item_id": "item-00", "prediction": "whatever your model said"}, {"item_id": "item-01", "prediction": "whatever your model said"} ] }' ``` You get back a job with `"status": "queued"`. Scoring happens on a worker, not in your request. Those two predictions will score zero, which is the point: the number comes from comparing what you sent to data you do not have. ## 4. Poll the job ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/jobs/$JOB_ID" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` `queued → running → succeeded`, or `failed` with an `error`, or `cancelled` if you cancel it. Poll every couple of seconds. A first submission after a quiet period waits a few seconds longer while the worker starts. A succeeded job carries a `result`: the metric, the value, how many items were scored, and how many you sent that the suite did not recognise. If the suite allows it, `per_item` says which items you got right — never what the right answer was. ## 5. Read the trace ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/jobs/$JOB_ID/trace" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` Every job records what ran, in what order, and how long each step took, so a number you disagree with can be argued about with evidence. ## Then - Check what you have used with [`GET /v1/usage`](https://jeantechnologies.com/docs/api/get-usage). Free accounts get 20,000 eval items a month, two jobs at a time, and 60 requests a minute. - [Invite your team](https://jeantechnologies.com/docs/api/create-invite), or [claim your email domain](https://jeantechnologies.com/docs/api/claim-domain) so colleagues land in your organisation instead of making their own. - Read the [API overview](https://jeantechnologies.com/docs/api/overview) for errors, limits and idempotency in full. ============================================================================== # Evals Source: https://jeantechnologies.com/docs/evals Summary: What a suite is, what the score means, and how a result is pinned to a version. An eval is a comparison. A suite holds items and the reference answers people actually gave; you send a prediction per item; Jean scores yours against theirs and keeps the answers. ## Suites [`GET /v1/suites`](https://jeantechnologies.com/docs/api/list-suites) lists the ones your organisation may submit to. Each says: | Field | What it tells you | | --- | --- | | `suite_id` | What to pass as `suite_id` when submitting. | | `version` | Bumped whenever the items or the reference answers change. | | `metric` | What the score measures — `accuracy`, `recall@10`, and so on. | | `n_items` | How many items the suite holds. | | `per_item_feedback` | Whether a result may say which items you got right. | | `hfm_sha` | The scorer commit that will produce your number. | ## Held-out suites On a held-out suite, a result gives you the aggregate number and nothing else: no `per_item` array, and never a reference answer. That is not a limitation to work around — it is the only reason the score is worth quoting. A suite you can read the answers to measures nothing. On the suites that do allow per-item feedback, you get `{"item_id": ..., "correct": true}` per item. Still no answers. ## What the number means A result carries `value`, the metric it is in, and the counts behind it: - `n` — items actually scored, meaning the ones your submission matched. - `n_submitted` — how many predictions you sent. - `n_unmatched` — predictions for items the suite does not contain. If `n` is smaller than `n_items`, you did not answer the whole suite, and the value covers only what you answered. Compare two runs only when `n` and `suite_version` agree. ## Versions Every result is stamped with `hfm_sha`, the exact scorer commit that computed it, and with `suite_id` and `suite_version`. Two numbers are comparable when all three match and not otherwise. A result that reads `hfm_sha: "unpinned"` came from the placeholder scorer that exists so the job path can be exercised end to end; it is a number, but it is not a measurement. ## Limits Submissions are metered per organisation, per calendar month. | Plan | Jobs at once | Eval items a month | Requests a minute | | --- | --- | --- | --- | | Free | 2 | 20,000 | 60 | | Dev | 5 | 200,000 | 300 | | Team | 20 | 2,000,000 | 1,000 | [`GET /v1/usage`](https://jeantechnologies.com/docs/api/get-usage) reports where you are against them. Going over returns `429` with `error.details` naming which limit and when it resets. Inline predictions are capped at 5 MB of JSON per request. Beyond that, [reserve an upload](https://jeantechnologies.com/docs/api/create-upload), PUT the bytes, and submit with `input_ref` instead. ## The public board Industry results are published separately, on the [user simulation leaderboard](https://huggingface.co/spaces/jean-technologies/user-simulation-leaderboard). Ask us if you want your system run against it. ============================================================================== # API overview Source: https://jeantechnologies.com/docs/api/overview Summary: Base URL, credentials, errors, limits and idempotency for the Jean Platform API. JSON over HTTPS. One base URL, one bearer header, one error shape. ``` https://api-833252724876.us-central1.run.app ``` These pages are generated from the contract the API publishes at build time, so they describe the deployment that is running right now. [Download it](https://jeantechnologies.com/docs/openapi.json). ## Credentials ```http Authorization: Bearer jean_live_... Content-Type: application/json ``` Two kinds of bearer token are accepted, and each page says which it needs. - **An API key** — `jean_live_…`, created in the dashboard, for everything your code does: submitting evals, reading jobs, checking usage. - **A session token** — issued to a signed-in browser, for the things a human does: creating and revoking keys, inviting people, claiming a domain, accepting terms. An API key is refused on these, so a leaked key cannot mint itself a successor or change who has access. Keys are scoped to one organisation. Nothing belonging to another organisation is reachable with yours, and a resource you may not see returns `404` rather than admitting it exists. ## Requests Every response carries `X-Request-Id`. Keep it; it is the fastest way for us to find what happened, and it appears inside the error body too. Send an `Idempotency-Key` when you submit an eval. Repeating the same key returns the original job instead of queueing a second one, which makes a retry after a timeout safe. List endpoints take `limit` and a cursor — `GET /v1/jobs` returns `next_before`; pass it back as `before` for the next page. Its absence means you have reached the end. ## Jobs Anything that takes real work returns `202` and a job rather than blocking your request. Poll [`GET /v1/jobs/{job_id}`](https://jeantechnologies.com/docs/api/get-job): `queued → running → succeeded | failed`, or `cancelled` if you cancel it first. A succeeded job carries a typed `result`; a failed one carries an `error` with a code and a message. Every job also has a [trace](https://jeantechnologies.com/docs/api/get-job-trace) once it has run. Poll every couple of seconds. An eval job is given fifteen minutes before it is considered stuck, and is retried up to three times. ## Errors Every non-2xx response, validation failures included, has the same body: ```json { "error": { "code": "quota_exceeded", "message": "this submission would bring eval_items to 21000 this month; the free plan allows 20000.", "request_id": "req_z9x8c7v6b5n4m3l2", "details": {"limit": "eval_items_per_month", "max": 20000, "resets_at": "2026-02-01T00:00:00Z"} } } ``` `code` is from a closed set, so it is safe to branch on. `message` is for a human and may change. `details` is present when there is something specific to say. | Code | Status | What to do | | --- | --- | --- | | `invalid_request` | 400 | Fix the request. | | `validation_failed` | 422 | A field is missing or the wrong type; `details` says which. | | `payload_too_large` | 413 | Over 5 MB inline — use an upload and `input_ref`. | | `unauthenticated` | 401 | No credential was supplied. | | `invalid_token` | 401 | The key or session token is not valid. | | `key_revoked` | 401 | This key was revoked. Create another. | | `forbidden` | 403 | Valid credential, not allowed to do this. | | `session_required` | 403 | This route needs a signed-in session, not an API key. | | `org_required` | 403 | The credential resolves to no organisation. | | `not_found` | 404 | No such resource in your organisation. | | `conflict` | 409 | It already exists. | | `invalid_state` | 409 | Not a legal transition — cancelling a finished job, for instance. | | `quota_exceeded` | 429 | A plan limit. `details` names it and when it resets. | | `rate_limited` | 429 | Too many requests this minute. Honour `Retry-After`. | | `internal` | 500 | Ours. Retry with the same idempotency key, and quote `request_id`. | | `unavailable` | 503 | Retry with backoff. | ## Rate limits Counted per organisation, per minute: 60 requests on free, 300 on dev, 1,000 on team. Every response tells you where you stand. ```http X-RateLimit-Limit: 60 X-RateLimit-Remaining: 41 X-RateLimit-Reset: 1768470000 Retry-After: 18 ``` `Retry-After` appears on `429`. Honour it rather than retrying immediately; repeated failed authentication is throttled separately and more harshly. ## Versions The contract is versioned in `info.version`, and `info.x-git-sha` names the exact build serving it. Additions — a new endpoint, a new optional field — happen without a version change; anything that could break a client does not happen silently. ============================================================================== # Liveness Source: https://jeantechnologies.com/docs/api/get-health Summary: Liveness — Jean Platform API reference. `GET /health` Liveness **Credential.** None. This endpoint is open. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/health" ``` ## Response · 200 ```json { "git_sha": "24cea6f1ac37", "hfm_sha": "9f2c1ab4d7e0", "env": "prod" } ``` [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Who am I Source: https://jeantechnologies.com/docs/api/get-me Summary: Who am I — Jean Platform API reference. `GET /v1/me` Who am I **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/me" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Response · 200 ```json { "principal": "session", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "orgs": [ { "id": "org_k3j2h4g5f6d7s8a9q0w1", "name": "Acme", "plan": "free", "data_use": "scoring_only", "role": "owner", "created_at": "2026-01-15T09:30:00Z" } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # List API keys Source: https://jeantechnologies.com/docs/api/list-keys Summary: List API keys — Jean Platform API reference. `GET /v1/keys` List API keys **Credential.** A dashboard session token only. An API key cannot call this — a key must never be able to mint another key. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/keys" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Response · 200 ```json { "keys": [ { "id": "key_a1b2c3d4e5f6g7h8i9j0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "name": "ci", "prefix": "jean_live_exam", "created_by": "usr_b2c3d4e5f6g7h8i9j0k1", "created_at": "2026-01-15T09:30:00Z", "last_used_at": null, "revoked_at": null } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Create an API key (shown once) Source: https://jeantechnologies.com/docs/api/create-key Summary: Create an API key (shown once) — Jean Platform API reference. `POST /v1/keys` Create an API key (shown once) **Credential.** A dashboard session token only. An API key cannot call this — a key must never be able to mint another key. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/keys" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "ci" }' ``` ## Body | Field | Type | Required | Notes | | --- | --- | --- | --- | | `name` | string | yes | Length 1–80. | ## Response · 201 ```json { "id": "key_a1b2c3d4e5f6g7h8i9j0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "name": "ci", "prefix": "jean_live_exam", "created_by": "usr_b2c3d4e5f6g7h8i9j0k1", "created_at": "2026-01-15T09:30:00Z", "last_used_at": null, "revoked_at": null, "key": "jean_live_exampleexampleexampleexample0000" } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Revoke an API key (rows are never deleted) Source: https://jeantechnologies.com/docs/api/revoke-key Summary: Revoke an API key (rows are never deleted) — Jean Platform API reference. `DELETE /v1/keys/{key_id}` Revoke an API key (rows are never deleted) **Credential.** A dashboard session token only. An API key cannot call this — a key must never be able to mint another key. ```bash curl --fail-with-body -X DELETE "https://api-833252724876.us-central1.run.app/v1/keys/key_a1b2c3d4e5f6g7h8i9j0" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `key_id` | string | yes | | ## Response · 200 ```json { "id": "key_a1b2c3d4e5f6g7h8i9j0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "name": "ci", "prefix": "jean_live_exam", "created_by": "usr_b2c3d4e5f6g7h8i9j0k1", "created_at": "2026-01-15T09:30:00Z", "last_used_at": null, "revoked_at": null } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # List suites Source: https://jeantechnologies.com/docs/api/list-suites Summary: List suites — Jean Platform API reference. `GET /v1/suites` List suites **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/suites" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Response · 200 ```json { "suites": [ { "suite_id": "suite:smoke-v1", "version": "1", "metric": "accuracy", "n_items": 200, "per_item_feedback": true, "description": "A tiny suite for wiring up a client.", "hfm_sha": "9f2c1ab4d7e0" } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Submit predictions for scoring Source: https://jeantechnologies.com/docs/api/submit-eval Summary: Submit predictions for scoring — Jean Platform API reference. `POST /v1/evals` Queues an `eval` job. Inline `predictions` are capped at 5 MB of JSON. Poll `GET /v1/jobs/{id}` for the result. **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/evals" \ -H "Authorization: Bearer $JEAN_API_KEY" \ -H "Idempotency-Key: YOUR-UNIQUE-REQUEST-KEY" \ -H "Content-Type: application/json" \ -d '{ "label": "nightly", "predictions": [ { "item_id": "item_4211", "prediction": [ "item_88", "item_12", "item_5" ] }, { "item_id": "item_4212", "prediction": [ "item_31", "item_7", "item_99" ] } ], "suite_id": "suite:smoke-v1" }' ``` ## Body | Field | Type | Required | Notes | | --- | --- | --- | --- | | `suite_id` | string | yes | | | `predictions` | object[] or null | no | Inline predictions. Capped at 5 MB of JSON. | | `input_ref` | string or null | no | An upload `ref` from POST /v1/uploads (kind `predictions`) instead of inline. | | `label` | string or null | no | | ## Response · 202 ```json { "id": "job_q1w2e3r4t5y6u7i8o9p0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "type": "eval", "status": "queued", "request_id": "req_z9x8c7v6b5n4m3l2", "label": "nightly", "versions": { "hfm_sha": "9f2c1ab4d7e0", "suite_id": "suite:smoke-v1" }, "attempts": 0, "created_at": "2026-01-15T09:30:00Z", "started_at": null, "finished_at": null } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `413` | Inline predictions exceed the 5 MB cap. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # List jobs, newest first Source: https://jeantechnologies.com/docs/api/list-jobs Summary: List jobs, newest first — Jean Platform API reference. `GET /v1/jobs` List jobs, newest first **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/jobs" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Query | Name | Type | Required | Notes | | --- | --- | --- | --- | | `type` | `"eval"`, `"predict"` or null | no | | | `status` | `"queued"`, `"running"`, `"succeeded"`, `"failed"`, `"cancelled"` or null | no | | | `limit` | integer | no | Range: 1–200. Default `50`. | | `before` | string or null | no | Return jobs created before this time. | ## Response · 200 ```json { "jobs": [ { "attempts": 1, "created_at": "2026-01-15T09:30:00Z", "finished_at": "2026-01-15T09:30:18Z", "id": "job_q1w2e3r4t5y6u7i8o9p0", "label": "nightly", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "request_id": "req_z9x8c7v6b5n4m3l2", "result": { "hfm_sha": "9f2c1ab4d7e0", "metric": "accuracy", "n": 200, "n_submitted": 200, "n_unmatched": 0, "suite_id": "suite:smoke-v1", "suite_version": "1", "value": 0.734 }, "started_at": "2026-01-15T09:30:02Z", "status": "succeeded", "trace_url": "https://storage.googleapis.com/jean-artifacts/.../trace.json", "type": "eval", "versions": { "hfm_sha": "9f2c1ab4d7e0", "suite_id": "suite:smoke-v1", "suite_version": "1" } } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Get a job Source: https://jeantechnologies.com/docs/api/get-job Summary: Get a job — Jean Platform API reference. `GET /v1/jobs/{job_id}` Get a job **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/jobs/job_q1w2e3r4t5y6u7i8o9p0" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `job_id` | string | yes | | ## Response · 200 ```json { "attempts": 1, "created_at": "2026-01-15T09:30:00Z", "finished_at": "2026-01-15T09:30:18Z", "id": "job_q1w2e3r4t5y6u7i8o9p0", "label": "nightly", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "request_id": "req_z9x8c7v6b5n4m3l2", "result": { "hfm_sha": "9f2c1ab4d7e0", "metric": "accuracy", "n": 200, "n_submitted": 200, "n_unmatched": 0, "suite_id": "suite:smoke-v1", "suite_version": "1", "value": 0.734 }, "started_at": "2026-01-15T09:30:02Z", "status": "succeeded", "trace_url": "https://storage.googleapis.com/jean-artifacts/.../trace.json", "type": "eval", "versions": { "hfm_sha": "9f2c1ab4d7e0", "suite_id": "suite:smoke-v1", "suite_version": "1" } } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Cancel a queued job Source: https://jeantechnologies.com/docs/api/cancel-job Summary: Cancel a queued job — Jean Platform API reference. `POST /v1/jobs/{job_id}/cancel` Cancel a queued job **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/jobs/job_q1w2e3r4t5y6u7i8o9p0/cancel" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `job_id` | string | yes | | ## Response · 200 ```json { "attempts": 1, "created_at": "2026-01-15T09:30:00Z", "finished_at": "2026-01-15T09:30:18Z", "id": "job_q1w2e3r4t5y6u7i8o9p0", "label": "nightly", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "request_id": "req_z9x8c7v6b5n4m3l2", "result": { "hfm_sha": "9f2c1ab4d7e0", "metric": "accuracy", "n": 200, "n_submitted": 200, "n_unmatched": 0, "suite_id": "suite:smoke-v1", "suite_version": "1", "value": 0.734 }, "started_at": "2026-01-15T09:30:02Z", "status": "succeeded", "trace_url": "https://storage.googleapis.com/jean-artifacts/.../trace.json", "type": "eval", "versions": { "hfm_sha": "9f2c1ab4d7e0", "suite_id": "suite:smoke-v1", "suite_version": "1" } } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `409` | The job is not in a cancellable state. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Fetch trace.json through the API Source: https://jeantechnologies.com/docs/api/get-job-trace Summary: Fetch trace.json through the API — Jean Platform API reference. `GET /v1/jobs/{job_id}/trace` Fetch trace.json through the API **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/jobs/job_q1w2e3r4t5y6u7i8o9p0/trace" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `job_id` | string | yes | | ## Response · 200 The OpenInference-style trace. ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Usage this period Source: https://jeantechnologies.com/docs/api/get-usage Summary: Usage this period — Jean Platform API reference. `GET /v1/usage` Usage this period **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/usage" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Response · 200 ```json { "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "plan": "free", "period_start": "2026-01-15T09:30:00Z", "period_end": "2026-01-15T09:30:00Z", "totals": { "eval_items": 18000, "requests": 412 }, "active_jobs": 1, "limits": { "concurrent_jobs": 2, "eval_items_per_month": 20000 } } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # List org members Source: https://jeantechnologies.com/docs/api/list-members Summary: List org members — Jean Platform API reference. `GET /v1/members` List org members **Credential.** A dashboard session token only. An API key cannot call this — a key must never be able to mint another key. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/members" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Response · 200 ```json { "members": [ { "user_id": "usr_b2c3d4e5f6g7h8i9j0k1", "email": "ada@example.com", "role": "owner", "created_at": "2026-01-15T09:30:00Z" } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Promote or demote a member Source: https://jeantechnologies.com/docs/api/set-member-role Summary: Promote or demote a member — Jean Platform API reference. `PATCH /v1/members/{user_id}` Owners only. An org must always keep at least one owner, so demoting the last one is refused with 409 `invalid_state`; promote a second owner first. An owner may demote themselves once another owner exists. **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body -X PATCH "https://api-833252724876.us-central1.run.app/v1/members/usr_b2c3d4e5f6g7h8i9j0k1" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "role": "owner" }' ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `user_id` | string | yes | | ## Body | Field | Type | Required | Notes | | --- | --- | --- | --- | | `role` | `"owner"`, `"member"` | yes | | ## Response · 200 ```json { "user_id": "usr_b2c3d4e5f6g7h8i9j0k1", "email": "ada@example.com", "role": "owner", "created_at": "2026-01-15T09:30:00Z" } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `409` | An org must keep at least one owner; this would remove the last. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Remove a member from the org Source: https://jeantechnologies.com/docs/api/remove-member Summary: Remove a member from the org — Jean Platform API reference. `DELETE /v1/members/{user_id}` Owners only, and the way someone is offboarded. The last owner cannot be removed (409 `invalid_state`). API keys belong to the org, not to the person who created them, so they keep working; revoke the departing person's keys separately if their access should end with them. **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body -X DELETE "https://api-833252724876.us-central1.run.app/v1/members/usr_b2c3d4e5f6g7h8i9j0k1" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `user_id` | string | yes | | ## Response · 204 Successful Response ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `409` | An org must keep at least one owner; this would remove the last. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # List invites Source: https://jeantechnologies.com/docs/api/list-invites Summary: List invites — Jean Platform API reference. `GET /v1/invites` List invites **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/invites" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Response · 200 ```json { "invites": [ { "id": "inv_a1b2c3d4e5f6g7h8i9j0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "email": "ada@example.com", "role": "owner", "invited_by": "usr_b2c3d4e5f6g7h8i9j0k1", "created_at": "2026-01-15T09:30:00Z", "expires_at": "2026-01-15T09:30:00Z", "accepted_at": null, "accepted_by": null, "revoked_at": null } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `409` | Already exists, or stale version. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Invite a teammate by email Source: https://jeantechnologies.com/docs/api/create-invite Summary: Invite a teammate by email — Jean Platform API reference. `POST /v1/invites` The invite is consumed on the invitee's first sign-in with that email address. Owners only. Invites expire after 14 days. **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/invites" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "email": "ada@example.com" }' ``` ## Body | Field | Type | Required | Notes | | --- | --- | --- | --- | | `email` | string | yes | Length 3–254. | | `role` | `"owner"`, `"member"` | no | Default `"member"`. | ## Response · 201 ```json { "id": "inv_a1b2c3d4e5f6g7h8i9j0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "email": "ada@example.com", "role": "owner", "invited_by": "usr_b2c3d4e5f6g7h8i9j0k1", "created_at": "2026-01-15T09:30:00Z", "expires_at": "2026-01-15T09:30:00Z", "accepted_at": null, "accepted_by": null, "revoked_at": null } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `409` | Already exists, or stale version. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Revoke an invite Source: https://jeantechnologies.com/docs/api/revoke-invite Summary: Revoke an invite — Jean Platform API reference. `DELETE /v1/invites/{invite_id}` Revoke an invite **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body -X DELETE "https://api-833252724876.us-central1.run.app/v1/invites/inv_a1b2c3d4e5f6g7h8i9j0" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `invite_id` | string | yes | | ## Response · 200 ```json { "id": "inv_a1b2c3d4e5f6g7h8i9j0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "email": "ada@example.com", "role": "owner", "invited_by": "usr_b2c3d4e5f6g7h8i9j0k1", "created_at": "2026-01-15T09:30:00Z", "expires_at": "2026-01-15T09:30:00Z", "accepted_at": null, "accepted_by": null, "revoked_at": null } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # List claimed domains Source: https://jeantechnologies.com/docs/api/list-domains Summary: List claimed domains — Jean Platform API reference. `GET /v1/domains` List claimed domains **Credential.** A dashboard session token only. An API key cannot call this — a key must never be able to mint another key. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/domains" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Response · 200 ```json { "domains": [ { "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "domain": "example.com", "claimed_by": "usr_b2c3d4e5f6g7h8i9j0k1", "verified_at": "2026-01-15T09:30:00Z", "created_at": "2026-01-15T09:30:00Z" } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `409` | Already exists, or stale version. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Claim an email domain Source: https://jeantechnologies.com/docs/api/claim-domain Summary: Claim an email domain — Jean Platform API reference. `POST /v1/domains` New users who sign in with a verified email on a claimed domain join this org as members. An owner may claim the domain of their own verified email; public mailbox domains cannot be claimed. Each domain belongs to at most one org. **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/domains" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "domain": "example.com" }' ``` ## Body | Field | Type | Required | Notes | | --- | --- | --- | --- | | `domain` | string | yes | Lower-case. Must be the domain of the caller's own verified email. Length 3–253. | ## Response · 201 ```json { "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "domain": "example.com", "claimed_by": "usr_b2c3d4e5f6g7h8i9j0k1", "verified_at": "2026-01-15T09:30:00Z", "created_at": "2026-01-15T09:30:00Z" } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `409` | Already exists, or stale version. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Release a claimed domain Source: https://jeantechnologies.com/docs/api/release-domain Summary: Release a claimed domain — Jean Platform API reference. `DELETE /v1/domains/{domain}` Release a claimed domain **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body -X DELETE "https://api-833252724876.us-central1.run.app/v1/domains/example.com" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `domain` | string | yes | | ## Response · 204 Successful Response ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # The org's audit log Source: https://jeantechnologies.com/docs/api/list-audit-events Summary: The org's audit log — Jean Platform API reference. `GET /v1/audit` The org's audit log **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/audit" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Query | Name | Type | Required | Notes | | --- | --- | --- | --- | | `limit` | integer | no | Range: 1–500. Default `100`. | ## Response · 200 ```json { "events": [ { "id": 1842, "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "actor_user_id": "usr_b2c3d4e5f6g7h8i9j0k1", "actor_key_id": "key_a1b2c3d4e5f6g7h8i9j0", "action": "key.create", "target": "key_a1b2c3d4e5f6g7h8i9j0", "request_id": "req_z9x8c7v6b5n4m3l2", "details": { "name": "ci" }, "ts": "2026-01-15T09:30:00Z" } ] } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Terms status Source: https://jeantechnologies.com/docs/api/get-terms Summary: Terms status — Jean Platform API reference. `GET /v1/terms` Terms status **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body "https://api-833252724876.us-central1.run.app/v1/terms" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Response · 200 ```json { "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "current_version": "2026-09-01", "data_use": "scoring_only", "accepted_version": "2026-09-01", "accepted_at": "2026-01-15T09:30:00Z", "accepted_by": "usr_b2c3d4e5f6g7h8i9j0k1", "up_to_date": true } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `409` | Already exists, or stale version. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Accept the current terms and set the org's data-use choice Source: https://jeantechnologies.com/docs/api/accept-terms Summary: Accept the current terms and set the org's data-use choice — Jean Platform API reference. `POST /v1/terms` Owners only. Records who accepted which version, from where, and sets `org.data_use`. The default before any acceptance is `scoring_only`. **Credential.** A dashboard session token belonging to an **owner** of the organisation. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/terms" \ -H "Authorization: Bearer $JEAN_SESSION_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "terms_version": "2026-09-01" }' ``` ## Body | Field | Type | Required | Notes | | --- | --- | --- | --- | | `terms_version` | string | yes | Must equal `current_version` from GET /v1/terms. | | `data_use` | `"scoring_only"`, `"aggregate_ok"`, `"training_ok"` | no | Default `"scoring_only"`. | ## Response · 200 ```json { "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "current_version": "2026-09-01", "data_use": "scoring_only", "accepted_version": "2026-09-01", "accepted_at": "2026-01-15T09:30:00Z", "accepted_by": "usr_b2c3d4e5f6g7h8i9j0k1", "up_to_date": true } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `409` | Already exists, or stale version. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Reserve an upload and get a PUT URL Source: https://jeantechnologies.com/docs/api/create-upload Summary: Reserve an upload and get a PUT URL — Jean Platform API reference. `POST /v1/uploads` Reserves a private object for this org and returns a time-limited PUT URL. PUT exactly `size_bytes` with `content_type`, then pass `ref` to a job as `input_ref`. Objects are private to the org and are only ever read by the worker. **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body -X POST "https://api-833252724876.us-central1.run.app/v1/uploads" \ -H "Authorization: Bearer $JEAN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "kind": "predictions", "size_bytes": 2048 }' ``` ## Body | Field | Type | Required | Notes | | --- | --- | --- | --- | | `kind` | `"outputs"`, `"panel"`, `"predictions"` | yes | `predictions` (JSON list for POST /v1/evals), `outputs` (JSONL), `panel` (CSV). | | `content_type` | `"application/json"`, `"application/x-ndjson"`, `"text/csv"` | no | Default `"application/json"`. | | `size_bytes` | integer | yes | Exact size you will PUT. Range: −∞–209715200. | ## Response · 201 ```json { "id": "upl_a1b2c3d4e5f6g7h8i9j0", "org_id": "org_k3j2h4g5f6d7s8a9q0w1", "kind": "predictions", "content_type": "application/json", "size_bytes": 2048, "ref": "upload:upl_a1b2c3d4e5f6g7h8i9j0", "put_url": "https://storage.googleapis.com/jean-uploads/...", "put_headers": { "Content-Type": "application/json" }, "expires_at": "2026-01-15T09:30:00Z" } ``` ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json) ============================================================================== # Upload bytes through the API (local artifact backend only) Source: https://jeantechnologies.com/docs/api/put-upload-bytes Summary: Upload bytes through the API (local artifact backend only) — Jean Platform API reference. `PUT /v1/uploads/{upload_id}/{kind}` In production `put_url` is a signed GCS URL and this route returns 404. With the local artifact backend it accepts the bytes directly. **Credential.** An API key (`jean_live_…`) or a dashboard session token. ```bash curl --fail-with-body -X PUT "https://api-833252724876.us-central1.run.app/v1/uploads/upl_a1b2c3d4e5f6g7h8i9j0/predictions" \ -H "Authorization: Bearer $JEAN_API_KEY" ``` ## Path | Name | Type | Required | Notes | | --- | --- | --- | --- | | `upload_id` | string | yes | | | `kind` | string | yes | | ## Response · 204 Successful Response ## Errors | Status | Meaning | | --- | --- | | `401` | Unauthenticated, invalid token or revoked key. | | `403` | Forbidden, session required or org required. | | `404` | No such resource in this org. | | `413` | Upload exceeds the size cap. | | `422` | Validation failed. | | `429` | Quota or rate limit exceeded; `error.details` says which, and when. | | `500` | Internal error; quote `error.request_id` when reporting it. | Every one carries the [same envelope](https://jeantechnologies.com/docs/api/overview#errors). [API overview](https://jeantechnologies.com/docs/api/overview) · [Full contract](https://jeantechnologies.com/docs/openapi.json)