{"openapi":"3.1.0","info":{"title":"Qurak REST API","description":"Evaluate Wolfram Language expressions over HTTP: one-shot or in persistent sessions, background jobs for long work, rendered plots, the execution log, and the account's plan. Authenticate with `Authorization: Bearer qk_...` (an API token minted on the MCP page) or a browser session. Prices and plan limits are served by GET /billing/plans; the same engine is also available over MCP at /mcp - see /llms.txt.","version":"2026-08"},"servers":[{"url":"https://qurak.com"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A qk_ API token (mint one on /en/mcp.html while signed in, or via OAuth - discovery at /.well-known/oauth-authorization-server). OAuth access tokens carry scopes; qk_ tokens carry full account access."}},"schemas":{"EvaluateRequest":{"type":"object","required":["expression"],"properties":{"expression":{"type":"string","description":"Wolfram Language, evaluated as-is."},"session_id":{"type":"string","description":"Optional persistent session to run in. State (variables, definitions) persists between calls until ~30 minutes idle."}}},"EvaluateResponse":{"type":"object","properties":{"result":{"type":"string"},"status":{"type":"string","description":"success | unevaluated | plot_omitted - unevaluated means the engine returned the input unchanged; do not read the result as an answer."},"execution_time_ms":{"type":"integer"},"run_id":{"type":["integer","null"],"description":"The execution-log row this evaluation was recorded as; /api/history and /api/bursts/locate speak this id."},"plot_url":{"type":["string","null"],"description":"/api/plots/{run_id} when the expression rendered a graphic."},"receipt_url":{"type":["string","null"],"description":"/api/receipts/{run_id}: the signed, content-addressed record of this run, present whenever run_id is."},"stdout":{"type":["string","null"]},"warnings":{"type":"array","items":{"type":"string"}},"verification":{"oneOf":[{"type":"object","description":"An independent check of the answer above, derived from the expression's own shape and run in a throwaway worker. Present only when a rule covers the expression AND the check reached a verdict - never as an `inconclusive` placeholder, because a field that is usually noise is a field callers stop reading. Absence therefore means nothing was learned, not that the answer is fine. POST /api/verify runs the same check at a longer budget.","properties":{"verdict":{"type":"string","description":"verified | refuted. `refuted` means an independent computation contradicts this answer; since both come from the same engine, at least one of them is wrong."},"basis":{"type":"string","description":"exact | numeric | cross_check. A cross_check may refute and can never verify."},"method":{"type":"string","description":"Which derivation rule ran, e.g. integrate_residual, solve_residual."},"check":{"type":"string","description":"The expression that was actually evaluated, so the verdict can be re-run by hand."},"residual":{"type":"string","description":"What that expression returned."},"elapsed_ms":{"type":"integer"},"automatic":{"type":"boolean","description":"True when the check ran unasked, alongside the evaluation."}}},{"type":"null"}]}}},"Job":{"type":"object","properties":{"job_id":{"type":"string"},"status":{"type":"string","description":"queued | running | succeeded | failed | timeout | cancelled | lost"},"position":{"type":"integer","description":"Queue position, while queued."},"jobs_remaining_today":{"type":"integer","description":"On a submit receipt, and on a proof submit answered with wait_ms."},"resubmit":{"type":"boolean","description":"On a submit: true when the idempotency key matched an existing job and no new slot was spent."},"run_id":{"type":"integer","description":"The execution-log row the job wrote, once it has one."},"output":{"type":"string","description":"The rendered result, or for a proof job the verdict sentence, once terminal."},"error":{"type":["string","null"]},"result":{"type":"object","description":"Once terminal: the structured result; for a proof job the certificate - verdict, reason, each named declaration's statement and axioms, the export identity."},"certificate_id":{"type":"string","description":"proof jobs: the certificate GET /api/certificates/{id} resolves."},"certificate_url":{"type":"string"}}},"VerifyRequest":{"type":"object","description":"Either `run_id` on its own, or both `code` and `result`. The run_id form is preferred: the server already holds both halves, so nothing has to be restated and nothing can be misquoted.","properties":{"run_id":{"type":"integer","description":"An execution-log row id, as returned by /api/evaluate. Must belong to the calling account."},"code":{"type":"string","description":"The original expression, when no run_id is held."},"result":{"type":"string","description":"The answer to check, when no run_id is held."}}},"VerifyResponse":{"type":"object","description":"The same fields the evaluate response's `verification` carries, plus `reason`. Unlike that field, this one is always returned - an explicit question deserves an explicit `inconclusive` naming which kind of nothing was learned.","properties":{"verdict":{"type":"string","description":"verified | refuted | inconclusive. `inconclusive` means nothing was learned - not that the answer is probably fine."},"basis":{"type":["string","null"],"description":"exact | numeric | cross_check. A cross_check may refute and can never verify."},"method":{"type":["string","null"],"description":"Which derivation rule ran, as a slug: a residual or identity rule (`integrate_residual`, `solve_residual`, `rewrite_identity`, ...) can verify or refute; a sampled route (`integrate_quadrature`, `nintegrate_truncation`, `nsum_truncation`, `series_truncation`, `limit_approach`, `series_order`, `findroot_residual`, `rsolve_sampled`, ...) can refute and never verifies."},"check":{"type":["string","null"],"description":"The expression that was actually evaluated."},"residual":{"type":["string","null"],"description":"What that expression returned."},"reason":{"type":["string","null"],"description":"On `inconclusive`, which kind of nothing: cross_check_agrees (an independent route agreed with the answer - support, not proof: a cross-check can only refute), no_check_for_head (no rule covers this function), no_check_for_shape (the function has a rule but not for the way this call is written - rephrasing may help), answer_not_usable, simplify_did_not_reduce, check_timed_out, check_engine_error, check_not_permitted."},"elapsed_ms":{"type":"integer"}}},"ProofUploadReceipt":{"type":"object","properties":{"upload_id":{"type":"string","description":"Pass as `upload_id` to POST /api/jobs {kind: proof} or the check_proof MCP tool. One upload is checked by one job."},"export_bytes":{"type":"integer"},"export_sha256":{"type":"string","description":"sha256 of the normalised export - the identity every certificate about it cites."},"exporter":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"}}},"lean":{"type":"object","properties":{"version":{"type":"string"},"githash":{"type":"string"}}},"format_version":{"type":"string"}}},"Certificate":{"type":"object","description":"The receipt of one proof check: the verdict, what was certified, the axioms each proof reaches, and the identity of what was judged. A verdict on a name certifies nothing a reader can act on, which is why each declaration carries its rendered statement.","properties":{"certificate_id":{"type":"string"},"certificate_url":{"type":"string"},"job_id":{"type":"string"},"about_run_id":{"type":["integer","null"],"description":"The evaluation this proof is about - the run_id the submit named - or null."},"verdict":{"type":"string","description":"verified | rejected | unsupported | inconclusive. `rejected` is the kernel refusing a proof; `unsupported` is an export the checker cannot judge (a format outside its window, a `sorry`, an axiom outside Init.Core's six, an Init.Core definition that differs from the reference); `inconclusive` is a judge that did not finish - never a verdict on the proof."},"reason":{"type":["string","null"]},"declarations":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"kind":{"type":"string","description":"theorem | definition | opaque"},"statement":{"type":["string","null"],"description":"Rendered by the checker's own printer, proof omitted."},"axioms":{"type":"array","items":{"type":"string"},"description":"The axioms this declaration's proof actually reaches - the same walk as `#print axioms`."},"statement_sha256":{"type":["string","null"]}}}},"axioms_used":{"type":"array","items":{"type":"string"}},"refusal":{"type":["object","null"],"description":"On `rejected`: {declaration, class, message, file, line} - the checker's own words and where in it the refusal came from."},"export":{"type":"object","properties":{"sha256":{"type":"string"},"bytes":{"type":"integer"},"exporter":{"type":"object"},"lean":{"type":"object"},"format_version":{"type":"string"}}},"checker":{"type":"object","properties":{"name":{"type":"string"},"rev":{"type":"string"},"format_window":{"type":"string"}}},"conformance":{"type":["object","null"],"description":"{reference_lean_version, matched, differing, outside: {count, namespaces}}: how the export's Init.Core declarations compared with the reference. Any name under `differing` makes the verdict unsupported."},"declarations_checked":{"type":"integer","description":"The whole closure, not only the named declarations."},"elapsed_ms":{"type":"integer"},"created_at":{"type":"string"}}}}},"paths":{"/healthz":{"get":{"summary":"Liveness probe","responses":{"200":{"description":"The service is up."}}}},"/billing/plans":{"get":{"summary":"The plan catalogue: tiers, prices, and the limits actually enforced","description":"Public. Feature bullets are derived from enforced limits, so what this says a plan does is what the server does. Each buyable price carries a `quote`: the plan, period, amount, currency and a 24-hour expiry, sealed with the deployment's receipt key (see /api/receipts/{id} for the envelope) so an agent can relay a firm, citable price to its principal.","responses":{"200":{"description":"Plans with budgets, rate limits and prices."}}}},"/auth/register":{"post":{"summary":"Create an account","description":"Rate-limited. The account starts on the Free plan; mint an API token from a signed-in session on /api/tokens.","requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string","minLength":8}}}}}},"responses":{"200":{"description":"The new account's user_id."}}}},"/api/docs/search":{"get":{"summary":"Search the function reference and task recipes","parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"kind","in":"query","schema":{"type":"string","enum":["function","task","any"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["supported","divergent","blocked","unsupported"]}}],"responses":{"200":{"description":"Paged, tagged rows."}}}},"/api/docs/symbol/{name}":{"get":{"summary":"One symbol's reference entry","parameters":[{"name":"name","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The entry."},"404":{"description":"No such symbol."}}}},"/api/docs/support":{"get":{"summary":"Availability of a comma-separated list of symbols","parameters":[{"name":"names","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"supported | divergent | blocked | unsupported per name."}}}},"/api/evaluate":{"post":{"summary":"Evaluate an expression","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateRequest"}}}},"responses":{"200":{"description":"The result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvaluateResponse"}}}},"408":{"description":"The plan's compute budget was exhausted - simplify, or resubmit as a background job."},"429":{"description":"The plan's per-minute rate limit was hit."}}}},"/api/verify":{"post":{"summary":"Check an answer Qurak already gave","description":"Derives an independent check from the original expression's shape - differentiating an integral back, substituting a solution into its equation's residual - and runs it in a throwaway worker, never a caller's session. It is not a second evaluation of the same derivation: a check that merely repeated the computation would repeat its mistakes.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyRequest"}}}},"responses":{"200":{"description":"The verdict. An answer that could not be checked is a 200 carrying `inconclusive`, not an error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyResponse"}}}},"400":{"description":"Neither a run_id nor a complete code/result pair was supplied."},"404":{"description":"No evaluation with that run_id belongs to this account."},"429":{"description":"The plan's per-minute rate limit was hit - a check is an evaluation and is admitted as one."}}}},"/api/receipts/{id}":{"get":{"summary":"The signed, content-addressed receipt for one of the account's runs","description":"The record - expression, answer, engine revision, the automatic check's verdict, the requesting account and the time - serialized canonically (keys sorted, no whitespace, non-ASCII escaped as \\uXXXX), its SHA-256 as `id`, and an Ed25519 signature over those bytes under the key named by `kid` in /.well-known/qurak-keys.json. A deployment with no signing key serves `signature: null` with `unsigned_reason`. Verify offline: re-serialize `record` canonically, hash it, check the signature against the JWK.","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"},"description":"The run_id an evaluation returned."}],"responses":{"200":{"description":"The sealed receipt: `record`, `id`, `canonical_form`, `signature` (or null), `keys_url`, `receipt_url`."},"404":{"description":"No evaluation with that run_id belongs to this account."}}}},"/api/history":{"get":{"summary":"The account's recent evaluations, newest first","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer"}},{"name":"offset","in":"query","schema":{"type":"integer"}},{"name":"status","in":"query","schema":{"type":"string"}},{"name":"source","in":"query","schema":{"type":"string","enum":["web","mcp","job"]}},{"name":"query","in":"query","description":"A substring to find in the expression as it arrived. Trimmed; over 200 characters is rejected.","schema":{"type":"string"}},{"name":"from","in":"query","description":"Only runs on or after this UTC calendar day (YYYY-MM-DD). A value that is not such a date is rejected.","schema":{"type":"string","format":"date"}},{"name":"to","in":"query","description":"Only runs on or before this UTC calendar day (YYYY-MM-DD), the whole day included.","schema":{"type":"string","format":"date"}},{"name":"verdict","in":"query","description":"Only runs whose automatic check reached this verdict. A row with no stored verdict is excluded.","schema":{"type":"string","enum":["verified","refuted","inconclusive"]}}],"responses":{"200":{"description":"Evaluation rows. Each carries `verification` ({verdict, method}) when the automatic check reached one."}}}},"/api/jobs":{"post":{"summary":"Queue a background job: an evaluation, a qsim circuit simulation, or a Lean 4 proof check","description":"The three kinds share one daily allowance. A submission refused at validation - a denied expression, a malformed circuit or export, an unregistered declaration, a run_id that is not the caller's, a plan that has none - costs no slot; a queued job spends one whichever way it ends, and cancelling it before it starts (DELETE) refunds it.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":[],"properties":{"expression":{"type":"string"},"session_id":{"type":"string"},"timeout_ms":{"type":"integer"},"idempotency_key":{"type":"string"},"run_id":{"type":"integer","minimum":1,"description":"proof only: the id an earlier /api/evaluate returned, when this proof is about that answer. The certificate carries it as `about_run_id`, and the run's history row shows the certificate. Must be one of this account's runs."},"wait_ms":{"type":"integer","minimum":0,"description":"proof only: hold the request open up to this many milliseconds (clamped to 25000) and answer with the finished job - the Job shape with `result`, `certificate_id` and `certificate_url`, plus `jobs_remaining_today` and `resubmit` - when the check completes inside it; otherwise the receipt. A kilobyte closure checks in milliseconds. Other kinds long-poll GET /api/jobs/{id}?wait_ms=... and are refused here."},"kind":{"type":"string","enum":["evaluate","qsim","proof"],"description":"Defaults to evaluate. qsim takes `circuit` instead of `expression`; proof takes `export` (or `upload_id`) and `declarations`."},"circuit":{"type":"object","description":"qsim only: {qubits, shots, gates:[{gate,target,control,angle}...], seed} - see the simulate_circuit MCP tool for the gate set."},"export":{"type":"string","description":"proof only: the lean4export NDJSON, as one string - the output of `lake env lean4export <Module> -- <decl>...` with no export options. Inline exports are limited to 640 KiB because the request body is; upload larger ones with POST /api/proofs and pass `upload_id` instead."},"upload_id":{"type":"string","description":"proof only: the id returned by POST /api/proofs, instead of `export`."},"declarations":{"type":"array","items":{"type":"string"},"description":"proof only: the declarations to certify (1 to 32 names, as exported). Every declaration in the export is checked; the verdict and the certificate are about these."},"source":{"type":"string","description":"proof only: a Lean source to elaborate on the server before checking, in place of export/upload_id. Elaboration is free; the check spends the slot."},"module":{"type":"string","description":"proof only, with source: the module the source becomes (default Qurak)."}},"description":"For evaluate: expression (required) and optionally session_id. For qsim: circuit (required). For proof: export or upload_id, and declarations (both required)."}}}},"responses":{"200":{"description":"The job receipt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}}}},"get":{"summary":"List the account's jobs","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Job rows."}}}},"/api/jobs/{id}":{"get":{"summary":"One job; pass wait_ms to long-poll for completion","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"wait_ms","in":"query","schema":{"type":"integer","maximum":25000}}],"responses":{"200":{"description":"The job with its result once terminal."}}},"delete":{"summary":"Cancel a job (queued = refunded, running = killed)","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The cancel outcome."}}}},"/api/proofs":{"post":{"summary":"Store a lean4export closure for a later proof check","description":"For exports too large to inline in POST /api/jobs (the request body limit is 1 MB; the closure of one `simp` proof over Nat measures 3.6 MB). The body is the export itself - the raw NDJSON, or gzip-compressed with `Content-Encoding: gzip` - not a JSON envelope. The plan's export budget is enforced here, so an export no plan of yours could check is refused now. Then queue the check with POST /api/jobs {kind: \"proof\", upload_id, declarations} or the check_proof MCP tool.","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/x-ndjson":{"schema":{"type":"string"}},"application/gzip":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"The upload receipt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProofUploadReceipt"}}}},"400":{"description":"Not a lean4export file the checker can read (a bad meta line, a format outside >=3.1.0,<3.2.0, a blank line), or over the plan's budget."},"403":{"description":"Proof checking is not on this plan; the body carries the plan signal."},"413":{"description":"Over the structural cap of 16 MiB."},"429":{"description":"The plan's per-minute rate limit was hit - an upload is admitted like an evaluation."}}}},"/api/proofs/validate":{"post":{"summary":"Validate a proof submission without spending a job slot","description":"The free pre-flight for POST /api/jobs {kind: \"proof\"}: the same `export` (or `upload_id`) and `declarations`, answered with what the submit would do. `would_be` is `checked` (the export parses, its Init.Core matches the reference, every named declaration is there and reaches only legitimate axioms - the kernel would now judge it), `refused` (the submit would answer `refusal` and spend nothing), `unsupported` (the submit would be accepted, spend a slot, and answer `refusal`: a name the export lacks, with the nearest it declares; a `sorry`; a custom axiom) or `undecided`. It cannot see a wrong proof - only the kernel can, at submission. Costs what an evaluation costs (the per-minute limit, a worker process), never a slot; an `upload_id` is not consumed and goes to the submit next.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"export":{"type":"string","description":"The lean4export NDJSON, inline (under the inline limit)."},"upload_id":{"type":"string","description":"An upload from POST /api/proofs, instead of `export`."},"declarations":{"type":"array","items":{"type":"string"},"minItems":1,"maxItems":32}},"required":["declarations"]}}}},"responses":{"200":{"description":"The validation report: `ok`, `would_be`, `refusal`, `export` (bytes, sha256, inline, meta), `declarations` (name, kind, statement, axioms, reaches_sorry), `axioms_used`, `conformance`, `declarations_in_export`, `slot_cost` (always 0), `jobs_remaining_today`, `elapsed_ms`.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Both or neither of `export` and `upload_id`, or an `upload_id` this account does not own."},"429":{"description":"The plan's per-minute rate limit was hit - validation is admitted like an evaluation."}}}},"/api/proofs/elaborate":{"post":{"summary":"Elaborate a Lean source on the server, then validate the export","description":"Server-side elaboration: a `.lean` `source` (imports limited to the pinned toolchain's own libraries), run in a sandbox, then exported and validated - the one-call alternative to installing Lean and lean4export locally. Elaboration is free (it spends the per-minute rate limit, like an evaluation, not a job slot); the kernel check that issues a certificate is a separate POST /api/jobs {kind: \"proof\", upload_id} which spends the slot. On a Lean error the answer is {ok: false, phase: \"elaborate\", messages: [{severity, line, column, ...}], hint} (HTTP 200). On success it is {ok: true, upload_id, declarations, messages (warnings only), export: {bytes, sha256, ...}, validation: <the validate report>, next}. Requires the elaboration service; a deployment without it answers 503. declarations may be omitted with source - the theorems and lemmas are discovered from the file.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","description":"The Lean 4 source to elaborate, up to 64 KB. Imports beyond the pinned toolchain's own libraries (Init, Std, Lean) are not available on the server."},"module":{"type":"string","description":"The module the source becomes (default Qurak); its name appears in the export's hygiene names. Dotted, e.g. Qurak.Clean."},"declarations":{"type":"array","items":{"type":"string"},"maxItems":32,"description":"The declarations to certify. Omit to certify every theorem and lemma the file declares."}},"required":["source"]}}}},"responses":{"200":{"description":"Either the Lean errors (ok: false, with messages and hint) or the stored export and its validation report (ok: true, with upload_id, export and validation).","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"An empty or oversize source, a bad module name, or source together with export/upload_id."},"403":{"description":"The plan has no proof checking."},"429":{"description":"The per-minute rate limit, or an elaboration already in flight for this account."},"503":{"description":"This deployment runs no elaboration service, or it is not responding; export locally and check the export instead."}}}},"/api/certificates":{"get":{"summary":"The account's proof certificates, newest first","security":[{"bearerAuth":[]}],"parameters":[{"name":"limit","in":"query","schema":{"type":"integer","maximum":200}},{"name":"before","in":"query","schema":{"type":"string"},"description":"The `next_before` of the previous page."}],"responses":{"200":{"description":"{certificates: [Certificate], next_before}"}}}},"/api/certificates/{id}":{"get":{"summary":"One proof certificate","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The certificate.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Certificate"}}}},"404":{"description":"No certificate with that id belongs to this account."}}}},"/api/certificates/{id}/public":{"get":{"summary":"One proof certificate, publicly, by id","description":"No token: anyone holding the certificate's id (a UUID) may read it. The same document as GET /api/certificates/{id} minus the account's own ids (job_id, submission_id, run_id, about_run_id); `public_url` is the human-readable page at /certificates/{id}.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The certificate: verdict, reason, declarations (name, kind, statement, axioms, statement_sha256), axioms_used, refusal, export (sha256, bytes, exporter, lean, format_version), checker, conformance, declarations_checked, elapsed_ms, created_at, certificate_url, public_url.","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No such certificate."}}}},"/api/sessions":{"get":{"summary":"The account's live evaluation sessions","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Sessions and the idle TTL in force."}}}},"/api/sessions/{id}":{"delete":{"summary":"Clear one session","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Whether it existed."}}}},"/api/plots/{id}":{"get":{"summary":"The rendered SVG of one evaluation's plot","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"image/svg+xml."},"404":{"description":"No plot for that run."}}}},"/api/bursts":{"get":{"summary":"Recent activity grouped into per-agent bursts (beta)","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Burst summaries over a bounded scan."}}}},"/api/bursts/locate":{"get":{"summary":"Which burst a run or job belongs to","security":[{"bearerAuth":[]}],"parameters":[{"name":"run_id","in":"query","schema":{"type":"integer"}},{"name":"job_id","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"The burst id, or an honest miss."}}}},"/api/bursts/{id}":{"get":{"summary":"One burst's ordered timeline","security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The timeline."},"404":{"description":"A derived id that no longer derives."}}}},"/billing/subscription":{"get":{"summary":"The account's subscription summary","description":"First-party only: the session or a qk_ token. Connected apps (OAuth) are refused whatever their scope.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"The summary, or null on the Free plan."}}}},"/billing/invoices":{"get":{"summary":"The account's recent invoices","description":"First-party only, like /billing/subscription.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Invoice rows, empty when the account never checked out."}}}},"/api/docs/availability.json":{"get":{"summary":"Every symbol in the reference with its availability status and call forms","description":"Public, unauthenticated, cached for a day and cross-origin readable. The counts and statuses are the same ones the reference pages render; the document changes only when the reference is rebuilt.","responses":{"200":{"description":"counts, the four status definitions, and one row per symbol: name, status, forms, verified_examples."}}}},"/api/public/evaluate":{"post":{"summary":"Evaluate one expression anonymously (the try box)","description":"No credential. Call heads are restricted to an allowlist of mathematics, the compute budget is shorter than the free plan's, and the allowance is per address per hour - X-RateLimit-Limit and X-RateLimit-Remaining say how many. Nothing is stored. The operator may switch this endpoint off, in which case it answers 404. For anything more, use /api/evaluate with a Bearer token.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["expression"],"properties":{"expression":{"type":"string","maxLength":400}}}}}},"responses":{"200":{"description":"result, stdout, warnings, elapsed_ms."},"403":{"description":"A call head outside the allowlist, named, with the allowlist."},"408":{"description":"Over the anonymous compute budget."},"413":{"description":"Over 400 bytes."},"422":{"description":"The engine refused the input; error says why."},"429":{"description":"The hourly allowance for this address is spent."},"404":{"description":"The operator has switched the anonymous box off."}}}}}}