TensorCash.Verify

Reference

Limits and errors

Rate limits

Limits are per key. Each group is a token bucket: it holds burst tokens and refills at the per-minute rate; a request takes one token or is answered 429. If the limits do not fit your use, ask us through the portal's contact address.

Group Routes Per minute Burst In flight at once
Full /v1/verify/full… 6 3 2
Quick /v1/verify/quick…, /v1/verify/quick-smell… 60 20 20
Status /v1/verify/status…, /v1/verify/result/…, /v1/verifier/capabilities, /v1/corrections 300 60 50

Two things are not counted: a submit answered from an existing result ("cached": true, or a 200 straight from a submit) gives its token back, and status reads always do. Polling is free; poll at the interval the reply suggests, not faster.

"In flight" counts HTTP requests open at the same time. The asynchronous submit routes return at once, so the Full cap of 2 bounds simultaneous submits, not verifications in progress.

The 429 replies carry Retry-After in seconds:

{"error": "Rate limit exceeded", "retry_after": 7}
{"error": "Too many concurrent requests", "retry_after": 1}

Sizes and timeouts

What Limit
Submit body 50 MB (413 above)
Batch status body 1 MB
Any other body 16 KB
Time to send a submit body 120 s
Time a synchronous submit may hold the connection about 5 minutes
Time a status call may take 60 s
wait_ms on the batch route 0 to 10000
Connections per client address 256
Methods GET, HEAD, POST; 405 otherwise

Keys

What Limit
Keys per account 5 (revoked keys do not count)
Scopes on a portal key verify:invoke, verify:full; verify:share-mode on request
Revocation takes effect within 30 s

Errors

HTTP Body Cause What to do
400 {"detail": "Content-Type must be application/octet-stream"} Wrong content type on a submit. Fix the header.
400 {"detail": "Invalid ValidationRequest: …"} The body is not a ValidationRequest. Fix the body.
400 {"detail": "Request must be BlockValidation"} The request is not a block request. Send a BlockValidation.
400 {"detail": "ValidationRequest precheck failed"} or … hash mismatch"} The proof failed the structural check or its hashes do not match. Not retryable with the same bytes.
400 {"detail": "target_override must be 32-byte hex …"} Malformed X-Target-Override. 64 hex characters.
400 {"detail": "share-mode nonce is not derived from Proof.Hash: …"} The share's header nonce is not the first 4 bytes of the inference digest. Fix the candidate; not retryable.
400 {"detail": "X-Target-Override is not supported on /verify/quick/request/submit"} Share header on the Quick route. Use the Full or Quick-Smell route for shares.
400 {"status": "refused", "error": "share_mode_not_scoped", …} Share header together with X-Verify-Result-Contract. Drop the contract header for shares.
400 {"status": "refused", "error": "context_required", …} Scoped format without height and ruleset in the request. Fill them in.
400 {"detail": "scope_key must be 64 lowercase hex characters"} Malformed scope_key. Fix it.
400 {"detail": "items must not be empty"} Batch status with no items.
401 {"error": "Unauthorized", "detail": "Missing API key"} or "Invalid API key" No key, an unknown key, or a revoked one. Check the Authorization header; create a new key if revoked.
403 {"detail": "Insufficient permissions. Required scope: verify:full"} The key lacks verify:full. Portal keys have it.
403 {"detail": "X-Target-Override requires verify:share-mode scope; …"} Share header on a key without the scope. Ask for the scope (Verifying shares).
404 {"detail": "No cached result found"} / … for this hash_id"} Nothing known for that hash and type (for shares: the header is missing on the poll). Submit, or poll with the right type and header.
404 {"status": "unknown", "scope_key": "…"} No result and no job for that scope. Submit again.
404 empty A path that does not exist here. See the API reference.
405 empty Method not allowed.
406 {"detail": "Only JSON responses are supported"} Accept excludes JSON. Send Accept: application/json or omit it.
409 {"status": "rejected", "outcome": {"code": "CONTEXT_MISMATCH", …}} The request names another network. Not retryable; mainnet only.
413 {"detail": "Request body too large"} or empty Body above the cap.
422 validation error A malformed batch item or query parameter. Fix the request.
429 {"error": "Rate limit exceeded", "retry_after": n} Per-key limit. Wait Retry-After.
429 {"error": "Too many concurrent requests", "retry_after": 1} Too many requests open at once. Wait a second.
429 empty Connection cap per address. Reduce parallel connections.
500 {"detail": "Internal server error"} Backend fault. Retry later; tell us if it persists.
503 {"detail": "…"}, Retry-After The backend cannot take the request now (no worker, queue full, ownership unavailable). Retry after the delay.
503 {"status": "pending", "state": "needs_reverify", "outcome": {…}}, Retry-After Scoped format: no verdict this time; outcome.code says why and retryable whether to try again. Honour retryable and Retry-After.
504 {"detail": "Verification request timed out"} Synchronous route; the verification outran the budget. Use the asynchronous route.

A 5xx with an HTML body or no body came from the edge, not the backend; retry with backoff.

Retrying

Updated 2026-10-07