Download OpenAPI specification:
Public API for the RTK card platform: catalog, listings, sold comps, pricing, inventory, outcomes, and PSA vault. The /api/v1 surface is the stable, token-authenticated contract consumed via the published SDK.
IDs are opaque, prefixed strings: <prefix>_<26-char lowercase ULID> (e.g. lst_01j9zq3vp4m8x2k7r5t1w9e6ha). Do not parse them; treat them as stable handles. Prefixes are self-identifying (card_, lst_, comp_, bid_, job_, ...).
Money is always an integer amount in minor units (cents) plus an ISO 4217 currency code: {"amount": 12999, "currency": "USD"}. No floats, ever.
Timestamps are RFC 3339 UTC with a Z suffix; field names end in _at.
Collections return the envelope {"items": [...], "pagination": {"next_cursor", "has_more", "limit"}, "meta": {...}} with opaque cursor pagination. meta carries opt-in aggregates requested via ?include=total_count,total_amount (comma list); each endpoint documents which aggregates it supports, and unbounded feeds (listings, comps) support none. Changing filters invalidates a cursor (400, code invalid_cursor). Single resources are returned bare.
Errors are RFC 9457 application/problem+json on every non-2xx response. Switch on the stable machine code; quote trace_id when contacting support.
Every response carries an X-Request-Id header (the request's trace id) — success and error alike.
Every authenticated response also carries the rate-limit trio X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset — on errors (401/403/404/429/500) as well as success, so a client can read its remaining budget no matter the outcome. The unauthenticated /api/v1/health endpoint is the sole exception (it is not rate-limited).
Mutating requests (POST/PUT/PATCH/DELETE) require an Idempotency-Key header (UUIDv4). Replays return the original response; the same key with a different body returns 409, code idempotency_conflict.
Request bodies are capped at 1 MiB. A larger body is rejected with 413, code request_too_large, before the handler reads it; for bulk data use the documented batch or cursor-paginated endpoints rather than one oversized payload.
Async jobs: operations that cannot complete synchronously return 202 Accepted with a Job resource (job_<ulid>); poll GET /api/v1/jobs/{job_id} until status is succeeded or failed, then follow result_url.
Enums are open: clients must tolerate unknown enum values; new values are additive, not breaking.
Returns the service health status and the running build version (git SHA or release tag). Unauthenticated and not rate-limited; used by SDK smoke tests and synthetic canaries to assert what build is live. No dependency probing — deep health checks are internal only.
{- "status": "ok",
- "version": "e5b7cee9d2c1f4a8b3e6d7c0a1f2b3c4d5e6f7a8"
}Fetches the status of an asynchronous job. Async operations return 202 Accepted with a Job resource; poll this endpoint until the job reaches succeeded or failed, then follow result_url.
Not yet implemented. This endpoint reserves the platform's async-job convention; no operations create jobs yet, so every request currently returns 404 (code not_found). It becomes live with the first async operation.
| job_id required | string^job_[0-9a-hjkmnp-tv-z]{26}$ Example: job_01j9zq3vp4m8x2k7r5t1w9e6ha Job identifier ( |
{- "id": "job_01j9zq3vp4m8x2k7r5t1w9e6ha",
- "status": "running",
- "created_at": "2026-06-12T17:32:11Z",
- "updated_at": "2026-06-12T17:32:42Z"
}Server-sent events feed of listing lifecycle events (listing.created, listing.updated). Each SSE data: payload is a JSON ListingEvent; the SSE id: field carries an event id usable as Last-Event-ID on reconnect for gapless resumption.
Future endpoint — reserved, not yet implemented. Documented now to fix the push-feed transport (SSE over one ALB/HTTP stack, native auth headers, trivial reconnect). Calling it today returns 501. It ships with M1 listings.
| Last-Event-ID | string Example: evt_01j9zq3vp4m8x2k7r5t1w9e6ha Standard SSE reconnection header: the last event id the client processed. The stream resumes after this event when it is still retained. |
{- "title": "Unauthorized",
- "status": 401,
- "detail": "The API key is missing or invalid.",
- "instance": "/api/v1/jobs/job_01j9zq3vp4m8x2k7r5t1w9e6ha",
- "code": "unauthorized",
- "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}