API reference

Version MVP

Datorus API reference: authentication, the proxy gateway endpoint, sticky sessions, rate limits, the canonical error envelope, and all 18 error codes.

Authentication

Datorus uses HTTP Basic auth over the proxy gateway. Send your gateway username and password with every request; route the request through the gateway with your HTTP client's proxy option. New here? Start with the price-monitoring quickstart.

curl -x http://USERNAME:PASSWORD@gw.datorus.io:8001 \
     -L https://target.example.com/products

Endpoints

GETgw.datorus.io:8001 is the proxy gateway — point any HTTP client's proxy setting at it. Datorus relays your request to the destination and returns the upstream response unchanged. There is no Datorus REST API surface for the proxy itself; you talk to your target through the gateway.

Sessions

By default each connection gets a fresh upstream session. To reuse one upstream session across a multi-step flow, send a session id header.

Live: send X-Datorus-Session-Id — an opaque id you generate (allowed characters A–Z a–z 0–9 _ -, up to 128 chars) — to pin a multi-step flow to a stable upstream egress. The gateway honours the header, echoes the same id back on the response, and scopes the affinity to your account, so your id can never collide with another customer's session. An invalid or absent header falls back to the default per-connection session (it is never an error). The exact affinity window (TTL), rotation, and concurrency limits are being finalized in Phase 7 load testing — subscribe to the changelog for the published values.

Rate limits

Live: the gateway emits X-Datorus-RateLimit-Limit, X-Datorus-RateLimit-Remaining, and X-Datorus-RateLimit-Reset on every response, and a 429 includes a Retry-After header per RFC 7231. The per-credential limit is a soft limit while we finish Phase 7 load testing; the headers always reflect the limit currently in force. The final concrete numbers (requests/second, burst) ship after load testing — subscribe to the changelog for the published values.

Error responses

Every error uses one canonical JSON envelope. The machine-readable code is SCREAMING_SNAKE_CASE and is never translated; message is English-only; requestId is a UUID; timestamp is ISO 8601 UTC.

{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Your balance is too low to complete this request.",
    "details": { "currentBalanceCents": 0, "requiredCents": 120 },
    "requestId": "0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01",
    "timestamp": "2026-05-19T14:32:18Z"
  }
}

The Example response column is the complete error envelope for each code (code + message + details + requestId + timestamp); requestId and timestamp vary per request. message is English-only regardless of locale.

CodeHTTPWhen it happensExample response
VALIDATION_ERROR400The request was malformed or a field failed validation.{"error":{"code":"VALIDATION_ERROR","message":"The submitted data is invalid.","details":{"field":"step","reason":"must be 4 or 5"},"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
TOKEN_INVALID400A signup/verification token could not be parsed.{"error":{"code":"TOKEN_INVALID","message":"The token is invalid.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
TOKEN_EXPIRED410A signup/verification token has expired.{"error":{"code":"TOKEN_EXPIRED","message":"The token has expired.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
TOKEN_USED409A signup/verification token was already consumed.{"error":{"code":"TOKEN_USED","message":"The token was already used.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
INSUFFICIENT_BALANCE402A paid account's balance is too low for the request.{"error":{"code":"INSUFFICIENT_BALANCE","message":"Your balance is too low to complete this request.","details":{"currentBalanceCents":0,"requiredCents":120},"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
TRIAL_EXHAUSTED402The free-trial allocation is used up — top up to continue.{"error":{"code":"TRIAL_EXHAUSTED","message":"Your free trial is used up.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
STRIPE_DECLINED402The card was declined during a top-up.{"error":{"code":"STRIPE_DECLINED","message":"The card was declined.","details":{"declineCode":"card_declined"},"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
STRIPE_3DS_REQUIRED402The card requires 3-D Secure authentication.{"error":{"code":"STRIPE_3DS_REQUIRED","message":"Card authentication is required.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
AUP_VIOLATION403The request violates the Acceptable Use Policy.{"error":{"code":"AUP_VIOLATION","message":"This request violates the Acceptable Use Policy.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
ACCOUNT_SUSPENDED403The account is suspended.{"error":{"code":"ACCOUNT_SUSPENDED","message":"This account is suspended.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
RESOURCE_NOT_FOUND404The requested resource does not exist.{"error":{"code":"RESOURCE_NOT_FOUND","message":"The requested resource was not found.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
INVALID_CREDENTIAL407The gateway rejected your proxy username or password.{"error":{"code":"INVALID_CREDENTIAL","message":"Invalid proxy credentials.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
EMAIL_TAKEN409An account already exists for this email.{"error":{"code":"EMAIL_TAKEN","message":"An account with this email already exists.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
EMAIL_PROVIDER_MISMATCH409This email is registered with a social-login provider.{"error":{"code":"EMAIL_PROVIDER_MISMATCH","message":"This email uses a social-login provider.","details":{"provider":"google"},"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
RATE_LIMITED429Too many requests — back off and retry after Retry-After.{"error":{"code":"RATE_LIMITED","message":"Too many requests.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
UPSTREAM_FAILED502The destination returned an invalid or unreachable response.{"error":{"code":"UPSTREAM_FAILED","message":"The upstream destination failed.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
SERVICE_UNAVAILABLE503The gateway is temporarily unavailable — retry shortly.{"error":{"code":"SERVICE_UNAVAILABLE","message":"The service is temporarily unavailable.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}
GATEWAY_TIMEOUT504The destination took too long to respond.{"error":{"code":"GATEWAY_TIMEOUT","message":"The upstream destination timed out.","details":null,"requestId":"0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01","timestamp":"2026-05-19T14:32:18Z"}}

Reserved headers

The Status column is honest about what the gateway sends today. These headers ride the HTTP forward response and the CONNECT 200 Connection established (both are proxy-layer headers the gateway controls); the inner tunneled HTTPS payload is end-to-end encrypted, so the proxy cannot add headers there.

HeaderDirectionStatusDescriptionExample
X-Datorus-Used-Bytesresponselive (on 402)Bytes this request consumed against your trial/balance.421
Retry-Afterresponse (429)liveSeconds (or HTTP date) to wait before retrying, per RFC 7231.120
X-Datorus-Request-IdresponselivePer-request id, 1:1 with the envelope requestId.0190f8c2-7a3b-4d8e-9f1c-2b5e8a4d6f01
X-Datorus-Session-Idrequest + responseliveClient-generated id to activate a sticky session; echoed back.7f3a9b2c-1d4e-4a8f-b0c2-9e5d7a3f6b21
X-Datorus-RateLimit-LimitresponseliveCurrent rate limit (requests/second); the concrete value is being finalized in load testing.(varies)
X-Datorus-RateLimit-RemainingresponseliveRequests remaining in the window.7
X-Datorus-RateLimit-ResetresponseliveUnix timestamp when the window resets.1748345538

Idempotency

Proxy requests are not idempotent by nature — they are forwarded to your target as sent. Billing top-ups use Stripe's idempotency keys internally so a retried checkout never double-charges.

Webhooks

Datorus does not deliver outbound webhooks for proxy traffic. Billing events are handled internally via Stripe; you do not need to host a webhook endpoint.

OpenAPI

A machine-readable OpenAPI description is planned. Until then, this page is the reference — subscribe to the changelog for updates.

On this page