API Endpoints
This page provides a complete reference of all available API endpoints.
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
Error Responses​
These error responses are shared across endpoints. Each endpoint's own Error Responses table lists the statuses it declares and links back here.
Payment Required​
Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). The API key is preserved; access resumes automatically once the subscription is active again. Emitted by the EnsureActiveSubscription middleware (issue #2038).
{
"errors": [
{
"status": "402",
"code": "SUBSCRIPTION_REQUIRED",
"title": "Payment Required",
"detail": "An active subscription is required to access this endpoint. Subscribe or update your billing to restore access; your API key is preserved and access resumes automatically once your subscription is active."
}
]
}
Bad Request​
Bad Request — the query string contains a parameter this endpoint does not accept, or the requested page size exceeds the maximum of 100. Unrecognized parameters are rejected rather than ignored, so a misspelled filter can never silently return the full unfiltered collection (issue #2305). One error object is returned per offending parameter, each naming it in source.parameter, and the detail lists every parameter the endpoint does accept.
{
"errors": [
{
"status": "400",
"code": "INVALID_PARAMETER",
"title": "Unknown query parameter",
"detail": "The query parameter 'name' is not supported by this endpoint. Accepted parameters are: first_name, full_name, include, last_name, limit, order_by, page, per_page, sort.",
"source": {
"parameter": "name"
}
}
]
}
Too Many Requests​
Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Every published endpoint except GET /health and POST /webhooks/stripe is throttled by the api limiter, whose quota is chosen per caller: anonymous requests (no bearer token) get the anonymous tier, and an authenticated request gets, in precedence order, its OAuth client's per-client rate_limit override, the internal-caller pool if the client row is flagged is_internal, or the default authenticated tier. See config/ratelimiting.php for the current values. A few public endpoints stack a tighter named per-IP limiter on top of the api bucket (signup, verification resend, invite validation), so they can return a 429 well before the api quota is spent — those operations describe the extra limit in their own description.
{
"errors": [
{
"status": "429",
"code": "TOO-MANY-REQUESTS",
"title": "Too many requests.",
"detail": "You have sent too many requests in a given amount of time. Please retry after a short delay."
}
]
}
Unprocessable Entity​
Unprocessable Entity — the request document failed validation. One error object is returned per offending field per rule, each naming the field with an RFC 6901 JSON Pointer in source.pointer (bare field names are rooted under /data/attributes/). The detail carries the human-readable validation message.
{
"errors": [
{
"status": "422",
"code": "VALIDATION-FAILED",
"title": "Validation failed",
"detail": "The name field is required.",
"source": {
"pointer": "/data/attributes/name"
}
},
{
"status": "422",
"code": "VALIDATION-FAILED",
"title": "Validation failed",
"detail": "The selected year id is invalid.",
"source": {
"pointer": "/data/attributes/year_id"
}
}
]
}
Health​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /health​
Liveness/readiness healthcheck (infrastructure)
Infrastructure healthcheck for load balancers and uptime monitors. Returns 200 when the database and cache are reachable, or 503 when a dependency check fails. Unauthenticated, unthrottled, and excluded from API usage logging. Not a public API feature. The checks.billing key is advisory only: it reports degraded when billing or lifecycle-email configuration is incomplete and never affects the status code.
Authentication: Public — no API token required.
Example Request​
curl -X GET "https://api.tradingcardapi.com/health" \
-H "Accept: application/json"
Example Response​
{
"status": "ok",
"version": "0.2.84",
"checks": {
"database": "ok",
"cache": "ok",
"billing": "ok"
}
}
Error Responses​
| Status | Description |
|---|---|
| 503 | At least one dependency check failed; the app is not ready to serve traffic |
Internal​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /internal/analytics/customer-usage​
Per-customer API usage (internal)
Returns one row per customer (a user with a billing account or a live API key) with the request count and last-request time over an inclusive UTC date range. Customers with no requests in range are included with request_count 0. request_count counts requests made with the customer's API key (credential_type api_key); requests_by_credential reports every credential type. Usage cannot be attributed per key, so each row reports the customer's current key metadata. The usage log keeps 30 days; meta.oldest_log_at marks the oldest retained row. Requires the 'internal' OAuth scope.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| from | string | No | First day of the range (Y-m-d, UTC). Defaults to 6 days before to. |
| to | string | No | Last day of the range (Y-m-d, UTC), inclusive. Defaults to today. The span may not exceed 31 days. |
| user | string | No | Restrict to one customer by user id |
| paying_only | boolean | No | Only customers whose subscription status is active (trials excluded) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/analytics/customer-usage" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "customer-usage",
"id": "string",
"attributes": {}
}
],
"meta": {}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 403 | Missing the 'internal' scope |
| 422 | Invalid date, range, user, or paying_only parameter |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /internal/analytics/sales-readiness​
Sales readiness report (internal)
Returns the analyze:sales-readiness data-coverage report. Requires the 'internal' OAuth scope. Use format=json (default) for the structured payload or format=table for the rendered text table.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| format | string | No | Output format: json (default) or table |
| years | integer | No | Number of most recent years to include in year coverage (must be a positive integer) |
| months | integer | No | Number of most recent months for the update-cadence window (positive integer) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/analytics/sales-readiness" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 403 | Missing the 'internal' scope |
| 422 | Invalid format, years, or months parameter |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /internal/audit-logs​
List audit log events (internal)
Retrieve audit log events with optional filtering by entity, event type, and date range. Defaults to last 30 days when no date filters are provided. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| filter[auditable_type] | string | No | Filter by entity type (e.g. set, card, player, team) |
| filter[auditable_id] | string | No | Filter by entity UUID |
| filter[event_type] | string | No | Filter by event type |
| filter[start_date] | string | No | Filter events on or after this date (ISO 8601) |
| filter[end_date] | string | No | Filter events on or before this date (ISO 8601) |
| per_page | integer | No | Number of results per page (default 50, max 500) |
| page | integer | No | Page number |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/audit-logs" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "audit_logs",
"id": 12345,
"attributes": {
"event_type": "agent_spawned",
"auditable_type": "set",
"auditable_id": "string",
"agent_id": "agent-abc-123",
"data": {},
"created_at": "string"
}
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /internal/audit-logs​
Create an audit log event (internal)
Record a new audit log event. Supports polymorphic association with any entity. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "audit_logs" | |
| data.attributes | object | No | No | ||
| data.attributes.event_type | string | Yes | No | "agent_spawned" | |
| data.attributes.auditable_type | string | No | Yes | "set" | |
| data.attributes.auditable_id | string (uuid) | No | Yes | "550e8400-e29b-41d4-a716-446655440000" | |
| data.attributes.agent_id | string | No | Yes | "agent-abc-123" | |
| data.attributes.data | object | No | Yes | {"step":"populate","status":"started"} |
Example Request​
curl -X POST "https://api.tradingcardapi.com/internal/audit-logs" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"audit_logs","attributes":{"event_type":"agent_spawned","auditable_type":"set","auditable_id":"550e8400-e29b-41d4-a716-446655440000","agent_id":"agent-abc-123","data":{"step":"populate","status":"started"}}}}'
Example Response​
{
"data": {
"type": "audit_logs",
"id": 12345,
"attributes": {
"event_type": "agent_spawned",
"auditable_type": "set",
"auditable_id": "string",
"agent_id": "agent-abc-123",
"data": {},
"created_at": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /internal/card-batches​
Upsert a batch of cards by client-supplied UUID (internal)
Idempotently upserts a batch of cards keyed on client-generated UUIDs: a row whose id is unknown is created, a row whose id already exists is updated, and a re-send of an unchanged batch is a no-op rather than a duplicate. Rows are written one transaction each, so a single bad row fails in isolation and is reported in results instead of aborting the batch. Batches at or under the sync threshold (config api.card_batch.sync_threshold) are processed inline and answered 200 with the full per-row result set; larger batches are queued and answered 202 with a job_id to poll via GET /internal/card-batches/{job_id}. Batch upserts do NOT trigger automatic parallel-card propagation — the caller is expected to supply its parallels explicitly with derived ids. Set meta.propagate to true to opt back in. Internal endpoint: requires the internal OAuth scope.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | array of object | Yes | No | Card resource objects. Each requires a client-generated uuid id. | |
| data[].type | string | Yes | No | "cards" | |
| data[].id | string (uuid) | Yes | No | ||
| data[].attributes | object | No | No | ||
| data[].relationships | object | No | No | ||
| meta | object | No | No | ||
| meta.propagate | boolean | No | No | Allow automatic parallel-card propagation for these rows. |
Example Request​
curl -X POST "https://api.tradingcardapi.com/internal/card-batches" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":[{"type":"cards","id":"string","attributes":{},"relationships":{}}],"meta":{"propagate":false}}'
Example Response​
{
"status": "completed",
"job_id": null,
"total": 1,
"created": 1,
"updated": 0,
"failed": 0,
"results": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "created",
"restored": null,
"error": null
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Missing the required internal OAuth scope |
| 422 | Validation error |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /internal/card-batches/{job_id}​
Poll the status of an async card-batch upsert (internal)
Returns the current status of a queued card-batch upsert. The job_id comes from the 202 response of POST /internal/card-batches. Results are retained for 24 hours after completion. Internal endpoint: requires the internal OAuth scope.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| job_id | string | Yes | Job UUID returned by the async card-batch request |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/card-batches/{job_id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"status": "completed",
"job_id": "3f2504e0-4f89-11d3-9a0c-0305e82c3301",
"total": 1,
"created": 1,
"updated": 0,
"failed": 0,
"results": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "created",
"restored": null,
"error": null
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Missing the required internal OAuth scope |
| 404 | Batch job not found or expired |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /internal/invites​
List signup invites (internal)
Lists issued invites with their label, pinned email, use counts, expiry and revocation state. Internal endpoint: requires the internal OAuth scope.
The plaintext code is NEVER returned here — it is surfaced exactly once at issuance and only its SHA-256 hash is stored.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/invites" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 403 | Missing the internal OAuth scope |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /internal/invites​
Issue a signup invite (internal)
Mints a new invite code and returns its plaintext EXACTLY ONCE — only the SHA-256 hash is persisted, so the code cannot be retrieved afterward. Internal endpoint: requires the internal OAuth scope.
All attributes are optional; an empty body issues a single-use, unpinned invite with the configured default TTL. Supply max_uses for a cohort code, email to pin the invite to one address, and expires_at: null for an invite that never expires.
The code attribute seeds a caller-supplied plaintext instead of minting one. It exists for the cutover from the marketing site's single shared code, so links already in a cohort's hands keep working when enforcement deploys.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "invites" | |
| data.attributes | object | No | No | ||
| data.attributes.label | string | No | Yes | ||
| data.attributes.email | string (email) | No | Yes | ||
| data.attributes.max_uses | integer | No | No | 1 | |
| data.attributes.expires_at | string (date-time) | No | Yes | ||
| data.attributes.code | string | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/internal/invites" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"invites","attributes":{"label":"string","email":"string","max_uses":1,"expires_at":"string","code":"string"}}}'
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 403 | Missing the internal OAuth scope |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /internal/sets/{set}/todos​
List the workflow todos for a set (internal)
Returns the set's workflow todos ordered by sort_order. Returns an empty collection when the set exists but has no workflow initialized. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the parent set |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/sets/{set}/todos" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "set_todos",
"id": "string",
"attributes": {
"step": "fetch",
"status": "in_progress",
"sort_order": 1,
"started_at": "string",
"completed_at": "string",
"completed_by": "admin",
"notes": "string",
"created_at": "string",
"updated_at": "string"
}
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 404 | Set not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /internal/sets/{set}/todos​
Create a workflow todo for a set (internal)
Create a new workflow todo on the set's workflow. The todo is bound to the set's existing workflow; the set must already have one. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the parent set |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "set_todos" | |
| data.attributes | object | No | No | ||
| data.attributes.step | string | Yes | No | "fetch" | |
| data.attributes.status | string | Yes | No | "pending" | |
| data.attributes.sort_order | integer | No | Yes | ||
| data.attributes.notes | string | No | Yes | ||
| data.attributes.completed_by | string | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/internal/sets/{set}/todos" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"set_todos","attributes":{"step":"fetch","status":"pending"}}}'
Example Response​
{
"data": {
"type": "set_todos",
"id": "string",
"attributes": {
"step": "fetch",
"status": "in_progress",
"sort_order": 1,
"started_at": "string",
"completed_at": "string",
"completed_by": "admin",
"notes": "string",
"created_at": "string",
"updated_at": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 404 | Set or workflow not found |
| 409 | A todo for this step already exists on the workflow (unique_workflow_step constraint) |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /internal/sets/{set}/todos/{todo}​
Get a single workflow todo for a set (internal)
Returns a single todo scoped to the parent set. A todo from a different set returns 404. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the parent set |
| todo | string | Yes | UUID of the set todo |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/sets/{set}/todos/{todo}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "set_todos",
"id": "string",
"attributes": {
"step": "fetch",
"status": "in_progress",
"sort_order": 1,
"started_at": "string",
"completed_at": "string",
"completed_by": "admin",
"notes": "string",
"created_at": "string",
"updated_at": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 404 | Todo not found for this set |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /internal/sets/{set}/todos/{todo}​
Delete a workflow todo for a set (internal)
Delete a todo scoped to the parent set. A todo from a different set returns 404. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the parent set |
| todo | string | Yes | UUID of the set todo to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/internal/sets/{set}/todos/{todo}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 404 | Todo not found for this set |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /internal/sets/{set}/todos/{todo}​
Update a set todo step status (internal)
Transition a workflow step. Enrichment steps skip ordering; others need prior completion. The todo is scoped to the parent set; a todo from a different set returns 404. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the parent set |
| todo | string | Yes | UUID of the set todo to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "set_todos" | |
| data.attributes | object | No | No | ||
| data.attributes.status | string | Yes | No | "in_progress" | |
| data.attributes.notes | string | No | Yes | ||
| data.attributes.completed_by | string | No | Yes | ||
| data.attributes.issues_found | boolean | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/internal/sets/{set}/todos/{todo}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"set_todos","attributes":{"status":"in_progress"}}}'
Example Response​
{
"data": {
"type": "set_todos",
"id": "string",
"attributes": {
"step": "fetch",
"status": "in_progress",
"sort_order": 1,
"started_at": "string",
"completed_at": "string",
"completed_by": "admin",
"notes": "string",
"created_at": "string",
"updated_at": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 404 | Todo not found for this set |
| 422 | Validation error or dependency not met |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /internal/sets/{set}/workflow​
Get the workflow state for a set (internal)
Returns the workflow record and its todos for the given set. Returns {"workflow": null} (200) when the set exists but has no workflow initialized. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | Set UUID |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/sets/{set}/workflow" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"workflow": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"set_id": "661f9511-f30c-52e5-b827-557766551111",
"priority": 1,
"current_step": "fetch",
"todos": [
{
"id": "772a0622-a41d-43f6-c938-668877662222",
"step": "discover_sources",
"status": "completed",
"sort_order": 1,
"started_at": "2024-03-15T09:00:00+00:00",
"completed_at": "2024-03-15T09:15:00+00:00",
"notes": null
},
{
"id": "883b1733-b52e-44a7-d049-779988773333",
"step": "fetch",
"status": "in_progress",
"sort_order": 2,
"started_at": "2024-03-15T09:20:00+00:00",
"completed_at": null,
"notes": "Retrying after transient 502 from source."
}
],
"created_at": "2024-03-15T08:00:00+00:00",
"updated_at": "2024-03-15T10:30:00+00:00"
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 404 | Set not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /internal/actionable-sets​
Get sets that are actionable for a given workflow step (internal)
Returns sets where the given step matches the requested status (default: pending). For pipeline steps with pending status, all prior steps must be completed or skipped. Enrichment steps bypass this requirement. Use status=review to find sets needing human intervention. Each row includes the current todo_id (for PATCH operations) and notes (the review reason when status=review). Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| step | string | Yes | Workflow step (discover_sources, fetch, parse, populate, validate, cleanup, publish, audit) |
| status | string | No | Filter by todo status (default: pending). Use 'review' to find sets needing human intervention. |
| limit | integer | No | Maximum number of results to return (1–100, default 25) |
| priority | string | No | Priority filter: 'current' (current year), 'backlog' (prior years), or 'all' (default) |
| genre_id | string | No | Filter by genre UUID |
| year | string | No | Filter by year name (e.g. '2025', '2025-26') |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/actionable-sets" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"todo_id": "string",
"set_id": "string",
"set_name": "string",
"genre": "string",
"year": "string",
"step": "string",
"priority": 0,
"card_count": 0,
"has_sources": false,
"notes": "string",
"updated_at": "2025-01-15T13:45:30+00:00"
}
],
"meta": {
"total": 0,
"full_total": 0,
"step": "string",
"status": "string",
"priority_filter": "string"
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
| 503 | Service unavailable — query timed out |
GET /internal/actionable-sets/count​
Count sets that are actionable for a given workflow step (internal)
Returns the unpaginated count of sets that are actionable for the given step, using the exact same filters as GET /internal/actionable-sets (step, status, priority, genre_id, year) but without materializing the row page or the per-row card_count / has_sources subqueries. The returned count is consistent with that endpoint's full_total for identical filters. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| step | string | Yes | Workflow step (discover_sources, fetch, parse, populate, validate, cleanup, publish, audit) |
| status | string | No | Filter by todo status (default: pending). Use 'review' to find sets needing human intervention. |
| priority | string | No | Priority filter: 'current' (current year), 'backlog' (prior years), or 'all' (default) |
| genre_id | string | No | Filter by genre UUID |
| year | string | No | Filter by year name (e.g. '2025', '2025-26') |
| limit | integer | No | Accepted for request-shape parity with GET /internal/actionable-sets but ignored: this endpoint returns an unpaginated count, so no row cap applies. Still validated (integer, 1-100) — an out-of-range value yields 422. |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/actionable-sets/count" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"count": 0,
"meta": {
"step": "string",
"status": "string",
"priority_filter": "string"
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
| 503 | Service unavailable — query timed out |
POST /internal/todo-initialization-jobs​
Bulk-initialize workflow todos for pre-existing sets (internal)
Initializes workflow todos for sets that have no existing workflow. Sets with existing workflows or published status are counted as skipped. When more than 100 sets would be processed, the operation is dispatched as a background job. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| set_ids | array of string | No | No | Specific set UUIDs to initialize. Mutually exclusive with all_draft. | |
| all_draft | boolean | No | No | Initialize all draft sets without existing workflows. | |
| genre_id | string (uuid) | No | No | Filter by genre (only valid with all_draft). | |
| year | string | No | No | Filter by year name, e.g. '2025' (only valid with all_draft). |
Example Request​
curl -X POST "https://api.tradingcardapi.com/internal/todo-initialization-jobs" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"set_ids":["string"],"all_draft":false,"genre_id":"string","year":"string"}'
Example Response​
{
"initialized": 0,
"skipped": 0,
"errors": [
{}
],
"job_id": "string",
"resolved_count": 0,
"meta": {
"total_draft_sets": 0,
"draft_with_workflow": 0,
"draft_without_workflow": 0
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /internal/todo-initialization-jobs/{job_id}​
Poll the status of an async bulk-initialize job (internal)
Returns the current status of a background bulk-initialize job. The job_id is obtained from the 202 response of POST /internal/todo-initialization-jobs. Results are retained for 24 hours after job completion. Internal endpoint: requires the internal OAuth scope (#1557).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| job_id | string | Yes | Job UUID returned by the async bulk-initialize request |
Example Request​
curl -X GET "https://api.tradingcardapi.com/internal/todo-initialization-jobs/{job_id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"status": "completed",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"initialized": 42,
"skipped": 3,
"errors": [],
"resolved_count": 45,
"meta": null
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 403 | Forbidden - missing the internal scope |
| 404 | Job not found or expired |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
Webhooks​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
POST /webhooks/stripe​
Stripe webhook receiver (infrastructure)
Receives Stripe webhook events. Unauthenticated — the Stripe-Signature header verified against the configured signing secret is the authentication. Returns 200 on accepted (including duplicate and unknown event types) and 400 on signature verification failure. Not a public API feature.
Authentication: Public — no API token required.
Example Request​
curl -X POST "https://api.tradingcardapi.com/webhooks/stripe" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 400 | Signature verification failed or payload malformed |
Authentication​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/user/api-key​
Get the authenticated user's API key (masked)
Returns masked metadata for the authenticated end user's single opaque API key. Never returns the plaintext key. If no key exists yet, data is null.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/user/api-key" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not read its owner's API-key metadata |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/user/api-key​
Regenerate the authenticated user's API key
Revokes the user's existing API key (if any) and issues a new opaque tc_live_ key. Returns the plaintext key exactly once, alongside masked metadata. The previous key stops authenticating immediately.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/user/api-key" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not rotate its owner's API key |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
DELETE /v1/user/api-key​
Revoke the authenticated user's API key
Revokes the user's existing opaque tc_live_ key (if any) without minting a replacement. The key stops authenticating immediately. Idempotent: a no-op 204 when the user has no live key. To rotate the key instead, POST the same path.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/user/api-key" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not revoke its owner's API key |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/invites/validate​
Validate a signup invite code (v1)
Reports whether an invite code may currently be used to create an account. Public (no authentication) so the marketing site's signup page can check the link a visitor arrived on before rendering a form.
This endpoint CONSUMES NOTHING and reserves nothing: a valid verdict means the code is live and had a use left at the moment of the check, not that a use — or a founding slot — is held for the caller. Enforcement happens again at POST /v1/signup.
Rejections carry a distinguishable code: invite_invalid (unknown, revoked, or pinned to a different address), invite_expired (410, renewable), or invite_exhausted (every use spent). The code must be sent in the JSON body; a code in the query string is ignored, since a query string is recorded by proxies and travels onward in Referer. Throttled by throttle:invite-validate per IP and per code so the endpoint is not a brute-force oracle.
Authentication: Public — no API token required.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "invite-validations" | |
| data.attributes | object | No | No | ||
| data.attributes.code | string | Yes | No | "FOUNDING-2026" |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/invites/validate" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"invite-validations","attributes":{"code":"FOUNDING-2026"}}}'
Error Responses​
| Status | Description |
|---|---|
| 410 | Invite code has expired |
| 422 | Invite code is missing, unknown, revoked, or fully used |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /v1/me​
Get the authenticated user (v1)
Returns the currently authenticated user as a JSON:API resource exposing name, email, company, and the plan / subscription status / trial end mirrored from the user's billing account (null when the user has no billing account).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/me" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "users",
"id": "9b1c1e2a-3f4d-4a5b-8c6d-7e8f9a0b1c2d",
"attributes": {
"name": "Jane Doe",
"company": "Acme Corp",
"plan": "pro_monthly",
"subscription_status": "active",
"trial_ends_at": "2026-07-15T00:00:00+00:00"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
DELETE /v1/me​
Delete the authenticated user's account and associated data (v1)
Irreversibly deletes the authenticated user's own account (issue #1979). Requires an interactive first-party session (a Passport personal access token is rejected with 401 at the authentication layer; an opaque tc_ data key with 403 by the session gate) and an explicit confirmation body { "data": { "confirm": true } }. Revokes the user's API keys and OAuth tokens, cancels the Stripe subscription, removes the Loops contact, then anonymizes the user's PII and soft-deletes the account. Billing/invoice financial records are retained (unlinked) per the documented retention policy.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | Yes | No | ||
| data.confirm | boolean | Yes | No | true |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/me" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"confirm":true}}'
Example Response​
{
"data": {
"type": "users",
"id": "9b1c1e2a-3f4d-4a5b-8c6d-7e8f9a0b1c2d",
"attributes": {
"deleted": true
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not delete its owner's account |
| 422 | Missing or invalid confirmation |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
PATCH /v1/me​
Update the authenticated user's profile (v1)
Updates the authenticated user's own name and/or company from the portal Profile page. Authorized on the first-party interactive session (#1971): a long-lived data key (PAT / opaque tc_ key) is rejected. The body is a JSON:API resource document (data.type = users); both attributes are optional, so a partial update leaves the omitted attribute unchanged, and company may be nulled to clear it. Requires Content-Type: application/vnd.api+json (415 otherwise). There is no user id in the path — the caller can only ever update their own record.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "users" | |
| data.attributes | object | No | No | ||
| data.attributes.name | string | No | No | "Jane Doe" | |
| data.attributes.company | string | No | Yes | "Acme Corp" |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/me" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"users","attributes":{"name":"Jane Doe","company":"Acme Corp"}}}'
Example Response​
{
"data": {
"type": "users",
"id": "9b1c1e2a-3f4d-4a5b-8c6d-7e8f9a0b1c2d",
"attributes": {
"name": "Jane Doe",
"company": "Acme Corp",
"plan": "pro_monthly",
"subscription_status": "active",
"trial_ends_at": "2026-07-15T00:00:00+00:00"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not rewrite its owner's profile |
| 415 | Content-Type is not application/vnd.api+json |
| 422 | Validation failed |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
PATCH /v1/user/password​
Change the authenticated user's password
Verifies the caller's current password, validates and rehashes the new one, and persists it. On success the user's OTHER OAuth access/refresh tokens are revoked (other login sessions and Passport personal-access tokens stop authenticating; opaque tc_ data keys live in a separate store and are NOT revoked by this sweep) while the current session stays alive. Requires an interactive first-party session; long-lived data keys are rejected.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "user-passwords" | |
| data.attributes | object | No | No | ||
| data.attributes.current_password | string (password) | Yes | No | "current-secret" | |
| data.attributes.new_password | string (password) | Yes | No | "new-secret-123" | |
| data.attributes.new_password_confirmation | string (password) | Yes | No | "new-secret-123" |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/user/password" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"user-passwords","attributes":{"current_password":"current-secret","new_password":"new-secret-123","new_password_confirmation":"new-secret-123"}}}'
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not change its owner's password |
| 422 | Wrong current password or new password fails the rules |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/user/password/forgot​
Request a password-reset link
Mints a single-use, expiring opaque reset token for the account holding the supplied address and emails the portal's /reset-password?token=… link to it. Public (no authentication) — a locked-out user has neither a session nor their current password. Always returns 202 whether or not the address matches an account, with a byte-identical body, so the response cannot be used to enumerate registered addresses; a failed email send is swallowed rather than surfaced for the same reason. Throttled per IP (throttle:password-forgot). A second request for the same account replaces the prior pending token rather than adding one.
Authentication: Public — no API token required.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "user-password-forgots" | |
| data.attributes | object | No | No | ||
| data.attributes.email | string (email) | Yes | No | "[email protected]" |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/user/password/forgot" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
Error Responses​
| Status | Description |
|---|---|
| 422 | Validation error (missing or malformed address) |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/user/password/reset​
Redeem a password-reset token and set a new password
Redeems the opaque token from the emailed reset link, sets the new password, and consumes the token (single use). Public (no authentication) — the token in the JSON:API body is the sole authorization. On success all of the user's OAuth access/refresh tokens are revoked, so every existing session and Passport personal-access token stops authenticating (unlike the authenticated change-password endpoint, which spares the acting session — a reset has no acting session and may be recovering a compromised account). Opaque tc_ data keys live in a separate store and are NOT revoked by this sweep. An unknown, expired, or already-used token all return the same generic 422 so the response cannot distinguish them. A missing or over-long token never reaches that check — request validation rejects it first with the standard JSON:API 422 carrying a /data/attributes/token source pointer.
Authentication: Public — no API token required.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "user-password-resets" | |
| data.attributes | object | No | No | ||
| data.attributes.token | string | Yes | No | "kQ8mZ3xR7vL2nP9wB4dF6sT1hJ0yC5gAeU3iO8qW2rY7tK4uM6bN1vX9zD5cH0f" | |
| data.attributes.password | string (password) | Yes | No | "new-secret-123" | |
| data.attributes.password_confirmation | string (password) | Yes | No | "new-secret-123" |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/user/password/reset" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"user-password-resets","attributes":{"token":"kQ8mZ3xR7vL2nP9wB4dF6sT1hJ0yC5gAeU3iO8qW2rY7tK4uM6bN1vX9zD5cH0f","password":"new-secret-123","password_confirmation":"new-secret-123"}}}'
Error Responses​
| Status | Description |
|---|---|
| 422 | Unknown, expired, or already-used reset token (single generic error), or a validation error with a source pointer when the token is missing/over-long or the new password fails the rules |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/signup​
Self-service signup (v1)
Creates an unverified user and dispatches a verification email. Public (no authentication). Gated on remaining founding-pool capacity; when the pool is full a waitlist response is returned. The success response is identical whether or not the email already exists (non-enumerating).
Requires a valid invite code (data.attributes.invite_code, issue #2282). A missing code is a 422 validation error; a code that is unknown, revoked, expired, or fully used is rejected with invite_invalid, invite_expired (410) or invite_exhausted. Holding an invite is permission to create an account — it does NOT reserve a founding slot, which is still claimed first-come-first-served at POST /v1/signup/verify. Use POST /v1/invites/validate to check a code without attempting a signup.
A re-submit never changes an existing account's password. When the address already belongs to an account, the submitted password is discarded and the account keeps whatever credential it currently has. For an account that is still unverified the verification email is re-sent, so re-submitting is a valid way to recover a lost link — but the password sent with it does not take effect, and the account's existing password is unaffected. Overwriting it is deliberately not supported: this endpoint is unauthenticated and cannot prove the re-submitter started the signup, so allowing it would let an attacker plant a credential that the victim's own verification click activates. Prefer POST /v1/signup/resend, which recovers an expired link from the token alone and never asks for a password. Because the 202 body is byte-identical on every branch, its meta.message states this conditionally rather than only when it applies.
Authentication: Public — no API token required.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "signups" | |
| data.attributes | object | No | No | ||
| data.attributes.email | string (email) | Yes | No | "[email protected]" | |
| data.attributes.password | string (password) | Yes | No | "correct horse battery" | |
| data.attributes.invite_code | string | Yes | No | "FOUNDING-2026" |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/signup" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"signups","attributes":{"email":"[email protected]","password":"correct horse battery","invite_code":"FOUNDING-2026"}}}'
Error Responses​
| Status | Description |
|---|---|
| 410 | Invite code has expired |
| 422 | Validation error, or the invite code is unknown, revoked, or fully used |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/signup/verify​
Verify signup email, start trial, issue API key (v1)
Redeems the emailed verification token: marks the email verified, atomically claims a founding slot, starts a 14-day app-managed trial, issues the single opaque tc_live_ API key (returned once), and sends the welcome email. Public (no authentication) — the token in the JSON:API body is the sole authorization. When the founding pool has filled since signup a waitlist response is returned and no trial is started.
Authentication: Public — no API token required.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "email-verifications" | |
| data.attributes | object | No | No | ||
| data.attributes.token | string | Yes | No | "kQ8mZ3xR7vL2nP9wB4dF6sT1hJ0yC5gAeU3iO8qW2rY7tK4uM6bN1vX9zD5cH0f" |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/signup/verify" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"email-verifications","attributes":{"token":"kQ8mZ3xR7vL2nP9wB4dF6sT1hJ0yC5gAeU3iO8qW2rY7tK4uM6bN1vX9zD5cH0f"}}}'
Error Responses​
| Status | Description |
|---|---|
| 410 | Verification token has expired |
| 422 | Verification token is missing, invalid, or already used |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/signup/resend​
Resend the signup verification email from an expired token (v1)
Mints a fresh verification token for the account the supplied token belongs to and re-sends the verification email. Public (no authentication) — the token in the JSON:API body is the sole authorization, which is what lets the marketing site's /verify?token=… page offer a one-click resend when POST /v1/signup/verify has answered 410 token_expired. An expired token is accepted here; that is the whole point of the endpoint.
Token rotation, not extension: a successful resend replaces the stored token and its expiry, so the previous link stops working immediately and the new one carries a full 24-hour window. Because rotation is immediate, a spent token keeps replaying its 202 for 60 seconds — a double-submitted or retried request is idempotent and sends no second email, rather than reporting the link it just replaced as unknown.
The 202 response is identical whether or not the account is already verified (non-enumerating); the email is only dispatched when it is not. A token that resolves to no account — never issued, already rotated, or burned by a completed verification — is answered with 422 token_unknown, which is safe to distinguish because the token is a 64-character random secret rather than a guessable identifier. The token must be sent in the JSON body; a token in the query string is ignored, since a query string is recorded by proxies and travels onward in Referer. Unlike signup and verify, this endpoint is NOT gated on founding-pool capacity: capacity is enforced when the link is redeemed, and a waitlist response here would be indistinguishable from a sent email.
A resend re-asserts the caller's invite claim. Because an expired token is accepted here and rotated into a fresh 24-hour one, an unverified account whose invite hold had already lapsed could otherwise be verified later against a use that had since been given to somebody else, taking an invite past its max_uses. So for an unverified account the hold is re-acquired before the token is rotated, and a resend is refused with 422 invite_exhausted when the invite has been fully claimed in the meantime, or with 422 invite_invalid when the invite has since been revoked (issue #2575). An account that holds no invite claim at all is unaffected, and an already-verified account does no invite work.
Throttled by throttle:signup-resend per IP and per token, on top of the default api limit, because every accepted call sends an email — so a 429 here can arrive well before the general rate limit is spent.
Authentication: Public — no API token required.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "verification-resends" | |
| data.attributes | object | No | No | ||
| data.attributes.token | string | Yes | No | "kQ8mZ3xR7vL2nP9wB4dF6sT1hJ0yC5gAeU3iO8qW2rY7tK4uM6bN1vX9zD5cH0f" |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/signup/resend" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"verification-resends","attributes":{"token":"kQ8mZ3xR7vL2nP9wB4dF6sT1hJ0yC5gAeU3iO8qW2rY7tK4uM6bN1vX9zD5cH0f"}}}'
Error Responses​
| Status | Description |
|---|---|
| 422 | Verification token is missing, malformed, or resolves to no account (token_unknown); or the account is unverified and the invite that put it in flight has since been fully claimed (invite_exhausted) or revoked (invite_invalid) |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /v1/user/subscription​
Get the authenticated user's subscription/plan and trial state
Returns the authenticated end user's plan, subscription status, trial state, and period/cancellation flags as a JSON:API resource. Read-only; never mutates billing state. A user with no billing account gets a graceful "no plan" resource (200), not a 500.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/user/subscription" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not read its owner's subscription |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /v1/user/usage​
Get the authenticated caller's current rate-limit window
Returns the live rate-limit window (limit, remaining, resets_at) for the authenticated user's tc_live_ API key, as a JSON:API resource. Both credential types work: an opaque tc_live_ API key may read its own usage, and so may an interactive first-party portal session — unlike the sibling account-management endpoints (GET/POST/DELETE /v1/user/api-key, PATCH /v1/user/email), which reject a data key with 403. Whichever credential calls it, the window reported is always the authenticated user's own API-key bucket, deliberately NOT the bucket of the token making this request, since the portal proxies its screens with an interactive session token whose browsing would otherwise be reported as API usage (issue #2304). The call is not metered: this endpoint is exempt from the api rate limiter it reports on, so polling your own usage never consumes the quota being reported (it has its own separate, more permissive limiter, hence the 429 below). A user with no API key is reported as a full, untouched window at their default tier. windows (issue #2559): an additive array reporting every window actually enforced against this user. It always contains an api_key entry (the same numbers as the top-level attributes), plus either a billing_account entry — when the user's OAuth-token traffic is metered against a per-billing-account plan allowance (see PR #2558) — or, when no entitling billing account resolves, a per_token entry whose remaining and resets_at are null (the limiter buckets that case per individual token, which this endpoint cannot sum). Read-only. The portal dashboard derives requests-used as limit - remaining.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/user/usage" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 403 | Authenticated as an OAuth client rather than a user, so there is no usage window to report (machine-to-machine client-credentials token) |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
PATCH /v1/user/email​
Initiate a change of the authenticated user's login email
Validates a new login-email address (well-formed, unused, and different from the current login), stores it as a pending change, and emails a confirmation link to the NEW address. The login email is NOT changed until the confirmation link is redeemed via POST /v1/user/email/confirm. Authorized on an interactive first-party session (#1971); personal-access / opaque data keys are rejected.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "user-emails" | |
| data.attributes | object | No | No | ||
| data.attributes.email | string (email) | Yes | No | "[email protected]" |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/user/email" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated — no token, an invalid/expired token, or a Passport personal-access token (rejected outright at the auth layer since the opaque-key cutover) |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which authenticates fine on the data endpoints but may not change its owner's login email |
| 422 | Validation error (invalid, in-use, or unchanged address) |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/user/email/confirm​
Confirm a pending login-email change
Redeems the confirmation token emailed to the new address, promotes the pending address to the login email, and marks it verified. The previous address stops authenticating. Followed from an emailed link, so it authenticates on the opaque token alone (no session, no bearer). Rejects a missing, unknown, or expired token.
Authentication: Public — no API token required.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "user-email-confirmations" | |
| data.attributes | object | No | No | ||
| data.attributes.token | string | Yes | No |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/user/email/confirm" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"user-email-confirmations","attributes":{"token":"string"}}}'
Error Responses​
| Status | Description |
|---|---|
| 422 | Missing, unknown, or expired confirmation token |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
Attributes v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/attributes​
Get all card attributes (v1)
Retrieve a paginated list of all card attributes (autographs, variations, etc.)
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | No | Filter by attribute name. The value is an exact match by default. Prefix it with like: for a case-insensitive substring match (for example like:Auto). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| limit | integer | No | Number of attributes per page |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/attributes" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "attributes",
"id": "string",
"attributes": {
"attribute": "Autograph",
"name": "Autograph",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
],
"included": [
{}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/attributes​
Create a new attribute (v1)
Create a new card attribute (autograph, variation, etc.)
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "attributes" | |
| data.attributes | object | No | No | ||
| data.attributes.attribute | string | Yes | No | "AU" | |
| data.attributes.name | string | Yes | No | "Autograph" | |
| data.attributes.description | string | No | Yes | "Player's signature on card" | |
| data.attributes.color | string | No | Yes | "#FF0000" |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/attributes" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"attributes","attributes":{"attribute":"AU","name":"Autograph","description":"Player'\''s signature on card","color":"#FF0000"}}}'
Example Response​
{
"data": {
"type": "attributes",
"id": "string",
"attributes": {
"attribute": "Autograph",
"name": "Autograph",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/attributes/{id}​
Get a specific attribute (v1)
Retrieve detailed information about a specific card attribute by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the attribute to retrieve |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/attributes/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "attributes",
"id": "string",
"attributes": {
"attribute": "Autograph",
"name": "Autograph",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
},
"included": [
{}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Attribute not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/attributes/{id}​
Delete an attribute (v1)
Delete an existing card attribute
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the attribute to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/attributes/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Attribute not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/attributes/{id}​
Update an attribute (v1)
Update an existing card attribute
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the attribute to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "attributes" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.attribute | string | No | No | "AU" | |
| data.attributes.name | string | No | No | "Autograph" | |
| data.attributes.description | string | No | Yes | "Player's signature on card" | |
| data.attributes.color | string | No | Yes | "#FF0000" |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/attributes/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"attributes","id":"string","attributes":{"attribute":"AU","name":"Autograph","description":"Player'\''s signature on card","color":"#FF0000"}}}'
Example Response​
{
"data": {
"type": "attributes",
"id": "string",
"attributes": {
"attribute": "Autograph",
"name": "Autograph",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Attribute not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Billing​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
POST /v1/billing/checkout​
Create a Stripe Checkout Session for self-service subscribe (v1)
Creates a subscription-mode Stripe Checkout Session for the authenticated caller's billing account (lazily creating the account and Stripe customer on first use) and returns the hosted session URL. The plan selects the Stripe price; optional success_url/cancel_url must match the configured trusted-origin allowlist.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| plan | string | Yes | No | "starter" | The plan slug to subscribe to. Must be one of the plans configured for the API (at launch: starter or pro). |
| success_url | string (uri) | No | No | "https://app.tradingcardapi.com/account/billing?checkout=success" | Optional. Where Stripe returns the user after a completed checkout. Its origin must be in the configured trusted-origin allowlist. |
| cancel_url | string (uri) | No | No | "https://app.tradingcardapi.com/account/billing?checkout=cancel" | Optional. Where Stripe returns the user if they abandon checkout. Its origin must be in the configured trusted-origin allowlist. |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/billing/checkout" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"plan":"starter","success_url":"https://app.tradingcardapi.com/account/billing?checkout=success","cancel_url":"https://app.tradingcardapi.com/account/billing?checkout=cancel"}'
Example Response​
{
"url": "https://checkout.stripe.com/c/pay/cs_test_abc123"
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which may not subscribe its owner |
| 409 | Caller's billing account already holds an entitling subscription |
| 422 | Unknown plan, or success_url/cancel_url origin not in the trusted allowlist |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 502 | Stripe checkout session creation failed |
POST /v1/billing/portal​
Create a Stripe Customer Portal session (v1)
Creates a Stripe Billing Portal session for the authenticated caller's billing account (lazily creating the account and Stripe customer on first use) and returns the hosted session URL. An optional return_url must match the configured trusted-origin allowlist.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| return_url | string (uri) | No | No | "https://app.tradingcardapi.com/account/billing" | Optional. Where Stripe returns the user after the portal session. Its origin must be in the configured trusted-origin allowlist. |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/billing/portal" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"return_url":"https://app.tradingcardapi.com/account/billing"}'
Example Response​
{
"url": "https://billing.stripe.com/session/test_abc123"
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthenticated |
| 403 | Authenticated but not an interactive first-party session — e.g. an opaque tc_ data key, which may not open its owner's billing portal |
| 422 | return_url origin not in the trusted allowlist |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 502 | Stripe portal session creation failed |
GET /v1/founding-slots/remaining​
Get the remaining founding-customer slots
Returns the number of founding-customer slots still available as a single derived count (capacity minus the billing accounts currently trialing or active). Public and unauthenticated — it exposes only the aggregate remaining count for the marketing-site indicator, no per-user state. Throttled by the default anonymous rate limit.
Authentication: Public — no API token required.
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/founding-slots/remaining" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
Brands v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/brands​
Get all brands (v1)
Retrieve a list of all trading card brands
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| include | string | No | Comma-separated list of relationships to include. Supported: sets |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/brands" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "brands",
"id": "string",
"attributes": {
"name": "Topps",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/brands​
Create a new brand (v1)
Create a new trading card brand
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "brands" | |
| data.attributes | object | No | No | ||
| data.attributes.name | string | Yes | No | "Topps" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/brands" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"brands","attributes":{"name":"Topps","description":"string"}}}'
Example Response​
{
"data": {
"type": "brands",
"id": "string",
"attributes": {
"name": "Topps",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/brands/{id}​
Get a specific brand (v1)
Retrieve detailed information about a specific brand by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the brand to retrieve |
| include | string | No | Comma-separated list of relationships to include. Supported: sets |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/brands/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "brands",
"id": "string",
"attributes": {
"name": "Topps",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Brand not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/brands/{id}​
Delete a brand (v1)
Delete an existing brand
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the brand to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/brands/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Brand not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/brands/{id}​
Update a brand (v1)
Update an existing brand
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the brand to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "brands" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.name | string | No | No | "Topps" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/brands/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"brands","id":"string","attributes":{"name":"Topps","description":"string"}}}'
Example Response​
{
"data": {
"type": "brands",
"id": "string",
"attributes": {
"name": "Topps",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Brand not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Cards v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/cards​
Get all cards (v1)
Retrieve a paginated list of all trading cards in the system
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| filter[name] | string | No | Filter by card name. This is the card's generated display name -- the card number, the players or teams on it, the card title, any attributes (RC, AU, ...) and the serial, joined in that order -- so an exact match has to reproduce that whole composed string. Exact match only. Unlike the other string filters in this API, the like: operator is NOT accepted here and returns a 400: it compiles to a leading-wildcard LIKE '%...%', which no index can serve, and api_cards is by far the largest table in the API. Substring search on card names is tracked at issue #2590. A card whose name literally begins like: therefore cannot be matched on its full name. |
| filter[set_id] | string | No | Filter cards by set UUID |
| filter[player_id] | string | No | Filter cards by player UUID. Returns every card the player appears on, both directly and via a player-team. |
| filter[team_id] | string | No | Filter cards by team UUID. Returns every card the team appears on, both directly and via one of its player-teams. |
| include | string | No | Comma-separated list of relationships to include (set,oncard,attributes,children) |
| page | integer | No | Page number for pagination |
| per_page | integer | No | Number of items per page (max 100, default 25) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/cards" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "cards",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"name": "Michael Jordan",
"number": "23",
"serial_number": "001/100",
"image_uuid": "550e8400-e29b-41d4-a716-446655440000",
"title": "Rookie Card",
"notes": "string",
"has_player": true,
"has_team": true,
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "string"
}
},
"oncard": {
"data": [
{
"type": "string",
"id": "string"
}
]
},
"attributes": {
"data": [
{
"type": "attributes",
"id": "string"
}
]
},
"images": {
"data": [
{
"type": "card_images",
"id": "string"
}
]
}
}
}
],
"included": [
{}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad Request — the query string contains a parameter this endpoint does not accept, or the requested page size exceeds the maximum of 100. Details |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/cards​
Create a new card (v1)
Create a new trading card record. A client-generated data.id (JSON:API §7.2.1) may be supplied to pin the new card's UUID, which makes a re-create of the same logical card detectable rather than duplicating it; omit it and the server generates a v4 UUID. Creating over an id that is already taken returns 409 — this endpoint is create-only. For upsert-by-id semantics use POST /internal/card-batches.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "cards" | |
| data.id | string (uuid) | No | No | "550e8400-e29b-41d4-a716-446655440000" | Optional client-generated UUID for the new card. Omit to let the server generate one. Optional but non-null when present — validation is sometimes|uuid, so an explicit null is rejected. |
| data.attributes | object | No | No | ||
| data.attributes.number | string | No | No | "23" | Card number within the set |
| data.attributes.serial_number | string | No | Yes | "001/100" | |
| data.attributes.image_uuid | string (uuid) | No | Yes | "550e8400-e29b-41d4-a716-446655440000" | UUID reference for card image |
| data.attributes.title | string | No | Yes | "Rookie Card" | |
| data.attributes.notes | string | No | Yes | ||
| data.relationships | object | No | No | ||
| data.relationships.set | object | No | No | ||
| data.relationships.set.data | object | No | No | ||
| data.relationships.set.data.type | string | No | No | "sets" | |
| data.relationships.set.data.id | string (uuid) | No | No | ||
| data.relationships.oncard | object | No | No | ||
| data.relationships.oncard.data | array of object | No | No | ||
| data.relationships.oncard.data[].type | string | No | No | ||
| data.relationships.oncard.data[].id | string (uuid) | No | No |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/cards" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"cards","id":"550e8400-e29b-41d4-a716-446655440000","attributes":{"number":"23","serial_number":"001/100","image_uuid":"550e8400-e29b-41d4-a716-446655440000","title":"Rookie Card","notes":"string"},"relationships":{"set":{"data":{"type":"sets","id":"string"}},"oncard":{"data":[{"type":"string","id":"string"}]}}}}'
Example Response​
{
"data": {
"type": "cards",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"name": "Michael Jordan",
"number": "23",
"serial_number": "001/100",
"image_uuid": "550e8400-e29b-41d4-a716-446655440000",
"title": "Rookie Card",
"notes": "string",
"has_player": true,
"has_team": true,
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "string"
}
},
"oncard": {
"data": [
{
"type": "string",
"id": "string"
}
]
},
"attributes": {
"data": [
{
"type": "attributes",
"id": "string"
}
]
},
"images": {
"data": [
{
"type": "card_images",
"id": "string"
}
]
}
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 409 | A card already exists at the supplied client-generated data.id |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/cards/{id}​
Get a specific card (v1)
Retrieve detailed information about a specific trading card by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the card to retrieve |
| include | string | No | Comma-separated list of relationships to include (set,oncard,attributes,children) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/cards/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "cards",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"name": "Michael Jordan",
"number": "23",
"serial_number": "001/100",
"image_uuid": "550e8400-e29b-41d4-a716-446655440000",
"title": "Rookie Card",
"notes": "string",
"has_player": true,
"has_team": true,
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "string"
}
},
"oncard": {
"data": [
{
"type": "string",
"id": "string"
}
]
},
"attributes": {
"data": [
{
"type": "attributes",
"id": "string"
}
]
},
"images": {
"data": [
{
"type": "card_images",
"id": "string"
}
]
}
}
},
"included": [
{}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Card not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/cards/{id}​
Delete a card (v1)
Delete an existing trading card record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the card to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/cards/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Card not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/cards/{id}​
Update a card (v1)
Update an existing trading card record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the card to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "cards" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.number | string | No | No | "23" | |
| data.attributes.serial_number | string | No | Yes | "001/100" | |
| data.attributes.image_uuid | string (uuid) | No | Yes | "550e8400-e29b-41d4-a716-446655440000" | UUID reference for card image |
| data.attributes.title | string | No | Yes | "Rookie Card" | |
| data.attributes.notes | string | No | Yes | ||
| data.attributes.attributes | array of object | No | No | Extra attributes for the card | |
| data.attributes.attributes[].id | string (uuid) | No | No | ||
| data.attributes.attributes[].value | string | No | No | ||
| data.attributes.field_overrides | array of string | No | Yes | Fields not inherited from parent (parallel cards only) | |
| data.relationships | object | No | No | ||
| data.relationships.set | object | No | No | ||
| data.relationships.set.data | object | No | No | ||
| data.relationships.set.data.type | string | No | No | "sets" | |
| data.relationships.set.data.id | string (uuid) | No | No | ||
| data.relationships.oncard | object | No | No | ||
| data.relationships.oncard.data | array of object | No | No | ||
| data.relationships.oncard.data[].type | string | No | No | ||
| data.relationships.oncard.data[].id | string (uuid) | No | No |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/cards/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"cards","id":"string","attributes":{"number":"23","serial_number":"001/100","image_uuid":"550e8400-e29b-41d4-a716-446655440000","title":"Rookie Card","notes":"string","attributes":[{"id":"string","value":"string"}],"field_overrides":["string"]},"relationships":{"set":{"data":{"type":"sets","id":"string"}},"oncard":{"data":[{"type":"string","id":"string"}]}}}}'
Example Response​
{
"data": {
"type": "cards",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"name": "Michael Jordan",
"number": "23",
"serial_number": "001/100",
"image_uuid": "550e8400-e29b-41d4-a716-446655440000",
"title": "Rookie Card",
"notes": "string",
"has_player": true,
"has_team": true,
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "string"
}
},
"oncard": {
"data": [
{
"type": "string",
"id": "string"
}
]
},
"attributes": {
"data": [
{
"type": "attributes",
"id": "string"
}
]
},
"images": {
"data": [
{
"type": "card_images",
"id": "string"
}
]
}
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Card not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Card Images​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/card-images​
List all card images
List all card images
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| include | string | No | Include related resources (card) |
| page | integer | No | Page number for pagination |
| per_page | integer | No | Number of items per page (default 50, max 100) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/card-images" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/card-images​
Upload a new card image
Upload a new card image
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: multipart/form-data
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| file | string (binary) | Yes | No | Image file (JPEG, PNG, or WebP, max 10MB, max 4000x4000px) | |
| data | string (json) | Yes | No | "{\"type\":\"card_images\",\"attributes\":{\"card_id\":\"uuid\",\"image_type\":\"front\"}}" | JSON:API formatted data |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/card-images" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json" \
-F 'file=@/path/to/file' \
-F 'data={"type":"card_images","attributes":{"card_id":"uuid","image_type":"front"}}'
Error Responses​
| Status | Description |
|---|---|
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /v1/card-images/{id}​
Get a specific card image
Get a specific card image
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Card image UUID |
| include | string | No | Include related resources (card) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/card-images/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Card image not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
DELETE /v1/card-images/{id}​
Delete a card image
Delete a card image
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Card image UUID |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/card-images/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Card image not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
PATCH /v1/card-images/{id}​
Update a card image
Update a card image
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | Card image UUID |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/card-images/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Card image not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /v1/card-images/{card_image}/download​
Download the actual image file
Download/stream the actual image file
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| card_image | string | Yes | Card image UUID |
| size | string | No | Image size variant. Sizes configured in config/images.php (default: small/medium/large) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/card-images/{card_image}/download" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: image/*"
Error Responses​
| Status | Description |
|---|---|
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Card image or variant not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/card-image-batches​
Upload multiple card images in a batch
Accepts up to 50 images per request. Returns immediately with a batch ID for polling status. The legacy POST /v1/card-images/bulk URL is a deprecated alias for this endpoint (slated for removal in v2).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: multipart/form-data
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| files[] | array of string | No | No | Image files (max 50, each max 10MB, JPEG/PNG/WebP) | |
| data | string (json) | Yes | No | "{\"type\":\"bulk_card_images\",\"attributes\":{\"mappings\":[...]}}" | JSON:API formatted data with mappings |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/card-image-batches" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json" \
-F 'files[]=@/path/to/file' \
-F 'data={"type":"bulk_card_images","attributes":{"mappings":[...]}}'
Error Responses​
| Status | Description |
|---|---|
| 401 | The caller identity could not be resolved, so the batch would have no owner and would be unreadable by anyone. |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
GET /v1/card-image-batches/{card_image_batch}​
Get bulk upload batch status
Returns bulk upload batch status and progress. Poll to track progress. The legacy GET /v1/card-images/bulk/{batch_id} URL is a deprecated alias for this endpoint (slated for removal in v2).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| card_image_batch | string | Yes | Batch UUID |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/card-image-batches/{card_image_batch}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Batch not found. Batches are scoped to the caller that created them, so a batch belonging to another caller is indistinguishable from one that does not exist. |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
Genres v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/genres​
Get all genres (v1)
Retrieve a paginated list of all trading card genres
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Number of genres per page |
| filter[name] | string | No | Filter by genre name. The value is an exact match by default. Prefix it with like: for a case-insensitive substring match (for example like:Base). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| name | string | No | Deprecated alias for filter[name]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| include | string | No | Comma-separated list of relationships to include |
| filter[status] | string | No | Filter genres by soft-delete state. Use 'deleted' to list only soft-deleted genres or 'active' for live genres (the default). |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/genres" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "genres",
"id": "string",
"attributes": {
"name": "Baseball",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Invalid filter parameter, or an unrecognized query parameter |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/genres​
Create a new genre (v1)
Create a new trading card genre, restoring if previously soft-deleted
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "genres" | |
| data.attributes | object | No | No | ||
| data.attributes.name | string | Yes | No | "Baseball" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/genres" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"genres","attributes":{"name":"Baseball","description":"string"}}}'
Example Response​
{
"data": {
"type": "genres",
"id": "string",
"attributes": {
"name": "Baseball",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/genres/{id}​
Get a specific genre (v1)
Retrieve detailed information about a specific genre by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the genre to retrieve |
| include | string | No | Comma-separated list of relationships to include |
| include_trashed | boolean | No | When true, a soft-deleted genre is returnable by id. Defaults to false (soft-deleted genres 404). |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/genres/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "genres",
"id": "string",
"attributes": {
"name": "Baseball",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Genre not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/genres/{id}​
Delete a genre (v1)
Soft delete an existing genre record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the genre to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/genres/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Genre not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/genres/{id}​
Update a genre (v1)
Update an existing genre record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the genre to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "genres" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.name | string | No | No | "Baseball" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/genres/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"genres","id":"string","attributes":{"name":"Baseball","description":"string"}}}'
Example Response​
{
"data": {
"type": "genres",
"id": "string",
"attributes": {
"name": "Baseball",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Genre not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Manufacturers v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/manufacturers​
Get all manufacturers (v1)
Retrieve a list of all trading card manufacturers
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/manufacturers" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "manufacturers",
"id": "string",
"attributes": {
"name": "Topps Company",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/manufacturers​
Create a new manufacturer (v1)
Create a new trading card manufacturer
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "manufacturers" | |
| data.attributes | object | No | No | ||
| data.attributes.name | string | Yes | No | "Topps Company" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/manufacturers" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"manufacturers","attributes":{"name":"Topps Company","description":"string"}}}'
Example Response​
{
"data": {
"type": "manufacturers",
"id": "string",
"attributes": {
"name": "Topps Company",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/manufacturers/{id}​
Get a specific manufacturer (v1)
Retrieve detailed information about a specific manufacturer by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the manufacturer to retrieve |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/manufacturers/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "manufacturers",
"id": "string",
"attributes": {
"name": "Topps Company",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Manufacturer not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/manufacturers/{id}​
Delete a manufacturer (v1)
Delete an existing manufacturer
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the manufacturer to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/manufacturers/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Manufacturer not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/manufacturers/{id}​
Update a manufacturer (v1)
Update an existing manufacturer
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the manufacturer to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "manufacturers" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.name | string | No | No | "Topps Company" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/manufacturers/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"manufacturers","id":"string","attributes":{"name":"Topps Company","description":"string"}}}'
Example Response​
{
"data": {
"type": "manufacturers",
"id": "string",
"attributes": {
"name": "Topps Company",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Manufacturer not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
ObjectAttributes v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/object-attributes​
Get all object attributes (v1)
Retrieve a paginated list of all object attributes (card-specific attribute instances)
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Number of object attributes per page |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/object-attributes" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "object-attributes",
"id": "string",
"attributes": {
"attribute_id": "string",
"attribute_value": "Authenticated",
"object_type": "App\\Models\\Card",
"object_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
],
"included": [
{}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/object-attributes​
Create a new object attribute (v1)
Create a new object attribute instance linking an attribute to a specific object (card)
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "object-attributes" | |
| data.attributes | object | No | No | ||
| data.attributes.attribute_id | string (uuid) | Yes | No | ID of the attribute definition | |
| data.attributes.attribute_value | string | Yes | No | "Authenticated" | Value of the attribute for this object |
| data.attributes.object_type | string | Yes | No | "App\\Models\\Card" | Type of object this attribute is attached to |
| data.attributes.object_id | string (uuid) | Yes | No | ID of the object this attribute is attached to |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/object-attributes" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"object-attributes","attributes":{"attribute_id":"string","attribute_value":"Authenticated","object_type":"App\\Models\\Card","object_id":"string"}}}'
Example Response​
{
"data": {
"type": "object-attributes",
"id": "string",
"attributes": {
"attribute_id": "string",
"attribute_value": "Authenticated",
"object_type": "App\\Models\\Card",
"object_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/object-attributes/{id}​
Get a specific object attribute (v1)
Retrieve detailed information about a specific object attribute by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the object attribute to retrieve |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/object-attributes/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "object-attributes",
"id": "string",
"attributes": {
"attribute_id": "string",
"attribute_value": "Authenticated",
"object_type": "App\\Models\\Card",
"object_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
},
"included": [
{}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Object attribute not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/object-attributes/{id}​
Delete an object attribute (v1)
Delete an existing object attribute instance
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the object attribute to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/object-attributes/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Object attribute not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/object-attributes/{id}​
Update an object attribute (v1)
Update an existing object attribute instance
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the object attribute to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "object-attributes" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.attribute_id | string (uuid) | No | No | ||
| data.attributes.attribute_value | string | No | No | "Authenticated" | |
| data.attributes.object_type | string | No | No | "App\\Models\\Card" | |
| data.attributes.object_id | string (uuid) | No | No |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/object-attributes/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"object-attributes","id":"string","attributes":{"attribute_id":"string","attribute_value":"Authenticated","object_type":"App\\Models\\Card","object_id":"string"}}}'
Example Response​
{
"data": {
"type": "object-attributes",
"id": "string",
"attributes": {
"attribute_id": "string",
"attribute_value": "Authenticated",
"object_type": "App\\Models\\Card",
"object_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Object attribute not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Players v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/players​
Get all players (v1)
Retrieve a paginated list of all players with optional filtering
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| filter[first_name] | string | No | Filter by player first name. The value is an exact match by default. Prefix it with like: for a case-insensitive substring match (for example like:Mich). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| filter[last_name] | string | No | Filter by player last name. The value is an exact match by default. Prefix it with like: for a case-insensitive substring match (for example like:Jord). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| filter[full_name] | string | No | Filter by full name (searches both first and last name). The value is an exact match by default. Prefix the whole value with like: for a case-insensitive substring match on each name token (for example like:Mich Jord). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| first_name | string | No | Deprecated alias for filter[first_name]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| last_name | string | No | Deprecated alias for filter[last_name]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| full_name | string | No | Deprecated alias for filter[full_name]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| limit | integer | No | Number of players per page (max 100, default 25) |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/players" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "players",
"id": "string",
"attributes": {
"name": "Michael Jordan",
"first_name": "Michael",
"last_name": "Jordan",
"position": "Shooting Guard",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
],
"included": [
{}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad Request — the query string contains a parameter this endpoint does not accept, or the requested page size exceeds the maximum of 100. Details |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/players​
Create a new player (v1)
Create a new player record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "players" | |
| data.attributes | object | No | No | ||
| data.attributes.first_name | string | No | No | "Michael" | |
| data.attributes.last_name | string | No | No | "Jordan" | |
| data.attributes.position | string | No | Yes | "Shooting Guard" | |
| data.attributes.full_name | string | No | No | "Michael Jordan" | Alternative to first_name/last_name |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/players" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"players","attributes":{"first_name":"Michael","last_name":"Jordan","position":"Shooting Guard","full_name":"Michael Jordan"}}}'
Example Response​
{
"data": {
"type": "players",
"id": "string",
"attributes": {
"name": "Michael Jordan",
"first_name": "Michael",
"last_name": "Jordan",
"position": "Shooting Guard",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/players/{id}​
Get a specific player (v1)
Retrieve detailed information about a specific player by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the player to retrieve |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/players/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "players",
"id": "string",
"attributes": {
"name": "Michael Jordan",
"first_name": "Michael",
"last_name": "Jordan",
"position": "Shooting Guard",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
},
"included": [
{}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Player not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/players/{id}​
Delete a player (v1)
Delete an existing player record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the player to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/players/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Player not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/players/{id}​
Update a player (v1)
Update an existing player record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the player to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "players" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.first_name | string | No | No | "Michael" | |
| data.attributes.last_name | string | No | No | "Jordan" | |
| data.attributes.position | string | No | Yes | "Shooting Guard" |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/players/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"players","id":"string","attributes":{"first_name":"Michael","last_name":"Jordan","position":"Shooting Guard"}}}'
Example Response​
{
"data": {
"type": "players",
"id": "string",
"attributes": {
"name": "Michael Jordan",
"first_name": "Michael",
"last_name": "Jordan",
"position": "Shooting Guard",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Player not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PlayerTeams v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/player-teams​
Get all player-team associations (v1)
Retrieve a paginated list of player-team associations with optional filtering. This resource is deliberately filterable by foreign key only: it owns no human-readable string column of its own, so there is nothing for a name filter to match and no like: filter is offered. To search by name, filter /v1/players or /v1/teams and follow the relationship. See ADR-007 (the v1 filter-set convention).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| filter[team_id] | string | No | Filter by team UUID. Exact match only -- like: is not accepted on a foreign key (ADR-007). |
| filter[player_id] | string | No | Filter by player UUID. Exact match only -- like: is not accepted on a foreign key (ADR-007). |
| team_id | string | No | Deprecated alias for filter[team_id]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| player_id | string | No | Deprecated alias for filter[player_id]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| limit | integer | No | Number of player-teams per page |
| include | string | No | Comma-separated list of relationships to include (player,team) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/player-teams" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "playerteams",
"id": "string",
"attributes": {
"name": "Michael Jordan - Chicago Bulls",
"player_id": "string",
"team_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
],
"included": [
{}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad Request — the query string contains a parameter this endpoint does not accept, or the requested page size exceeds the maximum of 100. Details |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/player-teams​
Create a new player-team association (v1)
Create a new player-team association record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "playerteams" | |
| data.attributes | object | No | No | ||
| data.attributes.player_id | string (uuid) | Yes | No | ID of the player | |
| data.attributes.team_id | string (uuid) | Yes | No | ID of the team |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/player-teams" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"playerteams","attributes":{"player_id":"string","team_id":"string"}}}'
Example Response​
{
"data": {
"type": "playerteams",
"id": "string",
"attributes": {
"name": "Michael Jordan - Chicago Bulls",
"player_id": "string",
"team_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/player-teams/{id}​
Get a specific player-team association (v1)
Retrieve detailed information about a specific player-team association by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the player-team association to retrieve |
| include | string | No | Comma-separated list of relationships to include (player,team) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/player-teams/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "playerteams",
"id": "string",
"attributes": {
"name": "Michael Jordan - Chicago Bulls",
"player_id": "string",
"team_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
},
"included": [
{}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Player-team association not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/player-teams/{id}​
Delete a player-team association (v1)
Delete an existing player-team association record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the player-team association to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/player-teams/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Player-team association not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/player-teams/{id}​
Update a player-team association (v1)
Update an existing player-team association record (PATCH only; PUT is not supported and returns 405 Method Not Allowed).
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the player-team association to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "playerteams" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.player_id | string (uuid) | No | No | ID of the player | |
| data.attributes.team_id | string (uuid) | No | No | ID of the team |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/player-teams/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"playerteams","id":"string","attributes":{"player_id":"string","team_id":"string"}}}'
Example Response​
{
"data": {
"type": "playerteams",
"id": "string",
"attributes": {
"name": "Michael Jordan - Chicago Bulls",
"player_id": "string",
"team_id": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Player-team association not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Sets v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/sets​
Get all card sets (v1)
Retrieve a paginated list of all trading card sets
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| include | string | No | Comma-separated list of relationships to include |
| per_page | integer | No | Number of sets per page (max 100, default 25) |
| limit | integer | No | Number of sets per page (deprecated, use per_page instead) |
| order_by | string | No | Field to order by |
| sort | string | No | Sort direction |
| filter[name] | string | No | Filter by set name. The value is an exact match by default. Prefix it with like: for a case-insensitive substring match (for example like:2021 Topps). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| filter[genre] | string | No | Filter by genre ID |
| filter[year] | string | No | Filter by year ID |
| filter[brand] | string | No | Filter by brand ID |
| filter[manufacturer] | string | No | Filter by manufacturer ID |
| filter[parent_id] | string | No | Filter by parent set ID (returns child sets/parallels of the specified parent) |
| name | string | No | Deprecated alias for filter[name]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| genre | string | No | Deprecated alias for filter[genre]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| year | string | No | Deprecated alias for filter[year]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| brand | string | No | Deprecated alias for filter[brand]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| manufacturer | string | No | Deprecated alias for filter[manufacturer]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| parent_id | string | No | Deprecated alias for filter[parent_id]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| scope | string | No | Row scope for the listing. root (the default) returns only sets without a parent, so parallels, inserts, autograph subsets and variations are omitted -- the default meta.pagination.total is therefore a count of root sets, not of the whole catalog. all returns every set. Ignored when parent_id is supplied, which always returns that parent's children. When scope is omitted a name query searches every set for backward compatibility; pass scope=root explicitly to keep a name search to root sets. |
| filter[status] | string | No | Filter by status (requires X-TCAPI-Ignore-Status header to see draft sets) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/sets" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "sets",
"id": "string",
"attributes": {
"name": "1989 Topps Baseball",
"title": "Series 1",
"description": "string",
"card_count": 792,
"current_card_count": 792,
"is_parallel": false,
"is_insert": false,
"is_autograph": false,
"is_relic": false,
"is_variation": false,
"serial": 250,
"number_prefix": "string",
"parent_set": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"sources": {
"data": [
{
"type": "set_sources",
"id": "string"
}
]
},
"genre": {
"data": {
"type": "genres",
"id": "string"
}
},
"manufacturer": {
"data": {
"type": "manufacturers",
"id": "string"
}
},
"brand": {
"data": {
"type": "brands",
"id": "string"
}
},
"year": {
"data": {
"type": "years",
"id": "string"
}
}
}
}
],
"included": [
{}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"pagination": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
},
"scope": {
"applied": "root_sets_only",
"description": "Only sets without a parent are listed, so parallels, inserts, autograph subsets and variations are omitted. This is a default scope, not a limit on your account. Add ?scope=all to list every set, or ?parent_id={id} to list one set's children."
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad Request — the query string contains a parameter this endpoint does not accept, or the requested page size exceeds the maximum of 100. Details |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/sets​
Create a new set (v1)
Create a new trading card set
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "sets" | |
| data.attributes | object | No | No | ||
| data.attributes.name | string | Yes | No | "1989 Topps Baseball" | |
| data.attributes.description | string | No | Yes | ||
| data.attributes.total_cards | integer | No | Yes | 792 | |
| data.attributes.genre_id | string (uuid) | No | Yes | ||
| data.attributes.manufacturer_id | string (uuid) | No | Yes | ||
| data.attributes.brand_id | string (uuid) | No | Yes | ||
| data.attributes.year_id | string (uuid) | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/sets" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"sets","attributes":{"name":"1989 Topps Baseball","description":"string","total_cards":792,"genre_id":"string","manufacturer_id":"string","brand_id":"string","year_id":"string"}}}'
Example Response​
{
"data": {
"type": "sets",
"id": "string",
"attributes": {
"name": "1989 Topps Baseball",
"title": "Series 1",
"description": "string",
"card_count": 792,
"current_card_count": 792,
"is_parallel": false,
"is_insert": false,
"is_autograph": false,
"is_relic": false,
"is_variation": false,
"serial": 250,
"number_prefix": "string",
"parent_set": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"sources": {
"data": [
{
"type": "set_sources",
"id": "string"
}
]
},
"genre": {
"data": {
"type": "genres",
"id": "string"
}
},
"manufacturer": {
"data": {
"type": "manufacturers",
"id": "string"
}
},
"brand": {
"data": {
"type": "brands",
"id": "string"
}
},
"year": {
"data": {
"type": "years",
"id": "string"
}
}
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/sets/{id}​
Get a specific set (v1)
Retrieve detailed information about a specific trading card set by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the set to retrieve |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/sets/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "sets",
"id": "string",
"attributes": {
"name": "1989 Topps Baseball",
"title": "Series 1",
"description": "string",
"card_count": 792,
"current_card_count": 792,
"is_parallel": false,
"is_insert": false,
"is_autograph": false,
"is_relic": false,
"is_variation": false,
"serial": 250,
"number_prefix": "string",
"parent_set": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"sources": {
"data": [
{
"type": "set_sources",
"id": "string"
}
]
},
"genre": {
"data": {
"type": "genres",
"id": "string"
}
},
"manufacturer": {
"data": {
"type": "manufacturers",
"id": "string"
}
},
"brand": {
"data": {
"type": "brands",
"id": "string"
}
},
"year": {
"data": {
"type": "years",
"id": "string"
}
}
}
},
"included": [
{}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/sets/{id}​
Delete a set (v1)
Delete an existing trading card set. By default the deletion is refused with a 409 when the set is still published or still has child records (cards, set sources, subsets); the response names the specific blocker(s). Pass force=true to cascade-delete those children and remove the set in a single call.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the set to delete |
| force | boolean | No | When true, cascade-delete remaining children (cards, set sources, subsets) and remove the set even if it is published. When false or omitted, a published set or a set with remaining children is refused with a structured 409. |
| confirm | boolean | No | Reserved confirmation flag accepted for forward compatibility with the documented delete contract; parsed as a boolean and currently advisory. |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/sets/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 409 | Set deletion blocked — published or has remaining children and force was not set |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/sets/{id}​
Update a set (v1)
Update an existing trading card set
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the set to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "sets" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.name | string | No | No | "1989 Topps Baseball" | |
| data.attributes.description | string | No | Yes | ||
| data.attributes.total_cards | integer | No | Yes | 792 | |
| data.attributes.genre_id | string (uuid) | No | Yes | ||
| data.attributes.manufacturer_id | string (uuid) | No | Yes | ||
| data.attributes.brand_id | string (uuid) | No | Yes | ||
| data.attributes.year_id | string (uuid) | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/sets/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"sets","id":"string","attributes":{"name":"1989 Topps Baseball","description":"string","total_cards":792,"genre_id":"string","manufacturer_id":"string","brand_id":"string","year_id":"string"}}}'
Example Response​
{
"data": {
"type": "sets",
"id": "string",
"attributes": {
"name": "1989 Topps Baseball",
"title": "Series 1",
"description": "string",
"card_count": 792,
"current_card_count": 792,
"is_parallel": false,
"is_insert": false,
"is_autograph": false,
"is_relic": false,
"is_variation": false,
"serial": 250,
"number_prefix": "string",
"parent_set": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"sources": {
"data": [
{
"type": "set_sources",
"id": "string"
}
]
},
"genre": {
"data": {
"type": "genres",
"id": "string"
}
},
"manufacturer": {
"data": {
"type": "manufacturers",
"id": "string"
}
},
"brand": {
"data": {
"type": "brands",
"id": "string"
}
},
"year": {
"data": {
"type": "years",
"id": "string"
}
}
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/sets/{set}/checklist​
Get set checklist (v1)
Retrieve the complete checklist for a trading card set including all cards. Supports compact format for large sets to avoid response size limits. Compact format returns only id, number, name, has_player, and has_team fields, reducing response size by ~75%.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the set to get checklist for |
| format | string | No | Response format: 'full' returns all card fields, 'compact' returns only id, number, name, has_player, and has_team |
| page | integer | No | Page number for pagination (starts at 1) |
| per_page | integer | No | Number of cards per page (max 100, returns all if not specified) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/sets/{set}/checklist" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "sets",
"id": "string",
"attributes": {
"name": "1989 Topps Baseball",
"title": "Series 1",
"description": "string",
"card_count": 792,
"current_card_count": 792,
"is_parallel": false,
"is_insert": false,
"is_autograph": false,
"is_relic": false,
"is_variation": false,
"serial": 250,
"number_prefix": "string",
"parent_set": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"sources": {
"data": [
{
"type": "set_sources",
"id": "string"
}
]
},
"genre": {
"data": {
"type": "genres",
"id": "string"
}
},
"manufacturer": {
"data": {
"type": "manufacturers",
"id": "string"
}
},
"brand": {
"data": {
"type": "brands",
"id": "string"
}
},
"year": {
"data": {
"type": "years",
"id": "string"
}
}
}
},
"included": [
{
"type": "cards",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"name": "Michael Jordan",
"number": "23",
"serial_number": "001/100",
"image_uuid": "550e8400-e29b-41d4-a716-446655440000",
"title": "Rookie Card",
"notes": "string",
"has_player": true,
"has_team": true,
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "string"
}
},
"oncard": {
"data": [
{
"type": "string",
"id": "string"
}
]
},
"attributes": {
"data": [
{
"type": "attributes",
"id": "string"
}
]
},
"images": {
"data": [
{
"type": "card_images",
"id": "string"
}
]
}
}
}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/sets/{set}/checklist​
Add checklist to set (v1)
Add or import a checklist to a trading card set. Can either generate empty cards or parse a detailed checklist.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the set to add checklist to |
| queue | boolean | No | Queue the import for async processing. When omitted, large checklists (more than 50 lines) are auto-queued and smaller ones run synchronously. Pass queue=true to force async or queue=false to force sync. |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "checklist" | |
| data.attributes | object | No | No | ||
| data.attributes.lines | array of string | No | No | ["# Base Set","1 Mike Trout - Los Angeles Angels"] | Checklist lines to parse, one entry per line. Lines starting with '#' denote a section. More than 50 lines are auto-queued when the queue parameter is omitted. |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/sets/{set}/checklist" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"checklist","attributes":{"lines":["# Base Set","1 Mike Trout - Los Angeles Angels"]}}}'
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/sets/{set}/checklist​
Delete set checklist (v1)
Bulk delete cards from a trading card set. Supports optional range filtering by card number. Without range parameters, all cards in the set are deleted.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the set to delete cards from |
| from_number | integer | No | Start of card number range to delete (inclusive, integer >= 1) |
| to_number | integer | No | End of card number range to delete (inclusive, integer >= 1, must be >= from_number) |
| queue | boolean | No | Queue the deletion for async processing (recommended for large sets) |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/sets/{set}/checklist" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "bulk_delete_result",
"attributes": {
"cards_deleted": 50,
"set_id": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 403 | Forbidden - missing delete scope |
| 404 | Set not found |
| 422 | Validation error - invalid from_number or to_number |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
POST /v1/sets/{id}/actions/sync-parallel​
Sync parallel set with parent (v1)
Add missing cards from parent set to a parallel set. This endpoint finds cards in the parent set that don't exist in the parallel set and creates them with their on-card relationships and attributes. This is the canonical JSON:API action-namespace route; the legacy POST /v1/sets/{id}/sync-parallel path is a deprecated alias.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the parallel set to sync |
| queue | string | No | Queue the sync for async processing. Defaults to "auto", which forces queued processing when the parent set has more than 20 cards and otherwise runs the sync inline. Pass "true" to always queue or "false" to always run inline. |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "sync_parallel" | |
| data.attributes | object | No | No | No attributes currently required. Reserved for future options. |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/sets/{id}/actions/sync-parallel" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"sync_parallel","attributes":{}}}'
Example Response​
{
"data": {
"type": "sync_result",
"id": "string",
"attributes": {
"cards_created": 15,
"cards_updated": 0,
"cards_skipped": 85
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 422 | Invalid operation (set is not a parallel set or has no parent) |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/sets/{id}/sync-parallel​
Sync parallel set with parent (v1) — DEPRECATED alias
Deprecated RPC-style alias of POST /v1/sets/{id}/actions/sync-parallel. Behaves identically but responds with deprecation headers (Deprecation, Sunset, Link, Warning). Retained for a removal window; migrate to the action-namespace route. (issue #1500)
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the parallel set to sync |
| queue | string | No | Queue the sync for async processing. Defaults to "auto", which forces queued processing when the parent set has more than 20 cards and otherwise runs the sync inline. Pass "true" to always queue or "false" to always run inline. |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "sync_parallel" | |
| data.attributes | object | No | No | No attributes currently required. Reserved for future options. |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/sets/{id}/sync-parallel" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"sync_parallel","attributes":{}}}'
Example Response​
{
"data": {
"type": "sync_result",
"id": "string",
"attributes": {
"cards_created": 15,
"cards_updated": 0,
"cards_skipped": 85
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 422 | Invalid operation (set is not a parallel set or has no parent) |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Set Sources v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/set-sources​
Get all set sources (v1)
Retrieve all set sources. Filter by set_id and/or source_type using filter[] params.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| filter[set_id] | string | No | Filter by set UUID |
| filter[source_type] | string | No | Filter by source type |
| include | string | No | Comma-separated list of relationships to include (set) |
| page | integer | No | Page number for pagination |
| per_page | integer | No | Number of items per page (default 50, max 200) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/set-sources" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "set_sources",
"id": "string",
"attributes": {
"source_url": "https://example.com/checklist",
"source_name": "CardboardConnection",
"source_type": "checklist",
"verified_at": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/set-sources​
Create a new set source (v1)
Create a new set source tracking record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "set_sources" | |
| data.attributes | object | No | No | ||
| data.attributes.set_id | string (uuid) | Yes | No | "550e8400-e29b-41d4-a716-446655440000" | |
| data.attributes.source_url | string (url) | Yes | No | "https://example.com/checklist" | |
| data.attributes.source_name | string | No | Yes | "CardboardConnection" | |
| data.attributes.source_type | string | Yes | No | "checklist" | |
| data.attributes.verified_at | string (date-time) | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/set-sources" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"set_sources","attributes":{"set_id":"550e8400-e29b-41d4-a716-446655440000","source_url":"https://example.com/checklist","source_name":"CardboardConnection","source_type":"checklist","verified_at":"string"}}}'
Example Response​
{
"data": {
"type": "set_sources",
"id": "string",
"attributes": {
"source_url": "https://example.com/checklist",
"source_name": "CardboardConnection",
"source_type": "checklist",
"verified_at": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/set-sources/{id}​
Get a specific set source (v1)
Retrieve detailed information about a specific set source by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the set source to retrieve |
| include | string | No | Comma-separated list of relationships to include (set) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/set-sources/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "set_sources",
"id": "string",
"attributes": {
"source_url": "https://example.com/checklist",
"source_name": "CardboardConnection",
"source_type": "checklist",
"verified_at": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set source not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/set-sources/{id}​
Delete a set source (v1)
Delete an existing set source
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the set source to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/set-sources/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set source not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/set-sources/{id}​
Update a set source (v1)
Update an existing set source
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the set source to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "set_sources" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.source_url | string (url) | No | No | ||
| data.attributes.source_name | string | No | Yes | ||
| data.attributes.source_type | string | No | No | ||
| data.attributes.verified_at | string (date-time) | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/set-sources/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"set_sources","id":"string","attributes":{"source_url":"string","source_name":"string","source_type":"string","verified_at":"string"}}}'
Example Response​
{
"data": {
"type": "set_sources",
"id": "string",
"attributes": {
"source_url": "https://example.com/checklist",
"source_name": "CardboardConnection",
"source_type": "checklist",
"verified_at": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set source not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Statistics v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/stats/{type}​
Get statistics for a model type (v1)
Retrieve daily statistics showing creation and deletion counts for a specific model type. For the set-derived types (cards, sets) the series is filtered to the set statuses the caller's token may see; taxonomy types are ungated.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| type | string | Yes | Type of model to get statistics for (e.g., cards, sets, players) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/stats/{type}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "stats",
"attributes": {
"model": "cards",
"unit": "daily",
"count": 30,
"stats": [
{
"date": "2024-01-15",
"count": 5,
"total": 150
}
]
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Model type not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/stats/counts​
Get current counts for all entity types
Get entity counts by status. Cached for 1 hour. Public and unauthenticated. Unauthenticated callers, and tokens without the internal, read:all-status or read:draft scope, see a published-only view: total equals published and draft is 0.
Authentication: Public — no API token required.
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/stats/counts" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "stats",
"attributes": {
"counts": [
{
"entity_type": "set",
"total": 730,
"published": 730,
"draft": 0,
"archived": 0
}
]
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/stats/snapshots​
Get historical snapshots with optional filtering
Get historical snapshots with date/type filters. Public and unauthenticated. Unauthenticated callers, and tokens without the internal, read:all-status or read:draft scope, see a published-only view: total equals published and draft is 0.
Authentication: Public — no API token required.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| entity_type | string | No | Filter by entity type |
| from | string | No | Filter snapshots from this date (YYYY-MM-DD) |
| to | string | No | Filter snapshots to this date (YYYY-MM-DD) |
| per_page | integer | No | Number of results per page (default: 100, max: 500) |
| page | integer | No | Page number |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/stats/snapshots" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "snapshots",
"attributes": {
"snapshots": [
{
"date": "2024-01-15",
"entity_type": "set",
"total": 730,
"published": 730,
"draft": 0,
"archived": 0
}
],
"entity_type": "set",
"from": "string",
"to": "string"
}
},
"meta": {
"total": 100,
"per_page": 100,
"current_page": 1,
"last_page": 1
}
}
Error Responses​
| Status | Description |
|---|---|
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/stats/growth​
Get growth metrics for a specific time period
Compare current counts to previous period. Cached for 1 hour. Public and unauthenticated. Unauthenticated callers, and tokens without the internal, read:all-status or read:draft scope, get metrics derived from published counts rather than totals.
Authentication: Public — no API token required.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| period | string | No | Time period for comparison |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/stats/growth" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "growth",
"attributes": {
"period": "7d",
"metrics": [
{
"entity_type": "set",
"current": 730,
"previous": 714,
"change": 16,
"percentage_change": 2.24
}
]
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Teams v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/teams​
Get all teams (v1)
Retrieve a paginated list of all teams with optional filtering
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| filter[name] | string | No | Filter by full team name (searches both location and mascot). The value is an exact match by default. Prefix the whole value with like: for a case-insensitive substring match on each name token (for example like:Chic Bull). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| filter[location] | string | No | Filter by team location. The value is an exact match by default. Prefix it with like: for a case-insensitive substring match (for example like:Chic). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| filter[mascot] | string | No | Filter by team mascot. The value is an exact match by default. Prefix it with like: for a case-insensitive substring match (for example like:Bull). Inside a like: value, % and _ are matched literally rather than acting as SQL wildcards. |
| filter[genre_id] | string | No | Filter by genre UUID. Exact match only -- like: is not accepted on a foreign key (ADR-007). |
| location | string | No | Deprecated alias for filter[location]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| mascot | string | No | Deprecated alias for filter[mascot]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| name | string | No | Deprecated alias for filter[name]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| genre_id | string | No | Deprecated alias for filter[genre_id]. Still accepted, but a request that uses it receives Deprecation and Sunset response headers; migrate to the bracketed spelling. |
| limit | integer | No | Number of teams per page (max 100, default 25) |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/teams" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "teams",
"id": "string",
"attributes": {
"name": "Chicago Bulls",
"city": "Chicago",
"abbreviation": "CHI",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
],
"included": [
{}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Invalid pagination parameter (limit exceeds the maximum of 100), or an unrecognized query parameter |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/teams​
Create a new team (v1)
Create a new team record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "teams" | |
| data.attributes | object | No | No | ||
| data.attributes.location | string | No | No | "Chicago" | |
| data.attributes.mascot | string | No | No | "Bulls" | |
| data.attributes.city | string | No | Yes | "Chicago" | |
| data.attributes.abbreviation | string | No | Yes | "CHI" | |
| data.attributes.name | string | No | No | "Chicago Bulls" | Alternative to location/mascot |
| data.attributes.genre_id | string (uuid) | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/teams" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"teams","attributes":{"location":"Chicago","mascot":"Bulls","city":"Chicago","abbreviation":"CHI","name":"Chicago Bulls","genre_id":"string"}}}'
Example Response​
{
"data": {
"type": "teams",
"id": "string",
"attributes": {
"name": "Chicago Bulls",
"city": "Chicago",
"abbreviation": "CHI",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/teams/{id}​
Get a specific team (v1)
Retrieve detailed information about a specific team by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the team to retrieve |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/teams/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "teams",
"id": "string",
"attributes": {
"name": "Chicago Bulls",
"city": "Chicago",
"abbreviation": "CHI",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
},
"included": [
{}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Team not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/teams/{id}​
Delete a team (v1)
Delete an existing team record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the team to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/teams/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Team not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/teams/{id}​
Update a team (v1)
Update an existing team record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the team to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "teams" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.location | string | No | No | "Chicago" | |
| data.attributes.mascot | string | No | No | "Bulls" | |
| data.attributes.city | string | No | Yes | "Chicago" | |
| data.attributes.abbreviation | string | No | Yes | "CHI" | |
| data.attributes.genre_id | string (uuid) | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/teams/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"teams","id":"string","attributes":{"location":"Chicago","mascot":"Bulls","city":"Chicago","abbreviation":"CHI","genre_id":"string"}}}'
Example Response​
{
"data": {
"type": "teams",
"id": "string",
"attributes": {
"name": "Chicago Bulls",
"city": "Chicago",
"abbreviation": "CHI",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Team not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Years v1​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /v1/years​
Get all years (v1)
Retrieve a list of all years available for trading card sets
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/years" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "years",
"id": "string",
"attributes": {
"year": "1989",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
]
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
POST /v1/years​
Create a new year (v1)
Create a new year record for trading card classification
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "years" | |
| data.attributes | object | No | No | ||
| data.attributes.name | string | Yes | No | "1989" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X POST "https://api.tradingcardapi.com/v1/years" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"years","attributes":{"name":"1989","description":"string"}}}'
Example Response​
{
"data": {
"type": "years",
"id": "string",
"attributes": {
"year": "1989",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
GET /v1/years/{id}​
Get a specific year (v1)
Retrieve detailed information about a specific year by ID
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the year to retrieve |
| include | string | No | Comma-separated list of relationships to include |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v1/years/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": {
"type": "years",
"id": "string",
"attributes": {
"year": "1989",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Year not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
DELETE /v1/years/{id}​
Delete a year (v1)
Delete an existing year record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the year to delete |
Example Request​
curl -X DELETE "https://api.tradingcardapi.com/v1/years/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Year not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
PATCH /v1/years/{id}​
Update a year (v1)
Update an existing year record
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| id | string | Yes | UUID of the year to update |
Request Body​
Media type: application/vnd.api+json
| Field | Type | Required | Nullable | Example | Description |
|---|---|---|---|---|---|
| data | object | No | No | ||
| data.type | string | No | No | "years" | |
| data.id | string (uuid) | No | No | ||
| data.attributes | object | No | No | ||
| data.attributes.name | string | No | No | "1989" | |
| data.attributes.description | string | No | Yes |
Example Request​
curl -X PATCH "https://api.tradingcardapi.com/v1/years/{id}" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/vnd.api+json" \
-H "Accept: application/vnd.api+json" \
-d '{"data":{"type":"years","id":"string","attributes":{"name":"1989","description":"string"}}}'
Example Response​
{
"data": {
"type": "years",
"id": "string",
"attributes": {
"year": "1989",
"description": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
}
}
}
Error Responses​
| Status | Description |
|---|---|
| 400 | Bad request |
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Year not found |
| 422 | Unprocessable Entity — the request document failed validation. Details |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Sets v2​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
Why v2?​
The v2 checklist endpoint fixes a JSON:API semantic issue in v1:
- v1 returns the set as primary data (
data: {type: "sets"}) with cards inincluded- incorrect for a "checklist" - v2 returns cards as primary data (
data: [{type: "cards"}, ...]) with set inincluded- correct semantics
When to use v2:
- New integrations that want standards compliance
- Applications prioritizing cards over set metadata
- When you need the improved response structure
When to use v1:
- Existing integrations (backward compatibility)
- No breaking changes needed
Both versions are fully supported long-term.
GET /v2/sets/{set}/checklist​
Get set checklist (v2)
Retrieve the complete checklist for a trading card set. V2 returns cards as the primary data with set information in the included array. Supports compact format for large sets to avoid response size limits. Compact format returns only id, number, name, has_player and has_team fields, reducing response size by ~75%. Compact also drops the JSON:API envelope: the response omits included, per-card relationships, and per-resource links. Top-level pagination links and meta are retained. An explicit include parameter is still honored on a compact request and re-adds the corresponding included and relationships members.
Authentication: Bearer token required — send Authorization: Bearer YOUR_API_TOKEN.
Parameters​
| Name | Type | Required | Description |
|---|---|---|---|
| set | string | Yes | UUID of the set to get checklist for |
| include | string | No | Comma-separated list of relationships to include (set,oncard,attributes). Defaults to set under the full format and to none under format=compact; see the format parameter. Passing this parameter explicitly overrides the default in both formats. |
| format | string | No | Response format: 'full' returns all card fields, 'compact' returns only id, number, name, has_player and has_team. Compact additionally omits included, per-card relationships, and per-resource links; top-level pagination links and meta are retained. Pass an explicit include to re-add the corresponding envelope members. |
| page | integer | No | Page number for pagination (starts at 1) |
| per_page | integer | No | Number of cards per page (max 100, returns all if not specified) |
Example Request​
curl -X GET "https://api.tradingcardapi.com/v2/sets/{set}/checklist" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/vnd.api+json"
Example Response​
{
"data": [
{
"type": "cards",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"name": "Michael Jordan",
"number": "23",
"serial_number": "001/100",
"image_uuid": "550e8400-e29b-41d4-a716-446655440000",
"title": "Rookie Card",
"notes": "string",
"has_player": true,
"has_team": true,
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"set": {
"data": {
"type": "sets",
"id": "string"
}
},
"oncard": {
"data": [
{
"type": "string",
"id": "string"
}
]
},
"attributes": {
"data": [
{
"type": "attributes",
"id": "string"
}
]
},
"images": {
"data": [
{
"type": "card_images",
"id": "string"
}
]
}
}
}
],
"included": [
{
"type": "sets",
"id": "string",
"attributes": {
"name": "1989 Topps Baseball",
"title": "Series 1",
"description": "string",
"card_count": 792,
"current_card_count": 792,
"is_parallel": false,
"is_insert": false,
"is_autograph": false,
"is_relic": false,
"is_variation": false,
"serial": 250,
"number_prefix": "string",
"parent_set": "string",
"created_at": "string",
"updated_at": "string",
"url": "string"
},
"relationships": {
"sources": {
"data": [
{
"type": "set_sources",
"id": "string"
}
]
},
"genre": {
"data": {
"type": "genres",
"id": "string"
}
},
"manufacturer": {
"data": {
"type": "manufacturers",
"id": "string"
}
},
"brand": {
"data": {
"type": "brands",
"id": "string"
}
},
"year": {
"data": {
"type": "years",
"id": "string"
}
}
}
}
],
"links": {
"first": "string",
"last": "string",
"prev": "string",
"next": "string"
},
"meta": {
"current_page": 1,
"from": 1,
"to": 25,
"per_page": 25,
"total": 100,
"last_page": 4
}
}
Error Responses​
| Status | Description |
|---|---|
| 401 | Unauthorized |
| 402 | Payment Required — the authenticated user's billing account is not subscribed (an expired trial that never converted). Details |
| 404 | Set not found |
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |
Version​
Unless an endpoint states otherwise, endpoints in this section are subject to the API rate limits. See the rate limits guide for quotas, response headers, and retry patterns.
GET /version​
Get API version information
Retrieve version information about the API, application, and supported versions
Authentication: Public — no API token required.
Example Request​
curl -X GET "https://api.tradingcardapi.com/version" \
-H "Accept: application/json"
Example Response​
{
"api_version": "1.0",
"app_version": "2.1.3",
"build_date": "2024-01-15",
"build_commit": "abc123def",
"supported_versions": [
"1.0",
"1.1"
],
"deprecated_versions": [
"0.9"
],
"changelog_url": "https://api.example.com/changelog"
}
Error Responses​
| Status | Description |
|---|---|
| 429 | Too Many Requests — the caller has exhausted its rate-limit budget for the current window. Details See the rate limits guide. |
| 500 | Internal server error |