Rate Limits
The Varity platform API (https://varity.app/api) has no per-route request budgets. Two limits can answer 429, and they mean different things.
Deployment Queue Backpressure
Section titled “Deployment Queue Backpressure”Creating a deployment or a machine is admitted into a platform-wide queue. When that queue is full, the create is refused before anything is allocated or charged:
{ "code": "queue_saturated", "message": "The deployment queue is full right now. Try again shortly.", "retryable": true, "docs_url": "https://docs.varity.so/api/errors#queue_saturated", "correlation_id": "..."}queue_saturated is always retryable: true. Wait a few seconds and retry the same request with the same Idempotency-Key (below), so a retry can never create a second deployment or machine. Reads, logs, and deletes are not queued. Stopping a resource is never throttled: a resource you cannot turn off keeps billing.
Abuse Protection At The Edge
Section titled “Abuse Protection At The Edge”The edge in front of varity.app applies a per-client abuse limit. It is set far above what a portal session, the CLI, the MCP server, or an SDK loop sends, so a normal integration never meets it. A client that does is answered with a plain-text 429 Too Many Requests from the edge, without the JSON error envelope. Slow down and retry with backoff and jitter.
import time, random, requests
def call(method, url, **kw): for attempt in range(6): r = requests.request(method, url, **kw) if r.status_code != 429: return r time.sleep(2 ** attempt + random.uniform(0, 1)) # backoff with jitter raise RuntimeError("still limited")Every response carries an x-request-id header. Send your own X-Request-Id and it is echoed back as correlation_id in any error body. See API Errors.
Per-plan account limits are planned. When they ship, they will be documented on this page.
Retries And Duplicate Resources
Section titled “Retries And Duplicate Resources”Retrying a create after a 429 is safe only if it is idempotent. Send an Idempotency-Key on every create so a retry cannot produce a second deployment or machine:
curl -X POST https://varity.app/api/deployments \ -H "Authorization: Bearer $VARITY_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: deploy-my-app-001" \ -d '{ "name": "my-app", "repository": { "url": "https://github.com/me/my-app" } }'Idempotency-key validation is route-specific. Deployment and template creates
accept an optional key up to 160 characters. Machine create and delete require
[A-Za-z0-9._:-]{8,128}. AI Gateway attachment mutations require the same
character set with a length of 1 to 160. Follow the operation’s schema in the
OpenAPI document. Replaying the same key with the same body
returns the original result; reusing it with a different body returns
409 idempotency_key_reused. See API Errors.
Other Limits
Section titled “Other Limits”Some limits are enforced by the resource contract rather than by a request budget:
- Health history:
GET /api/deployments/{id}/health-historyacceptslimitwith a default of 100 and a maximum of 500 observations. - Idempotency keys: constraints differ by operation; use the OpenAPI parameter on the route you are calling. Records are retained for 24 hours.
The AI Gateway (https://ai.varity.app/v1) is a separate surface with its own independent rate-limit, concurrency, and budget admission controls. Limits documented here do not apply to it. See AI Gateway Rate Limits.
Next Steps
Section titled “Next Steps”- API Errors: the error envelope and every verified error code
- Public API Reference: endpoints and examples
- AI Gateway Rate Limits: the separate controls for
ai.varity.app/v1