Reference

Authentication

API keys, scopes and the request envelope.

TextToQuant exposes a small REST API you can call from any language, plus an MCP server for AI agents. The REST API and the downloadable MCP server both authenticate with the same API key and share your billing and plan limits. The hosted MCP endpoint is different: it uses OAuth (scopes mcp:read / mcp:run / mcp:write), not an API key see the MCP page for that flow.

API keys#

Create a key under Account → API keys. It's shown once, so store it safely. You can have up to 5 active keys, and revoking one cuts off access instantly.

Send the key on every request, as either header:

http
Authorization: Bearer ttq_your_key
# or
x-api-key: ttq_your_key
Plan requirement

Programmatic access requires a plan with API access. Keys are shown once at creation. Store them securely.

The response envelope#

Every response, success or failure, shares one shape. A 2xx reply is the mirror of an error:

json
// success
{ "success": true, "data": { /* … */ } }

// list endpoints also add pagination
{ "success": true, "data": { "results": [ /* … */ ] }, "pagination": { "limit": 10, "offset": 0, "total": 1, "hasMore": false } }

// error
{ "success": false, "code": "invalid_api_key", "error": "Invalid or revoked API key. Create a new one at Account → API keys." }
Branch on code, not message

The code is stable and safe to switch on; the human readable error text may be reworded. Error responses also include a requestId. Quote it when contacting support.

Rate limits#

120 requests/minute per IP and 240/minute per account, on top of your plan quotas. Every response carries standard RateLimit headers (limit, remaining, reset). Pace yourself with them. Over a limit you get a 429 with code rate_limited.

Safe retries (idempotency)#

Send an Idempotency-Key header (or idempotency_key in the body) on POST /v1/backtests. Replaying the same key with the same body within 24h returns the original run, no second credit. The same key with a different body returns 409 idempotency_key_reuse.

Error reference#

HTTPcodeWhat it means
401missing_api_keyNo key on the request: add the header
401invalid_api_keyKey is wrong, revoked, or malformed
403feature_not_availableYour plan doesn't include this feature (requiredFeature says which)
403plan_history_limit / plan_timeframe_limitDate range or timeframe beyond your plan
400invalid_query / validation_errorBad input: the message names what failed. Nothing billed
422clarification_neededParse hit ambiguous terms: data.clarificationsNeeded lists them
422missing_parametersParse missing a required field: details.missingFields + suggestions
422invalid_strategyParsed strategy isn't executable: details.structuralErrors say why
422cannot_executePre run validation failed: the message lists failing checks
409idempotency_key_reuseSame key, different body: use a fresh key
413WORKLOAD_TOO_LARGEBacktest exceeds the bar count ceiling
429rate_limitedOver the request rate: pause and retry
429OVERAGE_*Billing state gate (pending / overdue / cap reached)
404not_foundUnknown endpoint, or an id you don't own
503QUEUE_BACKPRESSURE / queue_unavailableQueue busy or down: retryable, credit refunded
500execution_failedThe run failed: nothing saved, metered credit refunded
500parse_failedParser couldn't read the query: details.suggestions hint a fix
500internal_errorUnexpected server error: safe to retry
A run timed out, did it fail?

Usually not. Backtests finish server side even if the HTTP connection drops, and the credit was already counted. Wait a moment, then call GET /v1/backtests. The newest row is your run.

Next: the endpoint reference.