Reference

REST API

Every /api/v1 route with its method, path, authentication, request, response and errors.

View as Markdown

Version 1 of the registry API. The CLI uses these same routes. Request and response bodies are JSON unless a route says otherwise.

Conventions

  • Registry keys go in the Authorization: Bearer rtq_... header. A key without the scope a route needs, or a revoked key, is treated as missing and returns 401.
  • Browser routes use the session cookie set at sign-in. They are listed separately and are not meant for scripts.
  • Errors always have the shape { "error": "code", "message": "text" }. Codes are listed in Errors and troubleshooting.
  • Validation errors return 400 invalid_request with a message naming each bad field as path: problem.
  • Visibility. Private, draft and unpublished patches return 404 on public routes, the same as names that don't exist.
  • Base URL. Every route is relative to the site, for example https://<registry host>/api/v1/patches.
sh
curl -s "$RETOQUE_API_URL/api/v1/patches?baseModel=qwen2.5-1.5b-instruct&limit=10"
curl -s -X POST -H "Authorization: Bearer $RETOQUE_KEY" \
  "$RETOQUE_API_URL/api/v1/patches/<slug>/versions/<version>/install-tickets"

Public routes

No authentication.

GET /api/v1/patches

Search published, public patches. Filters, sort and pagination run on the server.

Query parameter Meaning
query Case-insensitive match on title and problem text. Up to 200 characters.
baseModel Model slug, such as qwen2.5-1.5b-instruct. Not an org/name@commit reference.
category Problem category, such as structured-output.
verified true returns only patches with a published VERIFIED_FOR_SCOPE version.
license free or paid.
sort newest (default), oldest or title.
page 1 to 10000. Default 1.
limit 10, 25 or 50. Any other value falls back to 10.
json
{
  "total": 1,
  "page": 1,
  "pageSize": 10,
  "pageCount": 1,
  "items": [
    {
      "slug": "string",
      "title": "string",
      "category": "string",
      "publisher": "string",
      "baseModel": "org/name@<commit>",
      "latestVersion": "1.0.0",
      "evidenceStatus": "IMPROVED_ON_SCOPE"
    }
  ]
}

latestVersion and evidenceStatus are null when no version is in the PUBLISHED state. Errors: 400 invalid_query.

GET /api/v1/patches/{slug}

A public patch with every published, deprecated or withdrawn version.

json
{
  "slug": "string",
  "title": "string",
  "status": "PUBLISHED",
  "baseModel": { "repository": "string", "revision": "string" },
  "versions": [
    {
      "semver": "1.0.0",
      "state": "PUBLISHED",
      "evidenceStatus": "IMPROVED_ON_SCOPE",
      "manifestSha256": "<64 hex>",
      "artifactSha256": "<64 hex>",
      "packageSha256": "<64 hex>",
      "publishedAt": "<ISO 8601 or null>"
    }
  ]
}

state is PUBLISHED, DEPRECATED or WITHDRAWN. artifactSha256 is the adapter weights digest. Errors: 404 not_found.

GET /api/v1/patches/{slug}/versions/{version}

The full signed manifest of one version, for verification before download.

json
{
  "semver": "1.0.0",
  "state": "PUBLISHED",
  "manifest": { "...": "the parsed retoque.manifest.json" },
  "manifestSha256": "<64 hex>",
  "signature": { "...": "the contents of signature.json" },
  "packageSha256": "<64 hex>"
}

The manifest digest is the sha256 of the manifest serialized as canonical JSON (sorted keys, no spaces, UTF-8), which retoque verify recomputes. Errors: 404 not_found for unknown, private or unpublished versions.

GET /api/v1/models

Supported base model revisions.

json
{
  "items": [
    { "slug": "string", "repository": "string", "revision": "string", "license": "string", "publishedPatches": 0 }
  ]
}

GET /api/v1/status

Live probe results for each component, checked on every request. A component without a real probe reports unknown, never healthy.

json
{
  "components": [
    {
      "id": "api",
      "name": "Website and API",
      "state": "operational",
      "detail": "Database reachable",
      "checkedAt": "<ISO 8601>"
    }
  ]
}

id is one of api, artifacts, chain, workers, replay. state is one of operational, degraded, down, unknown, not_deployed.

GET /api/v1/chain/config

The chain this environment uses and its contract addresses.

json
{
  "chainId": 31337,
  "name": "string",
  "rpcUrl": "string",
  "explorerUrl": null,
  "isTestnet": true,
  "registry": null,
  "market": null,
  "paymentToken": null,
  "confirmations": 2,
  "deployed": false
}

