Atlas exposes a hand-curated, hardened public REST surface under /v1/. Auth, rate limits, idempotency, pagination, webhooks - everything you need to integrate, plus one-click downloads of the spec, a Postman collection, and the matching environment.
https://api-atlas.wrxstack.com/v1/openapi.jsonAll three artefacts are generated server-side from the same source of truth - the hand-written OpenAPI 3.1 doc. Nothing is stale.
atlas-public-api.openapi.json
Machine-readable spec with x-required-scopes, x-ratelimit-class, and x-rate-limits extensions.
atlas-public-api.postman_collection.json
Postman v2.1, grouped by tag. Bearer auth + Idempotency-Key + sample bodies wired to {{baseUrl}}/{{apiKey}}/{{idempotencyKey}}.
atlas-public-api.postman_environment.json
Companion environment template. Paste your PAT into apiKey and you're sending real requests.
https://api-atlas.wrxstack.com/v1/docs
Three-pane reference renderer with searchable endpoint nav, schemas, and try-it examples. Always reflects the live spec.
The whole API is one Authorization header away. Mint a Personal Access Token, then curl any /v1/ endpoint with it.
tasks:read).atlas_pat_ and is shown once.curl -H "Authorization: Bearer atlas_pat_REPLACE_ME" \
https://api-atlas.wrxstack.com/v1/tasks?limit=50Every /v1 request carries a bearer token. The same header accepts a Personal Access Token (atlas_pat_...) or a session JWT - PATs are the recommended path for server-to-server use because they're scope-bounded and revocable independently of the user's session.
Authorization: Bearer atlas_pat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxEvery 4xx and 5xx response uses RFC 9457 problem+json. Always check Content-Type - successful responses are application/json, errors are application/problem+json.
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
{
"type": "https://api.atlas-todo.com/errors/insufficient-scope",
"title": "insufficient_scope",
"status": 403,
"detail": "PAT is missing the 'tasks:write' scope.",
"missingScope": "tasks:write",
"requestId": "req_01HW3T..."
}| Status | When you see it |
|---|---|
| 400 | Body failed Zod validation. `errors[]` lists the failing fields. |
| 401 | Missing or expired token. Mint or rotate the PAT. |
| 403 (insufficient_scope) | PAT is valid but missing a required scope. |
| 403 (pat-ip-blocked) | PAT has an IP allowlist and the request came from outside it. |
| 404 | Resource not found OR the calling tenant cannot see it. |
| 409 | Optimistic-concurrency conflict - re-read and retry with the new version. |
| 422 | Request was understood but business rules rejected it (e.g. cyclic dependency). |
| 429 | Rate-limited. `Retry-After` and `X-RateLimit-Reset` headers included. |
| 5xx | Atlas is degraded. Safe to retry with exponential backoff (300ms 800ms 2s). |
Every route is classified as read, write, or ai. Each class has its own bucket per tenant; the limits below are defaults - your tenant may have a higher ceiling configured.
| Class | Default ceiling | Applies to |
|---|---|---|
read | 300/m | GET requests on /v1/* (excluding /v1/ai/*) |
write | 60/m | POST/PATCH/PUT/DELETE on /v1/* |
ai | 20/m | Any /v1/ai/* call (read or write) |
429 response shape
When you hit a bucket Atlas returns 429 with three headers: Retry-After (seconds), X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix seconds when the bucket resets). Honour Retry-After - it's authoritative.
Every POST route accepts an Idempotency-Key header. Replaying the same key (same tenant) within 24h returns the original 2xx response - verbatim, including the resource id. Crucial for safe retries on flaky networks.
curl -X POST https://api-atlas.wrxstack.com/v1/tasks \
-H "Authorization: Bearer atlas_pat_REPLACE_ME" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"projectId": "prj_...",
"title": "Review Q3 forecast",
"priority": "HIGH",
"dueOn": "2026-05-01T17:00:00Z"
}'Use a UUID per logical operation - uuidgen on the shell, randomUUID() in Node, or any stable hash you can re-derive on retry. Don't reuse a key for different requests - Atlas matches on the key, not the body.
List endpoints return a cursor: pass nextCursor back as ?cursor= to get the following page. Cursors are opaque - never parse or modify them.
# First page
curl -H "Authorization: Bearer atlas_pat_..." \
"https://api-atlas.wrxstack.com/v1/tasks?limit=50"
# { "items": [...], "nextCursor": "eyJpZCI6Li4ufQ==" }
# Next page
curl -H "Authorization: Bearer atlas_pat_..." \
"https://api-atlas.wrxstack.com/v1/tasks?limit=50&cursor=eyJpZCI6Li4ufQ=="Subscribe to delivery URLs via /v1/webhooks. Atlas signs every payload with HMAC-SHA256 and retries failed deliveries with an exponential ladder (1s 5s 25s 2m 10m 1h, capped at 24h total).
POST https://your.app/atlas-webhook
Content-Type: application/json
X-Atlas-Event: task.created
X-Atlas-Signature: sha256=...
X-Atlas-Delivery: dlv_01HW3T...# Verify the X-Atlas-Signature header (Node.js)
import crypto from 'node:crypto';
function verify(rawBody: string, headerValue: string, secret: string): boolean {
const sig = headerValue.replace(/^sha256=/, '');
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(sig, 'hex'), Buffer.from(expected, 'hex'));
}Replay any failed delivery from Settings Webhooks or via POST /v1/webhooks/{id}/deliveries/{deliveryId}/replay.
The official TypeScript client mirrors the REST surface 1:1. For AI agents, the MCP server wraps the same endpoints in a model-friendly tool catalogue.
import { createAtlasClient } from '@atlas/client';
const atlas = createAtlasClient({
baseUrl: 'https://api-atlas.wrxstack.com',
// PATs are passed verbatim - no refresh logic needed.
getAccessToken: () => process.env.ATLAS_API_KEY ?? null,
});
const { items } = await atlas.tasks.list({ limit: 50 });
const created = await atlas.tasks.create({
projectId: 'prj_...',
title: 'Review Q3 forecast',
priority: 'HIGH',
});Building an AI agent integration? See the MCP setup guide for Claude Desktop, Cursor, and Cline configuration.
The downloadable collection comes pre-wired with bearer auth, idempotency keys, sample bodies, and 2xx response examples. The companion environment file holds your token.
apiKey, and save.idempotencyKey when blank, so creates are safe to retry out of the box.Defence in depth across every public route.
x-required-scopes on every operation.PUBLIC_API_RATE_OVERRIDES env JSON.allowedIps; calls from outside fail with 403 pat-ip-blocked.Idempotency-Key twice within 24h. That's by design - the second call returns the original 2xx response so you don't double-create. Use a fresh UUID for each logical create.version field as If-Match: <version>. If the task changed in the meantime you'll get a 409; re-read, merge, and retry.baseUrl at the sandbox URL.info.version on breaking changes.