Reference
Every field, what it accepts, and the responses to expect.
Fields
POST /api/business/v1/sourcings · PATCH /api/business/v1/sourcings/:id| Field | Type | Required | Accepts |
|---|---|---|---|
| Request | |||
name | string | Required | 1–120 characters. Exact duplicate payloads return 409 duplicate_sourcing with the existing ID. |
start_date | date | null | Optional | YYYY-MM-DD, in your organization's timezone. Future dates create pending requests; null starts immediately. |
deadline | date | Required | Delivery deadline, YYYY-MM-DD. On or after the start date and not in the past. |
groups | array | Required for grouped requests | 1–20 groups, at most 200 price buckets in total. Groups are alternatives; one card must not ambiguously fit multiple buckets. |
duplicate_limits | array | Optional | Up to 30 copy limits across the entire request. Empty means no copy cap. |
duplicate_limits[].scope | enum | Required per limit | card, character or athlete. |
duplicate_limits[].max_copies | integer | Required per limit | 1–10,000. Choose an exact maximum, not a range. |
duplicate_limits[].subjects | string[] | Optional | Omit to apply to every entity. Character/athlete names or real Card Ladder card IDs, never certificates or invented IDs. |
| Groups | |||
groups[].name | string | Required | 1–80 characters. A readable name for this selection. |
groups[].filters | object | Required | Every specified condition must match. Values within a list are alternatives. |
groups[].bands | array | Required | 1–30 inclusive price ranges per group. Use 0–100 then 101–200 to avoid overlapping boundaries. |
| Filters · groups[].filters | |||
categories | enum[] | Required | Pokemon, OnePiece, Baseball, Basketball, Football. |
card_format | enum | Optional | graded (default), raw (ungraded), or either. With either, grader, grade and certificate filters apply only to graded cards. Raw-only groups cannot have grading filters. |
graders | enum[] | Optional | PSA, BGS, CGC, SGC. Omit for any supported grader. |
grader_rules | object[] | null | Optional | Separate grade rules sharing the same price buckets and budgets. Example: [{"grader":"BGS","grade_min":7},{"grader":"PSA","grade_min":1,"grade_max":5}]. A card must match one rule; unlisted graders are excluded. One rule per grader. Omit shared graders, grades, grade_min and grade_max when using this field. |
grader_rules[].grader / grades / grade_min / grade_max | enum / number[] / number | null | grader required | PSA, BGS (Beckett), CGC or SGC. Grades are 1–10 in half-grade steps: use exact grades, an inclusive range or a minimum. Omitted grade restrictions accept any grade from that grader. Raw-only groups cannot use these rules. |
grades | number[] | Optional | Exact grades from 1 to 10 in half-grade steps. If a range is also present, both must match. |
grade_min / grade_max | number | null | Optional | Inclusive lowest/highest grade, 1–10. |
languages | enum[] | Optional | English, Japanese, Chinese, Korean, French, German, Italian, Spanish, Portuguese, Dutch, Indonesian, Thai, Russian, Polish. Defaults still exclude Chinese Pokémon. |
cert_number_min | integer | null | Optional | Inclusive numeric certificate floor, e.g. 70,000,000. An unknown or nonnumeric certificate cannot satisfy it. |
year_min / year_max | integer | null | Optional | Inclusive printing years, 1800–2100. |
players | string[] | null | Optional | Character or athlete names. At least one must match whole words in the recorded player field. |
keywords | string[] | null | Optional | At least one phrase must match whole words in the card label, set or variation. |
exclude_keywords | string[] | null | Optional | Skip cards matching any phrase. For example: Gengar, Leaf, NCAA. |
allow_qualified | boolean | Optional | False by default. Whether grading qualifiers/condition notes are accepted. |
notes | string | null | Optional | Up to 2,000 characters of plain-English buying instructions for this group. For example: "We don't want cards from sets released between 2020 and 2026, inclusive. Avoid Rayquaza cards with a low graded population; confirm the population cutoff with us before sourcing them." Notes stay visible with the request but do not automatically apply filters. Encode supported restrictions in structured filters too; other conditions need review. |
exclusions | array | Optional | Conditional exclusions. All conditions in one active exclusion must match to reject a card. |
exclusions[] | object | Conditional | label, active (default true), categories, year_min, year_max, card_types (rookie/prospect), value_above (USD dollars). At least one condition is required. |
| Price buckets · groups[].bands[] | |||
value_min | number | Required | Lowest Card Ladder green value in USD dollars, inclusive, with at most two decimal places. 0–100,000,000. Preserve exact cents, such as 50.01. |
value_max | number | null | Required | Highest Card Ladder green value in USD dollars, inclusive, with at most two decimal places and at least value_min. null means no maximum. |
budget | integer | null | Required | Budget for this bucket in whole USD dollars. null means unlimited. The request total is calculated from all bucket budgets; one unlimited bucket makes the total unlimited. |
min_confidence | integer | Required | Every integer from 0 to 5 is valid. 2 means 2/5 or above (2, 3, 4, 5), excluding missing scores. 1, 3, 4 and 5 work the same way. 0 accepts any score, including missing scores. |
exclude_keywords | string[] | Optional | Additional exclusions only for this price range. |
allocation_id | UUID | Edits only | Keep the ID from GET for retained buckets. Omit for new ones. Removed buckets are archived; acquired cards and confirmed pickups remain under their original allocation and count toward the campaign budget. |
| Updates | |||
expected_updated_at | timestamp | Required for PATCH | Copy updated_at from the latest GET exactly. A stale revision returns 409 sourcing_changed. Pending/paused requests only; pause active requests before editing. |
Defaults
Chinese Pokémon and WNBA are excluded. Pokémon and One Piece must be official TCG products. We use Card Ladder green value; account pricing applies automatically. Notes remain visible for the sourcing team and do not replace structured filters.
Endpoints
POST /sourcings | Create a request. Future start dates make it pending. |
GET /sourcings?view=all | Requests, notes, allocation criteria, budgets and progress. view=home/history/all; status accepts active,paused,canceled,delivered. Follow next_offset. |
GET /sourcings/:id | The request, all its buckets and one page of acquired cards. Optional bucket_id, allocation_id and offset. Acquisition-time prices and scan links are included. |
PATCH /sourcings/:id | Replace pending/paused configuration with revision protection. Existing acquisition facts stay fixed. |
POST /sourcings/:id/cancel | Delete a zero-acquired request from Sourcing. It remains in History as canceled. |
POST /sourcings/:id/pause or /resume | Change sourcing status. |
GET /acquisitions | Page acquired cards across requests. Filter by sourcing_id, allocation_id and local from/to dates. |
GET /acquisitions/:id/preview | Private WebP scan preview, at most 480 × 640. Use for card grids with the same session or Bearer authorization. ETag caching is supported. |
GET /acquisitions/:id/photo | A short-lived link to the full scanner photo. Fetch only when the user opens the image. |
GET /sourcings/:id/template | Reusable rules with fresh dates and review notes. |
GET /summary | Authoritative cumulative/period totals. Supply both from and to for a local-date range. |
GET /memories | Remembered buying preferences: revision, pending learning jobs and active preferences with category, statement and origin. |
POST /memories · PATCH /memories/:id · DELETE /memories/:id | Add {category, statement}, rewrite {statement, category?} or forget a preference. Budgets and dates are never remembered. |
All paths use /api/business/v1. Date bounds are inclusive local YYYY-MM-DD dates. On request lists, from/to filter creation dates; history_from/history_to filter the finished period.
Status codes
Errors keep the same shape: error (code), message, status, optional issues (path + message), and sourcing_id for duplicates.
| Status | Code | What to do |
|---|---|---|
| 200 | Success | The response contains the created/updated request, list, cards, or action result. Exact duplicate creation returns 409 instead. |
| 400 | invalid_json | Send a valid JSON object with Content-Type: application/json. |
| 401 | unauthorized / invalid_key | The API key is absent, invalid or revoked. Use Authorization: Bearer <key>. |
| 403 | not_authorized / admin_required | The member or role cannot perform this action. Account administration requires an admin dashboard session. |
| 404 | not_found | No matching record is available to this organization. |
| 409 | duplicate_sourcing | The exact request already exists. Read sourcing_id from the response; do not create another copy. |
| 409 | sourcing_changed | Someone edited the request. GET it again and use its new updated_at. |
| 409 | sourcing_active | Pause active sourcing before changing its budget, filters or notes. |
| 409 | funded_sourcing | Acquired dollars are greater than zero. Pause instead of deleting/canceling. |
| 409 | sourcing_finished / historical_sourcing | Finished or imported historical records cannot be edited. Reuse their rules in a new request. |
| 422 | invalid_input | A field is missing/invalid or buckets overlap. issues contains each field path and message. |
| 422 | budget_below_acquired | Keep total and bucket budgets at least as large as their acquired amounts. |
| 422 | deadline_in_past | Choose a delivery deadline today or later in the organization's timezone. |
| 429 | rate_limited | Wait before trying again. |
| 503 | unavailable | The service is temporarily unavailable. Check whether the write succeeded before retrying. |