RTK Card Platform API (0.2.0)

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.

Conventions

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.

system

Service health, async jobs, and platform metadata.

Health check

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.

Responses

Response samples

Content type
application/json
{
  • "status": "ok",
  • "version": "e5b7cee9d2c1f4a8b3e6d7c0a1f2b3c4d5e6f7a8"
}

Get an async job

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.

Authorizations:
apiKey
path Parameters
job_id
required
string^job_[0-9a-hjkmnp-tv-z]{26}$
Example: job_01j9zq3vp4m8x2k7r5t1w9e6ha

Job identifier (job_ prefix + 26-char lowercase ULID).

Responses

Response samples

Content type
application/json
{
  • "id": "job_01j9zq3vp4m8x2k7r5t1w9e6ha",
  • "status": "running",
  • "created_at": "2026-06-12T17:32:11Z",
  • "updated_at": "2026-06-12T17:32:42Z"
}

listings

Live eBay listings normalized into the platform catalog.

Stream listing events (SSE)

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.

Authorizations:
apiKey
header Parameters
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.

Responses

Response samples

Content type
application/problem+json
{
  • "title": "Unauthorized",
  • "status": 401,
  • "detail": "The API key is missing or invalid.",
  • "instance": "/api/v1/jobs/job_01j9zq3vp4m8x2k7r5t1w9e6ha",
  • "code": "unauthorized",
  • "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}