deployed is true only when both the registry and market addresses are configured. Addresses are null when not set.

Registry key routes

GET /api/v1/me

Check a registry key. Used by retoque login. Needs the registry:read scope.

json
{ "email": "string", "org": "string", "scopes": ["registry:read", "artifacts:download"] }

Errors: 401 unauthenticated.

POST /api/v1/patches/{slug}/versions/{version}/install-tickets

Issue a single-use download link for a version you hold an active license for. Authenticate with a key that has the artifacts:download scope, or a signed-in session. The body is ignored. The CLI sends {}.

201:

json
{
  "downloadUrl": "https://<host>/api/v1/downloads/<token>",
  "expiresAt": "<ISO 8601, five minutes from now>",
  "packageSha256": "<64 hex>",
  "manifestSha256": "<64 hex>"
}

Withdrawn versions still issue tickets to existing license holders. Errors: 401 unauthenticated, 403 no_entitlement, 404 not_found.

GET /api/v1/downloads/{token}

Stream the package tar. The token in the path is the credential, so don't send your registry key. The token is consumed on first use.

text
200 OK
content-type: application/x-tar
content-length: <bytes>
content-disposition: attachment; filename="<slug>-<version>.tar"
cache-control: no-store

Errors: 410 download_expired when the token was already used, is older than five minutes, or doesn't exist.

POST /api/v1/install-events

Opt-in CLI check-in. Needs the installs:report scope. A download on its own is never counted as an install.

json
{
  "slug": "string, up to 100 characters",
  "semver": "string, up to 40 characters",
  "artifactSha256": "<64 lowercase hex>",
  "baseModelRef": "org/name@<commit>",
  "runtime": "transformers-peft",
  "state": "INSTALLED",
  "clientVersion": "0.1.0"
}

state is one of INSTALLED, ACTIVE, DISABLED, ROLLED_BACK, FAILED. Returns 201 with { "recorded": true }. Errors: 400 invalid_request, 401 unauthenticated, 404 not_found, 422 digest_mismatch when artifactSha256 isn't the version's adapter digest.

Browser session routes

These back the website and rely on the session cookie.

POST /api/v1/auth/magic-link

Send a sign-in link by email. The body is form-encoded: email=<address>&next=<optional path>, with the email up to 254 characters and next up to 512. Always answers 303, to /sign-in?sent=1 (with next when given), or to /sign-in?error=invalid_email. Links expire after 15 minutes.

GET /api/v1/auth/callback

?token=<emailed token>. Consumes a sign-in link, sets the session cookie and answers 303 to the requested page, or to /sign-in?error=link_invalid when the link is unknown, used or expired.

POST /api/v1/auth/sign-out

Ends the session. Answers 303 to /.

POST /api/v1/auth/wallet/challenge

Get a message to sign that binds this site, the chain ID, your address, a nonce and a 10-minute expiry.

json
{ "address": "0x..." }

200 with { "nonce": "string", "message": "string" }. Errors: 400 invalid_request when the address isn't an EVM address, 401 unauthenticated.

POST /api/v1/auth/wallet/verify

Submit the signed challenge to link the wallet. Signing costs no gas.

json
{ "nonce": "string", "signature": "0x..." }

200 with { "address": "0x...", "chainId": 31337 }. Errors: 400 invalid_request, 400 wallet_link_failed, 401 unauthenticated.

POST /api/v1/chain/reconcile-purchase

Ask the server to check a purchase transaction. The hash is only a hint. Every fact is read from the chain, and the call is safe to repeat.

json
{ "txHash": "0x<64 hex>" }

200 with one of:

json
{ "status": "not_found" }
{ "status": "confirming", "confirmations": 1, "required": 2 }
{ "status": "confirmed", "purchases": [
    { "id": "<uuid>", "entitled": true },
    { "id": "<uuid>", "entitled": false, "reason": "buyer_wallet_not_linked" }
] }

The simple statuses are not_found, pending, failed, wrong_contract and no_license_event. The meaning of each, and of every reason, is in Purchase reconciliation results. Errors: 400 invalid_request, 401 unauthenticated.

GET /api/v1/me/compare/{runId}

Raw JSON export of a recorded comparison: the patch and base model digests, the evaluation run with target and regression counts and the rollback result, the public case summary, how many private cases were withheld, and the visible cases with inputs, expected outputs, both outputs and per-field errors. Visible to the comparison's owner, or to any signed-in user once it is shared. Sent with Cache-Control: private, no-store. Errors: 401 unauthenticated, 404 not_found.