Reference
REST API
Every /api/v1 route with its method, path, authentication, request, response and errors.
View as MarkdownVersion 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 returns401. - 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_requestwith a message naming each bad field aspath: problem. - Visibility. Private, draft and unpublished patches return
404on 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.
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. |
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{
"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.
{ "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:
{
"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.
200 OK
content-type: application/x-tar
content-length: <bytes>
content-disposition: attachment; filename="<slug>-<version>.tar"
cache-control: no-storeErrors: 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.
{
"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.
{ "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.
{ "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.
{ "txHash": "0x<64 hex>" }200 with one of:
{ "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.