Documentation
REST API
Authenticate with a Bearer API key (created in your seller dashboard under Integrations → API Access). The reference below is generated from the live API spec, so it always matches what the backend serves. Requires a Pro or Enterprise plan.
Base URL
Bearer token authentication is required on every request.
Use this root for all authenticated REST API requests.
https://supercatch.com/api/v1Authentication Example
Include your API key in the Authorization header for every request.
curl https://supercatch.com/api/v1/listings \ -H "Authorization: Bearer YOUR_API_KEY"
API Reference
Endpoint metadata, query parameters, response fields, and examples are generated from the shared API spec.
GET/listings
List store listings
Returns non-deleted listings owned by the API key's store in newest-first order. Use pagination.nextCursor unchanged to request the next page.
Use Cases
- Sync active inventory into an ERP, warehouse tool, or marketplace feed builder.
- Audit draft, reserved, sold, and showcase listings without scraping the seller UI.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
statusOptional | string | Filters listings by lifecycle status. Omit this parameter to return every non-deleted listing status for the store. DRAFT, PENDING, PROCESSING, ACTIVE, SOLD, RESERVED, +4 more Example: |
limitOptional | integer | Maximum records to return. Values above 100 are clamped by the reader, and omitted values default to 50. Example: |
cursorOptional | string | Opaque listing id returned in pagination.nextCursor. Pass it unchanged to continue from the previous page. Example: |
Response Fields
| Field | Type | Description |
|---|---|---|
data[].id | string | Stable listing id. Use as an internal key or cursor value. Example: |
data[].slug | string | Public product/listing slug used by SuperCatch product URLs. Example: |
data[].productType | string | Catalog product family for routing and downstream taxonomy mapping. SPORTS_CARD, NONSPORTS_CARD, TCG_CARD, VIDEO_GAME, TICKET, AUTOGRAPH, +1 more Example: |
data[].status | string | Current listing lifecycle status. DRAFT, PENDING, PROCESSING, ACTIVE, SOLD, RESERVED, +4 more Example: |
data[].condition | string | Seller-facing condition or grading bucket. MINT, NEAR_MINT, EXCELLENT, GOOD, LIGHT_PLAYED, PLAYED, +2 more Example: |
data[].price | decimal-string | Base listing price as an exact decimal string. Example: |
data[].salePrice | decimal-string | null | Active sale price when one is configured; null otherwise. Example: |
data[].quantity | integer | Total quantity attached to the listing. Example: |
data[].quantityAvailable | integer | Quantity currently available for purchase after holds and sales. Example: |
data[].imageUrls | string[] | Public image URLs in display order. Example: |
data[].createdAt | date-time | ISO-8601 creation timestamp. Example: |
pagination.nextCursor | string | null | Cursor for the next page, or null when hasMore is false. Example: |
pagination.hasMore | boolean | True when another page is available. Example: |
pagination.limit | integer | Effective page size after defaulting and clamping. Example: |
Example Response
{
"data": [
{
"id": "clst_01hzn7y3d0qa9b5c2r8m4p6x7k",
"slug": "1993-topps-derek-jeter-98",
"productType": "SPORTS_CARD",
"status": "ACTIVE",
"condition": "NEAR_MINT",
"price": "49.99",
"salePrice": null,
"quantity": 1,
"quantityAvailable": 1,
"imageUrls": [
"https://supercatch.com/cdn/listings/clst_front.webp"
],
"createdAt": "2026-04-27T17:30:00.000Z"
}
],
"pagination": {
"nextCursor": "clst_01hzn7y3d0qa9b5c2r8m4p6x7k",
"hasMore": true,
"limit": 50
}
}POST/listings
Create draft listings
Pushes a batch of up to 25 cards into the API key's store as DRAFT listings owned by the store. Images are uploaded (remote URLs are re-hosted; base64 is stored to R2), catalog identity is matched, and each card lands in the seller's review queue. New drafts are grouped into a rolling batch job visible on /store/jobs (1-hour window, 500-card cap); the response jobId is pollable via GET /jobs/{jobId}. Send an Idempotency-Key header to make whole-request retries safe. Requests are rate-weighted by cards + images. Created listings are attributed to the store owner, never to a user id from the request.
Use Cases
- Push a scanning-app or external-inventory batch into the store as drafts for seller review before publishing.
- Re-run the same import safely: each card's clientId makes creation idempotent, so retries replay instead of duplicating.
- Track and review a push as a unit: returned jobId opens the batch on /store/jobs with per-card progress and counts.
Query Parameters
No query parameters.
Request Body
| Field | Type | Description |
|---|---|---|
cardsRequired | object[] | Array of card payloads to create. At least one, at most 25 per request. Excess returns a 422. Example: |
cards[].clientIdRequired | string | Caller-stable id for the card, the per-card idempotency key. While the card is still a draft, re-sending the same clientId updates that draft (status `duplicate`) instead of creating a second listing. Example: |
cards[].productTypeRequired | string | Catalog product family. Determines which identity fields are required. SPORTS_CARD, NONSPORTS_CARD, TCG_CARD, VIDEO_GAME, TICKET, AUTOGRAPH, +1 more Example: |
cards[].featuredOptional | string | Player, character, signer, or item name. Required for SPORTS_CARD, NONSPORTS_CARD, and TCG_CARD. Example: |
cards[].seriesOptional | string | Set/series name. Required for card product types. Example: |
cards[].cardNumberOptional | string | Card number within the set. Required for card product types. Example: |
cards[].yearOptional | string | Release year ("YYYY" or season "YYYY-YY"). Required for card product types. Example: |
cards[].brandOptional | string | Manufacturer. Required for card product types. Example: |
cards[].conditionOptional | string | Seller-facing condition or grading bucket for the copy. MINT, NEAR_MINT, EXCELLENT, GOOD, LIGHT_PLAYED, PLAYED, +2 more Example: |
cards[].priceOptional | number | Listing price in dollars. Optional for drafts; validated against store price bounds when present. Example: |
cards[].imageUrlsOptional | string[] | Image inputs in display order: each may be a public https URL (re-hosted to R2) or a base64 data URL (stored to R2). Max 20 per card, 100 per request. Example: |
cards[].quantityOptional | integer | Listing quantity (1-99, default 1). Unique items — graded cards and standalone autograph/memorabilia/ticket/video-game items — are always forced to 1. Example: |
cards[].sellerSkuOptional | string | Your own SKU for the copy; stored on the listing for reconciliation. Example: |
cards[].shippingProfileIdOptional | string | Id of one of your shipping profiles to attach; omit to use the store default. Example: |
Example Request
{
"cards": [
{
"clientId": "ext-row-00042",
"productType": "SPORTS_CARD",
"featured": "Derek Jeter",
"series": "Topps",
"cardNumber": "98",
"year": "1993",
"brand": "Topps",
"condition": "NEAR_MINT",
"price": 49.99,
"imageUrls": [
"https://cdn.example.com/jeter-front.jpg"
]
}
]
}Response Fields
| Field | Type | Description |
|---|---|---|
data.created | integer | Number of cards that produced a new DRAFT listing in this request. Example: |
data.failed | integer | Number of cards that could not be created (see per-card error). Example: |
data.jobId | string | null | Id of the /store/jobs batch the new drafts were grouped into (rolling 1-hour window, 500-card cap). Null when nothing new was created (e.g. all cards were idempotent duplicates or errors). Example: |
data.results | object | Per-card outcome array, aligned to the submitted cards by clientId. Example: |
data.results[].clientId | string | Echoes the submitted clientId so callers can correlate outcomes. Example: |
data.results[].status | string | created = new draft; duplicate = idempotent replay of a prior push; error = validation/creation failed. created, duplicate, error Example: |
data.results[].listingId | string | null | Created (or replayed) listing id; null when status is error. Example: |
data.results[].slug | string | null | Listing slug when created; null on error. Example: |
data.results[].listingStatus | string | null | Lifecycle status of the created listing (DRAFT for review-queue cards). DRAFT, PENDING, PROCESSING, ACTIVE, SOLD, RESERVED, +4 more Example: |
data.results[].linkedCatalog | object | null | Catalog product the card linked to or created. Present only when a catalog row was resolved at save time (existing-row link); omitted when status is error or no catalog identity was resolved yet. Example: |
data.results[].linkedCatalog.catalogId | string | Id of the linked catalog product. Example: |
data.results[].linkedCatalog.catalogType | string | Catalog target key the product belongs to. SPORTS_CARD, NONSPORTS_CARD, TCG_CARD, VIDEO_GAME, TICKET, AUTOGRAPH, +1 more Example: |
data.results[].linkedCatalog.wasExisting | boolean | True when the card linked to a catalog product that already existed; false when a new one was created for it. Example: |
data.results[].error | string | null | Human-readable failure reason when status is error; null otherwise. Example: |
Example Response
{
"data": {
"created": 1,
"failed": 0,
"jobId": "imp_01hzn7y3d0qa9b5c2r8m4p6x7k",
"results": [
{
"clientId": "ext-row-00042",
"status": "created",
"listingId": "clst_01hzn7y3d0qa9b5c2r8m4p6x7k",
"slug": "1993-topps-derek-jeter-98",
"listingStatus": "DRAFT",
"error": null
}
]
}
}GET/orders
List store orders
Returns orders owned by the API key's store in newest-first order. Use status and since filters to build incremental fulfillment or accounting imports.
Use Cases
- Pull new paid orders into shipping, accounting, or customer support systems.
- Poll recent marketplace-imported orders without giving an external system admin access.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
statusOptional | string | Filters by order lifecycle status. Omit this parameter to include all order statuses. PENDING, PAID, PROCESSING, SHIPPED, DELIVERED, CANCELLED, +2 more Example: |
sinceOptional | date-time | Filters orders whose createdAt timestamp is greater than or equal to this ISO-8601 datetime. Example: |
limitOptional | integer | Maximum records to return. Values above 100 are clamped by the reader, and omitted values default to 50. Example: |
cursorOptional | string | Opaque order id returned in pagination.nextCursor. Pass it unchanged to continue from the previous page. Example: |
Response Fields
| Field | Type | Description |
|---|---|---|
data[].id | string | Stable order id. Example: |
data[].orderNumber | string | Buyer-facing order number. Example: |
data[].storeOrderNumber | integer | Store-local numeric order sequence. Example: |
data[].status | string | Current order lifecycle status. PENDING, PAID, PROCESSING, SHIPPED, DELIVERED, CANCELLED, +2 more Example: |
data[].subtotal | decimal-string | Item subtotal before tax and shipping. Example: |
data[].shippingCost | decimal-string | Shipping amount charged to the buyer. Example: |
data[].tax | decimal-string | Tax amount collected on the order. Example: |
data[].totalAmount | decimal-string | Final charged total. Example: |
data[].trackingNumber | string | null | Carrier tracking number when shipment tracking is available. Example: |
data[].carrier | string | null | Shipping carrier label when known. Example: |
data[].sourcePlatform | string | null | Marketplace/source system that produced the order, or null for native orders. Example: |
data[].itemCount | integer | Number of line items on the order. Example: |
data[].createdAt | date-time | ISO-8601 creation timestamp. Example: |
data[].paidAt | date-time | null | Payment timestamp, or null before payment. Example: |
data[].shippedAt | date-time | null | Shipment timestamp, or null before shipment. Example: |
data[].deliveredAt | date-time | null | Delivery timestamp, or null before delivery. Example: |
data[].cancelledAt | date-time | null | Cancellation timestamp, or null unless cancelled. Example: |
pagination.nextCursor | string | null | Cursor for the next page, or null when hasMore is false. Example: |
pagination.hasMore | boolean | True when another page is available. Example: |
pagination.limit | integer | Effective page size after defaulting and clamping. Example: |
Example Response
{
"data": [
{
"id": "ord_01hzn80t0tbw67ez6j9r6p4b2m",
"orderNumber": "SC-100042",
"storeOrderNumber": 42,
"status": "PAID",
"subtotal": "49.99",
"shippingCost": "5.00",
"tax": "4.13",
"totalAmount": "59.12",
"trackingNumber": "9400111206213999999999",
"carrier": "USPS",
"sourcePlatform": "supercatch",
"itemCount": 1,
"createdAt": "2026-04-27T17:35:00.000Z",
"paidAt": "2026-04-27T17:36:00.000Z",
"shippedAt": null,
"deliveredAt": null,
"cancelledAt": null
}
],
"pagination": {
"nextCursor": "ord_01hzn80t0tbw67ez6j9r6p4b2m",
"hasMore": true,
"limit": 50
}
}GET/inventory
Get inventory snapshot
Returns a cached aggregate snapshot of listing counts and quantities for the API key's store. The snapshot avoids row-level image joins and is safe for dashboards.
Use Cases
- Show current inventory totals in an external operations dashboard.
- Compare sellable quantity against a warehouse or accounting system without paging every listing.
Query Parameters
No query parameters.
Response Fields
| Field | Type | Description |
|---|---|---|
data.counts | object | Listing count by ListingStatus enum value. Example: |
data.totalListings | integer | Total non-deleted listings across every status. Example: |
data.totalQuantity | integer | Sum of listing quantity across every non-deleted listing. Example: |
data.totalQuantityAvailable | integer | Sum of currently purchasable quantity after holds and sales. Example: |
data.generatedAt | date-time | ISO-8601 timestamp when the snapshot payload was generated. Example: |
Example Response
{
"data": {
"counts": {
"DRAFT": 14,
"PENDING": 2,
"PROCESSING": 0,
"ACTIVE": 128,
"SOLD": 42,
"RESERVED": 3,
"INACTIVE": 5,
"REMOVED": 0,
"REJECTED": 0,
"SHOWCASE": 9
},
"totalListings": 203,
"totalQuantity": 221,
"totalQuantityAvailable": 173,
"generatedAt": "2026-04-27T17:40:00.000Z"
}
}GET/jobs/{jobId}
Get push/import job status
Returns the status and per-card counts of one of the store's batch jobs, including the API-push job returned by POST /listings. Poll it to confirm a push landed and how many cards were created; the cards themselves are reviewable on /store/jobs.
Use Cases
- Poll the jobId returned by POST /listings to confirm the batch landed and read its counts.
- Drive an external dashboard from push/import job progress without scraping the seller UI.
Query Parameters
No query parameters.
Response Fields
| Field | Type | Description |
|---|---|---|
data.id | string | Job id (matches the jobId from POST /listings). Example: |
data.name | string | null | Seller-facing job label. Example: |
data.status | string | Job lifecycle status (COMPLETED for synchronous API pushes). Example: |
data.totalItems | integer | Total cards grouped into the job. Example: |
data.successfulItems | integer | Cards that produced a listing. Example: |
data.failedItems | integer | Cards that failed to create. Example: |
data.createdAt | date-time | ISO-8601 job creation timestamp. Example: |
data.completedAt | date-time | null | ISO-8601 completion timestamp; null while still open. Example: |
Example Response
{
"data": {
"id": "imp_01hzn7y3d0qa9b5c2r8m4p6x7k",
"name": "API push — 12 cards",
"status": "COMPLETED",
"totalItems": 12,
"successfulItems": 12,
"failedItems": 0,
"createdAt": "2026-04-27T17:30:00.000Z",
"completedAt": "2026-04-27T17:30:05.000Z"
}
}Rate Limits
Hourly request caps are enforced per API key. Rate limit headers are returned with every API response.
Pro Plan
1,000 requests/hour
Enterprise Plan
10,000 requests/hour
Free and starter plans do not include REST API access. Upgrade to pro or enterprise to enable API keys. Contact support for custom enterprise limits.
