{"openapi":"3.1.0","servers":[{"url":"https://api.managem.co.uk","description":"Production API"}],"info":{"version":"0.0.0","title":"Managem API","description":"\nManagem API is the platform API for the Managem marketplace. It powers discovery, checkout, messaging, account management, and seller operations through a single REST surface with OpenAPI 3.1 documentation.\n\n## API at a glance\n\n- Every action on Managem has a corresponding API route\n- **Public and authenticated access**: public discovery routes for search and profile data, with authenticated routes for account, basket, orders, and seller operations\n- **Domain-first structure** so clients can integrate one product area at a time\n\n## Domain map\n\n### Discover\n\nFind cards and products, resolve item identifiers, inspect item hierarchies, and browse marketplace listings:\n- `/search` and `/search/*` for full-text search, bulk lookup, and hierarchy navigation\n- `/listings` for listing search, seller listing views, and item price history\n- `/profile/{identifier}` for public profile and review data\n\n### Buyer\n\nSupport the full customer lifecycle:\n- `/basket` for basket state, summaries, fees, delivery costs, and checkout session creation\n- `/conversations` for inbox, unread counts, messaging, attachments, and conversation locking\n- `/user/*` for account updates, addresses, purchases, reviews, cases, invoices, portal access, personal access tokens, and account stats\n\n### Seller\n\nOperate and scale marketplace supply:\n- `/seller` for onboarding, account status, dashboard links, vacation mode, and balance\n- `/seller/listings`, `/seller/orders`, and `/seller/cases` for day-to-day trading operations\n- `/seller/delivery-options`, `/seller/payouts`, and `/seller/transfers` for logistics and finance\n- `/seller/imports` for bulk listing workflows\n- `/seller/webhooks` for event delivery, testing, subscriptions, metrics, and failure diagnostics\n\nUse this reference to integrate each domain independently, then compose them into complete marketplace experiences.\n\n## Authentication\n\nProtected routes accept:\n- Access tokens with `Authorization: Bearer <access-token>`.\n- Personal Access Tokens (PATs) with `Authorization: ApiKey <personal-access-token>`.\n\nFor first-party and OAuth-style user sessions, contact support@managem.co.uk to apply for a custom application that you can use to authenticate Managem users.\n\n### Personal Access Tokens (PATs)\n\nPATs are user-scoped API credentials designed for automation, scripts, and server-to-server integrations where interactive login is not practical.\n\nUse the `/user/personal-access-tokens` endpoints to manage them:\n- List active tokens\n- Create new tokens\n- Revoke existing tokens\n\nPAT behavior:\n- Each user can have up to 5 active tokens\n- Token names must be unique per user\n- `expires` is optional, but if provided it must be at least 24 hours in the future\n\nUse PATs with the API key authorization scheme:\n\n```http\nAuthorization: ApiKey <personal-access-token>\n```\n\nRecommended lifecycle:\n1. Create a token for each integration\n2. Store it in a secure secret manager\n3. Rotate on a schedule\n4. Revoke immediately if exposed or no longer needed\n\n## Third-party Integrations\n\nWe welcome third-party integrations that enhance the Managem ecosystem. If you're interested in building an integration, contact us on [Discord](https://discord.gg/qaU4KSEQRd) to arrange the creation of your third-party application, which will allow you to authenticate and link Managem users. We will need:\n- Your application name\n- Your logo\n- A terms of use URL (if you have one)\n- A privacy policy URL (if you have one)\n\nOnce your application has been created, Managem users can sign in to your application. This will provide you with a refreshable access token for each user who links their account, which you can use to make API calls on their behalf.\n\n### Important API Endpoints\n- [Get seller status](https://api.managem.co.uk/#tag/seller-account/GET/seller/status)\n- [Manage seller listings](https://api.managem.co.uk/#tag/listings)\n- [Importing listings](https://api.managem.co.uk/#tag/seller-imports)\n- [Registering webhooks](https://api.managem.co.uk/#tag/seller-webhooks)\n\n"},"tags":[{"name":"search","x-displayName":"Search","description":"\nSearch and discovery endpoints for cards, products, and user references.\n\nThese routes support free-text search, hierarchy-driven browsing, and image embedding search flows.\n"},{"name":"listings","x-displayName":"Listings","description":"\nPublic endpoints for retrieving seller listings.\n"},{"name":"profile","x-displayName":"Profile","description":"\nPublic endpoints for user profiles and reviews.\n"},{"name":"basket","x-displayName":"Basket","description":"\nBasket (cart) endpoints used to add, update, remove, review, and checkout items.\n\nThese routes support both lightweight basket summaries and full checkout-ready pricing breakdowns.\n"},{"name":"conversations","x-displayName":"Conversations","description":"\nEndpoints for messaging between users.\n"},{"name":"user-account","x-displayName":"Account","description":"Manage account profile, credentials and media."},{"name":"user-addresses","x-displayName":"Addresses","description":"Manage saved addresses and postcode lookup for checkout and shipping."},{"name":"user-purchases","x-displayName":"Purchases","description":"List and manage buyer purchases and order updates."},{"name":"user-reviews","x-displayName":"Reviews","description":"\nReviews are the trust layer between buyers and sellers after an order interaction.\n\n## How review permissions work\n\n- Reviews are currently order-scoped only.\n- Only the buyer and seller attached to that order can review each other.\n- You cannot review yourself.\n- Each reviewer can leave only one review per order.\n\n## How review scoring works\n\n1. A valid review is created.\n2. The reviewed user's aggregate rating stats are updated immediately.\n3. If the review is edited, aggregates are recalculated from rating delta.\n4. If the review is deleted, aggregates are adjusted again.\n\n## Auto-generated reviews after inactivity\n\nManagem also backstops missing reviews in the purchase workflow:\n\n1. When a purchase reaches completed state, the workflow starts a review timer.\n2. Managem then waits 14 days for a review to be left manually by either the buyer and/or seller.\n3. For each order in the purchase, if buyer->seller or seller->buyer review is missing, Managem creates a default 5-star review with an automatic message.\n\nThis ensures both parties are not left without reciprocal feedback when one side does not submit a review in time.\n"},{"name":"user-cases","x-displayName":"Cases","description":"\nCases are Managem's dispute workflow between a buyer and seller for contested order items.\n\nFrom the buyer side, these endpoints let you track a dispute from first report to final resolution without leaving the purchase flow.\n\n## Dispute lifecycle (step-by-step)\n\n1. A case begins when disputed items are submitted through a purchase/order dispute action.\n2. Managem opens the case, records reason/comment, links disputed items, and stores initial proposed outcomes.\n3. Both sides can upload case evidence (create upload URL, then finalize attachment).\n4. Both sides can continue negotiation by proposing outcomes (`RETURN`, `REFUND`, `REPLACEMENT`).\n5. Outcomes can be accepted or rejected by the opposite party:\n   - accepted `RETURN` -> case moves to `SETTLED` and later `CLOSED` when resolved\n   - accepted `REFUND`/`REPLACEMENT` -> case moves directly to `CLOSED`\n6. Either party can escalate, and unresolved open/remediation cases are auto-escalated by the system after 7 days.\n\n## Buyer-focused behavior\n\n- If a `RETURN` outcome is proposed, seller return-address details are hidden until a seller accepts the return outcome.\n- Case history is recorded as actions happen, so timeline/audit views can explain who did what.\n- Stats are invalidated as case state changes to keep buyer/seller dashboard counts current.\n\n## Buyer endpoint usage\n\n- `GET /user/cases`: list buyer-owned cases.\n- `GET /user/cases/{id}`: retrieve one case.\n- `PUT /user/cases/{id}`: propose/accept/reject/escalate actions.\n- `POST /user/cases/{id}/attachments` + `PATCH /user/cases/{id}/attachments`: evidence upload flow.\n"},{"name":"user-invoices","x-displayName":"Invoices","description":"List invoices and download invoice documents."},{"name":"user-portal","x-displayName":"Portal","description":"Access the customer billing and subscription portal."},{"name":"user-personal-access-tokens","x-displayName":"Personal Access Tokens","description":"\nCreate, rotate, and revoke Personal Access Tokens (PATs) for non-interactive API integrations.\n\nPATs authenticate as the user who created them. If that user has an active seller account, the PAT can be used to perform seller actions on their behalf, including creating listings, updating orders, and managing webhooks.\n\nTypical integration flow:\n1. Create a PAT from the personal access token endpoints.\n2. Store the token in your secrets manager.\n3. Send requests with `Authorization: ApiKey <personal-access-token>`.\n4. Rotate regularly and revoke tokens that are no longer required.\n\nSecurity boundaries:\n- Maximum 5 active PATs per user.\n- PAT names must be unique per user.\n- Expiry is optional, but when provided it must be at least 24 hours in the future.\n"},{"name":"user-stats","x-displayName":"Stats","description":"Retrieve account-level counters for purchases, cases and messages."},{"name":"seller-account","x-displayName":"Account","description":"Manage seller onboarding, status, dashboard access and vacation mode."},{"name":"seller-finance","x-displayName":"Finance","description":"View balances, transfers and payouts for the authenticated seller."},{"name":"seller-delivery-options","x-displayName":"Delivery Options","description":"Configure package and shipping delivery options."},{"name":"seller-listings","x-displayName":"Listings","description":"Create, search, update and manage seller listings and listing attachments."},{"name":"seller-orders","x-displayName":"Orders","description":"View, update and fulfill seller orders, including shipment attachments."},{"name":"seller-cases","x-displayName":"Cases","description":"\nCases are Managem's dispute workflow between a buyer and a seller for one or more order items.\n\nUse the seller-cases endpoints when a seller needs to review evidence, negotiate an outcome, and close disputes in a structured way.\n\n## Dispute lifecycle (step-by-step)\n\n1. A dispute is opened against order items through an order update action (`action: \"dispute\"`).\n2. Managem creates a case, links disputed items, records initial outcomes, and starts a background case workflow.\n3. Both parties can add evidence using the case attachment upload/finalize flow.\n4. Buyer and seller can propose outcomes (`RETURN`, `REFUND`, `REPLACEMENT`), then accept or reject the other party's proposals.\n5. If a `RETURN` outcome is accepted, the case enters `SETTLED` until the return is resolved (`resolve`), then closes.\n6. If `REFUND` or `REPLACEMENT` is accepted, the case closes directly.\n7. If unresolved, the system escalates open/remediation cases after 7 days.\n\n## Rules and guardrails\n\n- Disputes are limited to eligible order items (for example, not already refunded/resolved/disputed).\n- Items can only be disputed within 30 days of their last update.\n- Outcome amount proposals cannot exceed disputed item total + delivery charge.\n- A party cannot accept or reject its own proposed outcome.\n- Escalated/closed cases are locked from normal case updates.\n\n## Seller endpoint usage\n\n- `GET /seller/cases`: list seller-visible cases.\n- `GET /seller/cases/{id}`: retrieve one seller case with outcomes and attachments.\n- `PUT /seller/cases/{id}`: propose/accept/reject/resolve/escalate.\n- `POST /seller/cases/{id}/attachments` + `PATCH /seller/cases/{id}/attachments`: evidence upload flow.\n"},{"name":"seller-imports","x-displayName":"Imports","description":"\nCreate, monitor, and control CSV-based bulk listing imports for the authenticated seller.\n\nUse imports when you need to create or update many listings in one job without sending per-listing API requests.\n\nAuthentication model:\n- Import endpoints are scoped to the authenticated seller.\n- Use access tokens with `Authorization: Bearer <access-token>`.\n- Personal Access Tokens are also supported with `Authorization: ApiKey <personal-access-token>`.\n\n## Import lifecycle\n\n1. Build a CSV using the exact header and column order shown below.\n2. Upload the file with `POST /seller/imports`.\n3. Track progress with `GET /seller/imports` and `GET /seller/imports/{id}`.\n4. Control active jobs with `PATCH /seller/imports/{id}/status/{mode}` (`pause`, `resume`, `terminate`).\n\nProcessing model:\n- Upload accepts `multipart/form-data` with a `text/csv` file field named `file`.\n- Files are validated, stored, then split into background workflow batches.\n- Each row is applied independently: successful rows are committed even if other rows fail.\n- Import details include per-batch progress and row-level errors (`code`, `message`, `line`).\n\n## CSV contract\n\nCurrent header (recommended, exact order):\n```csv\nMODE,URN,GAME,SET,NAME,CARDMARKET_ID,TCGPLAYER_ID,CONDITION,PRICE,QUANTITY,VARIANTS,HIDDEN,COMMENT,NOTES,REFERENCE\n```\n\nColumn rules:\n- `MODE` (required): `CREATE` or `UPDATE`.\n- Item identity (required): provide at least one of:\n  - `URN` (recommended),\n  - `GAME` + `SET` + `NAME`,\n  - `CARDMARKET_ID`,\n  - `TCGPLAYER_ID`.\n- `CONDITION` (required): one of `MT`, `NM`, `EX`, `GD`, `LP`, `PL`, `PO`.\n- `PRICE` (required): integer price in pence (for example, `100` = £1.00).\n- `QUANTITY` (required): integer quantity.\n- `VARIANTS` (optional): comma-separated variant identifiers.\n- `HIDDEN` (optional): `true` or `false`.\n- `COMMENT`, `NOTES` (optional): free text values.\n- `REFERENCE` (optional): integration-owned listing reference; blank values clear stored reference.\n\nUpload-level validation:\n- Header mismatch returns `400`.\n- Empty files (header only) return `400`.\n- Files over 2,000,000 non-empty rows return `400`.\n\n## Examples\n\n### Create using a URN\n\n```csv\nCREATE,urn:managem:pokemon:set/surging-sparks/card/16,,,,,,NM,350,1,,,,SKU65125,partner-ref-16\n```\n\nCreates a new listing by using Managem's URN identifier, to target a specific item (single card), creating it with a \"Near Mint\" condition for £3.50 and a quantity of 1. It also has a seller note, indicating a SKU that the seller will recognise upon receiving an order containing it, plus a third-party integration reference.\n\n### Create using Game/Set/Name\n\n```csv\nCREATE,,Pokemon,Surging Sparks,Vulpix,,,,LP,200,5,,true,\"Quick delivery\",,erp-ref-vulpix\n```\n\nCreates a new listing for Vulpix, in the Surging Sparks (Pokemon) set. Upon processing this row, our system will perform a search, attempting to match the game, set and name fields with a specific item.\n\n### Create using an external marketplace ID\n\n```csv\nCREATE,,,,,794271,,NM,2,1,,false,,,cardmarket-ref-794271\n```\n\nCreates using Cardmarket's ID for Vulpix in the Surging Sparks (Pokemon) set, to create a new listing.\n\n---\n\n## Statuses\n\n- `RUNNING`: batches are processing.\n- `PAUSED`: processing is paused and can be resumed.\n- `TERMINATED`: job was stopped; already-processed rows remain applied.\n- `FAILED`: one or more rows failed; successful rows remain applied.\n- `COMPLETED`: all rows across all batches finished without row errors.\n\n## Error handling and retries\n\nCommon row error codes:\n- `400`: row validation failed (for example bad types, invalid `CONDITION`, invalid `HIDDEN`).\n- `404`: item/listing not found (lookup miss, or `UPDATE` with no existing seller listing).\n- `409`: ambiguous/conflicting match (multiple item matches or multiple seller listings for one item).\n- `500`: unexpected internal processing error.\n\nRetry pattern:\n1. Open import details and review `errors` entries.\n2. Copy only failing rows into a new CSV with the same header.\n3. Fix the data and upload as a new import job.\n\nRecommended practice:\n- Prefer `URN` for the most deterministic matching.\n- Start with a small smoke test (5-10 rows) before large imports.\n"},{"name":"seller-webhooks","x-displayName":"Webhooks","description":"\nManage outbound event delivery from Managem to your seller integrations.\n\nSeller webhooks let your systems react to marketplace activity without polling. Endpoints in this tag cover full lifecycle management: create, list, update, subscription changes, test delivery, and failure/metrics diagnostics.\n\nAuthentication model:\n- Webhook endpoints are scoped to the authenticated seller.\n- Calls can be authenticated with normal bearer access tokens.\n- Automation services can also use Personal Access Tokens (PATs) created by the seller account and sent as `Authorization: ApiKey <personal-access-token>`.\n\n## Events\n\n### `LISTING_CREATED`\nFired after a listing is successfully created, including single and bulk creates.\n\nPayload\n```json\n{\n  \"type\": \"LISTING_CREATED\",\n  \"data\": {\n    \"sellerId\": \"string\",\n    \"createdAt\": \"ISO-8601 datetime\",\n    \"urn\": \"string\",\n    \"listingId\": \"string\",\n    \"quantity\": \"integer >= 0\",\n    \"price\": \"number >= 0\"\n  }\n}\n```\n\n---\n\n### `LISTING_UPDATED`\nFired after a seller updates an existing listing through `PUT /seller/listings/{id}`.\n\n> Note: Quantity updates from orders do not trigger this event. Only explicit seller-initiated listing updates through the API will fire `LISTING_UPDATED`.\n\nPayload\n```json\n{\n  \"type\": \"LISTING_UPDATED\",\n  \"data\": {\n    \"sellerId\": \"string\",\n    \"createdAt\": \"ISO-8601 datetime\",\n    \"urn\": \"string\",\n    \"listingId\": \"string\",\n    \"quantity\": \"integer >= 0\",\n    \"price\": \"number >= 0\"\n  }\n}\n```\n\n---\n\n### `ORDER_CREATED`\nFired when checkout is committed into seller orders. One event per created seller order.\n\nPayload\n```json\n{\n  \"type\": \"ORDER_CREATED\",\n  \"data\": {\n    \"sellerId\": \"string\",\n    \"createdAt\": \"ISO-8601 datetime\",\n    \"orderId\": \"string\",\n    \"listings\": [\n      {\n        \"urn\": \"string\",\n        \"listingId\": \"string\",\n        \"quantity\": \"integer >= 0\",\n        \"price\": \"number >= 0\"\n      }\n    ]\n  }\n}\n```\n\n---\n\n### `TEST_WEBHOOK`\nFired when you trigger a test delivery for a webhook endpoint. This is a synthetic event type used to validate your receiver logic and endpoint configuration. It is not related to any marketplace activity and will not be fired automatically by any system events.\n\nPayload\n```json\n{\n  \"type\": \"TEST_WEBHOOK\",\n  \"data\": {\n    \"sellerId\": \"string\",\n    \"createdAt\": \"ISO-8601 datetime\"\n  }\n}\n```\n\nForward-compatibility:\n- Subscription enums already include additional event types such as `LISTING_DELETED` and `ORDER_UPDATED`.\n- Receivers should treat unknown event types as forward-compatible additions and ignore unsupported events safely.\n\nRecommended rollout:\n1. Create the endpoint in a disabled state.\n2. Configure subscriptions and optional custom headers.\n3. Run webhook test delivery and validate receiver processing.\n4. Enable deliveries in production.\n5. Monitor reliability with webhook metrics and failure inspection endpoints.\n"},{"name":"seller-stats","x-displayName":"Stats","description":"Retrieve seller counters for orders, cases and listings."}],"x-tagGroups":[{"name":"Discover","tags":["search","listings","profile"]},{"name":"Buyer","tags":["basket","conversations","user-account","user-addresses","user-purchases","user-reviews","user-cases","user-invoices","user-portal","user-personal-access-tokens","user-stats"]},{"name":"Seller","tags":["seller-account","seller-finance","seller-delivery-options","seller-listings","seller-orders","seller-cases","seller-imports","seller-webhooks","seller-stats"]}],"components":{"securitySchemes":{"Bearer":{"type":"http","scheme":"bearer"}},"schemas":{"UserProfile":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"type":"object","properties":{"seller":{"type":"boolean","description":"Indicates if the user is a seller"}},"required":["seller"]}],"description":"User profile information"},"UserSummary":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the user"},"username":{"type":"string","description":"Public username of the user"},"joined":{"type":"string","format":"date-time","description":"ISO timestamp when the user account was created"},"avatar":{"type":"string","format":"uri","description":"URL to the user's avatar image"},"cover":{"type":"string","format":"uri","description":"URL to the user's cover image"},"profile":{"type":"string","description":"Information about the user"},"reviews":{"type":"integer","description":"Total number of reviews the user has received"},"rating":{"type":"number","description":"Confidence-based rating between 0 and 5"},"score":{"type":"number","description":"Average rating between 0 and 5"},"sales":{"type":"integer","description":"Total number of sales the user has made"},"purchases":{"type":"integer","description":"Total number of purchases the user has made"}},"required":["id","username","reviews","rating","score","sales","purchases"],"description":"A minimal representation of a user"},"Reviews":{"type":"array","items":{"$ref":"#/components/schemas/Review"},"description":"List of user reviews"},"Review":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the review"},"rating":{"type":"integer","description":"Rating given in the review"},"content":{"type":"string","description":"Optional textual feedback"},"revisions":{"type":"integer","description":"Number of times the review has been revised"},"source":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["ORDER"]}},"required":["id","type"],"description":"Source associated with the review"},"reviewer":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that wrote the review"}]},"createdAt":{"type":["string","null"],"description":"Timestamp when the review was created"}},"required":["id","rating","revisions","source","reviewer"],"description":"User review"},"ProfileReviewSortDirection":{"type":"string","enum":["asc","desc"],"default":"desc","description":"Sort direction"},"Address":{"type":"object","properties":{"label":{"type":["string","null"],"description":"A recognisable label for the address, e.g. \"Home\", \"Work\""},"type":{"type":"string","enum":["shipping","billing"],"description":"Type of address, 'shipping' or 'billing'"},"line1":{"type":"string","minLength":1,"description":"First line of the formatted address"},"line2":{"type":["string","null"],"description":"Second line of the formatted address"},"city":{"type":"string","minLength":1,"description":"City or town"},"state":{"type":"string","description":"State or province name"},"postalCode":{"type":"string","minLength":1,"description":"Postal or ZIP code"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO 3166-1 alpha-2 country code"},"loqateId":{"type":["string","null"],"description":"The LoqateID of the address, if applicable"},"isValidated":{"type":["boolean","null"],"default":false,"description":"Whether the address has been validated using Loqate"},"isPrimary":{"type":["boolean","null"],"default":false,"description":"Whether the address is the primary address for this type"},"id":{"type":"string","description":"Unique identifier for the address"},"createdAt":{"type":["string","null"],"description":"Timestamp when the address was created"},"updatedAt":{"type":["string","null"],"description":"Timestamp when the address was last updated"}},"required":["type","line1","city","state","postalCode","country","id"],"description":"Information representing a user's address. A user address can be either a shipping or billing address."},"Addresses":{"type":"array","items":{"$ref":"#/components/schemas/Address"},"description":"List of addresses for a user."},"Account":{"type":"object","properties":{"username":{"type":"string","description":"Current username of the user"},"name":{"type":"string","description":"User's given name"},"familyName":{"type":"string","description":"User's family name"},"profile":{"type":"string","description":"User's personal bio or profile description"},"emailAddress":{"type":"string","description":"Primary email address"},"phoneNumber":{"type":"string","description":"Primary phone number"},"avatar":{"type":["string","null"],"format":"uri","description":"URL to avatar"},"cover":{"type":["string","null"],"format":"uri","description":"URL to cover"},"suspended":{"type":"boolean","description":"Whether the user is suspended"},"local":{"type":"boolean","description":"Whether the user has a local password"},"connectedIdentities":{"$ref":"#/components/schemas/ConnectedIdentities"}},"required":["emailAddress","suspended","local","connectedIdentities"],"description":"Represents a user account in the system, including personal details and connected identities.","title":"Account Information"},"ConnectedIdentities":{"type":"array","items":{"$ref":"#/components/schemas/ConnectedIdentity"},"description":"A list of social identities connected to a user","title":"Connected Social Identities"},"ConnectedIdentity":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the identity"},"issuer":{"type":"string","description":"Identity provider issuer"},"createdAt":{"type":"string","description":"When the identity was created"}},"required":["id","issuer","createdAt"],"title":"Connected Social Identity","description":"Represents a social identity connected to a user's account."},"UpdatePassword":{"type":"object","properties":{"password":{"type":"string","minLength":8,"description":"The new password"}},"required":["password"],"description":"Password update payload after policy validation"},"UpdateProfile":{"type":"object","properties":{"familyName":{"type":"string","description":"User's family name"},"name":{"type":"string","description":"User's display name"},"username":{"type":"string","description":"Public username"},"profile":{"type":"string","description":"Brief profile description"}},"description":"Payload used when updating the user's display name"},"VerifyEmail":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email address to verify"}},"required":["email"],"description":"Email address used to trigger a verification email from Logto."},"VerifyPhoneNumber":{"type":"object","properties":{"phone":{"type":"string","description":"Phone number to verify"}},"required":["phone"],"description":"Phone number used to trigger an SMS verification from Logto."},"UpdateEmail":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"Email address to update"},"code":{"type":"string","description":"The verification code received via email"}},"required":["email","code"],"description":"Payload required once the user has confirmed the verification code."},"UpdatePhoneNumber":{"type":"object","properties":{"phone":{"type":"string","description":"Phone number to update"},"code":{"type":"string","description":"The verification code received via SMS"}},"required":["phone","code"],"description":"Payload required once the user has confirmed the verification code."},"Image Upload":{"type":"object","properties":{"id":{"type":"string","description":"Image identifier"},"uploadURL":{"type":"string","format":"uri","description":"URL to upload the image"}},"required":["id","uploadURL"],"description":"Direct upload URL for an image"},"ImageClassificationFailure":{"type":"object","properties":{"reasons":{"type":"array","items":{"type":"string"},"description":"Reasons describing why the image was rejected"}},"required":["reasons"],"description":"Image rejected during moderation"},"Image Upload Complete":{"type":"object","properties":{"id":{"type":"string","description":"Image identifier"}},"required":["id"],"description":"Image identifier to finalize upload"},"PurchaseSummaryList":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseSummary"},"title":"Purchase Summary List","description":"Paginated list of purchases for a user"},"PurchaseSummary":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the purchase"},"customerEmailAddress":{"type":"string","format":"email","description":"Email address used for the purchase"},"deliveryCharge":{"type":"integer","description":"Delivery charge in pence"},"deliveryAddress":{"$ref":"#/components/schemas/DeliveryAddress"},"subtotal":{"type":"integer","description":"Subtotal in pence"},"total":{"type":"integer","description":"Total in pence"},"serviceFee":{"type":"integer","description":"Service fee in pence"},"status":{"$ref":"#/components/schemas/PurchaseStatus"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the purchase was created"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp when the purchase was last updated"},"sellers":{"type":"integer","description":"Number of orders in the purchase"},"invoiceId":{"type":["string","null"],"description":"Invoice identifier generated for the purchase"}},"required":["id","customerEmailAddress","deliveryCharge","deliveryAddress","subtotal","total","serviceFee","createdAt","updatedAt","sellers"],"title":"Purchase Summary","description":"Summary information about a purchase"},"DeliveryAddress":{"type":"object","properties":{"name":{"type":"string"},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"state":{"type":["string","null"]}},"required":["name"],"title":"Delivery Address","description":"Address where the order should be delivered"},"PurchaseStatus":{"type":"string","enum":["ACTIVE","REFUNDED","COMPLETED"],"default":"ACTIVE","title":"Purchase Status","description":"Purchase status"},"SortDirection":{"type":"string","enum":["asc","desc"],"default":"desc","description":"Sort direction"},"OrderItemStatus":{"anyOf":[{"type":"string","enum":["PENDING"]},{"type":"string","enum":["ACCEPTED"]},{"type":"string","enum":["SHIPPED"]},{"type":"string","enum":["DELIVERED"]},{"type":"string","enum":["REFUNDED"]},{"type":"string","enum":["DISPUTED"]},{"type":"string","enum":["RESOLVED"]}],"default":"ACCEPTED","title":"Order Item Status","description":"Current status of the item"},"OrderItem":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the order item"},"status":{"$ref":"#/components/schemas/OrderItemStatus"},"listingId":{"type":"string","description":"Associated listing ID"},"orderId":{"type":"string","description":"Associated order ID"},"urn":{"type":"string","description":"URN of the purchased item"},"price":{"type":"integer","description":"Price per item in pence"},"quantity":{"type":"integer","description":"Quantity purchased"},"condition":{"type":"string","description":"Condition of the listed item"},"language":{"type":"string","description":"Language of the listed item"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed item"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the item was created"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp when the item was last updated"}},"required":["id","listingId","orderId","urn","price","quantity","condition","language","createdAt","updatedAt"],"title":"Order Item","description":"Item included in an order"},"Shipment":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the shipment"},"orderId":{"type":"string"},"trackingNumber":{"type":"string","description":"Carrier tracking number"},"trackingStatus":{"type":"string","description":"Latest tracking status"},"trackingStatusDetail":{"type":"string","description":"Detailed tracking status information"},"trackingUrl":{"type":"string","description":"Public URL to track the shipment"},"carrier":{"type":"string","description":"Shipping carrier"},"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the shipment was created"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the shipment was last updated"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Shipment Attachment"},"description":"Attachments linked to the shipment"}},"required":["id","orderId","trackingNumber","trackingStatus","trackingStatusDetail","trackingUrl","carrier","createdAt","updatedAt","attachments"],"description":"Shipment information for an order"},"Shipment Attachment":{"type":"object","properties":{"id":{"type":"string","description":"Image identifier"},"url":{"type":"string","format":"uri","description":"Public URL for the attachment"},"hidden":{"type":"boolean","description":"True when the attachment is hidden from the buyer"}},"required":["id","url","hidden"],"description":"Image attachment linked to a shipment"},"PurchaseHistoryResponse":{"type":"array","items":{"$ref":"#/components/schemas/PurchaseHistoryEntry"},"title":"Purchase History Response","description":"Chronological history entries for a purchase or order"},"PurchaseHistoryEntry":{"allOf":[{"$ref":"#/components/schemas/PurchaseHistory"},{"type":"object","properties":{"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the history entry was recorded"},"user":{"$ref":"#/components/schemas/PurchaseHistoryActor"},"orderItemIds":{"type":"array","items":{"type":"string"},"default":[],"description":"Identifiers of order items involved in the history entry"}}}],"title":"Purchase History Entry","description":"A single entry within the purchase history timeline"},"PurchaseHistoryParty":{"type":"string","enum":["BUYER","SELLER","SYSTEM"],"title":"Purchase History Party","description":"Which party initiated the action recorded in the history"},"PurchaseHistoryActor":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the user that initiated the action"},"username":{"type":"string","description":"Display name for the user that initiated the action"}},"required":["id","username"],"title":"Purchase History Actor","description":"User that initiated the action, if the action was user driven"},"PurchaseHistory":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the history entry"},"purchaseId":{"type":"string","description":"Identifier of the purchase that this history belongs to"},"orderId":{"type":["string","null"],"description":"Identifier of the order associated with this entry"},"comment":{"type":"string","minLength":1,"description":"Human readable description of the action"},"party":{"$ref":"#/components/schemas/PurchaseHistoryParty"},"userId":{"type":["string","null"],"description":"User identifier of the action initiator, when available"},"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the history entry was created"}},"required":["id","purchaseId","comment","party","createdAt"],"title":"Purchase History","description":"A single entry representing an action taken on a purchase"},"CustomerOrderUpdateRequestWithoutCancel":{"oneOf":[{"type":"object","properties":{"action":{"type":"string","enum":["delivered"]},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"}},"required":["id"]},"description":"Items to mark as delivered"}},"required":["action","items"]},{"type":"object","properties":{"action":{"type":"string","enum":["dispute"]},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["id","quantity"]},"description":"Items to dispute"},"case":{"type":"object","properties":{"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":"string"},"outcomes":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["RETURN"]},"comment":{"type":"string","minLength":1},"amount":{"type":"integer","minimum":0}},"required":["type","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REFUND"]},"comment":{"type":"string","minLength":1},"amount":{"type":"integer","minimum":0}},"required":["type","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REPLACEMENT"]},"comment":{"type":"string","minLength":1}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["RETURN"]},"address":{"type":"object","properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"state":{"type":["string","null"]}}},"amount":{"type":"integer","minimum":0},"comment":{"type":"string","minLength":1}},"required":["type","address","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REFUND"]},"amount":{"type":"integer","minimum":0},"comment":{"type":"string","minLength":1}},"required":["type","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REPLACEMENT"]},"comment":{"type":"string","minLength":1}},"required":["type"]}]},"description":"Proposed outcomes"}},"required":["reason","outcomes"]}},"required":["action","items","case"]}],"description":"Customer-initiated order updates. Use the separate cancel endpoint to cancel a purchase."},"AuthoredReviews":{"type":"array","items":{"$ref":"#/components/schemas/AuthoredReview"},"description":"List of reviews"},"AuthoredReview":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the review"},"rating":{"type":"integer","description":"Rating given in the review"},"content":{"type":"string","description":"Optional textual feedback"},"revisions":{"type":"integer","description":"Number of times the review has been revised"},"source":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["ORDER"]}},"required":["id","type"],"description":"Source associated with the review"},"reviewedUser":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that the review is about"}]},"createdAt":{"type":["string","null"],"description":"Timestamp when the review was created"}},"required":["id","rating","revisions","source","reviewedUser"],"description":"Review authored by the user"},"ReviewSortDirection":{"type":"string","enum":["asc","desc"],"default":"desc","description":"Sort direction"},"ReviewInput":{"type":"object","properties":{"reviewedUserId":{"type":"string","description":"ID of the user being reviewed"},"rating":{"type":"integer","minimum":1,"maximum":5,"description":"Rating between 1 and 5"},"content":{"type":"string","description":"Optional textual feedback"},"source":{"type":"object","properties":{"id":{"type":"string","description":"ID of the order the review is about"},"type":{"type":"string","enum":["ORDER"],"description":"Source type"}},"required":["id","type"],"description":"Source that the review refers to"}},"required":["reviewedUserId","rating","source"],"description":"Input for creating a review"},"ReviewUpdateInput":{"type":"object","properties":{"rating":{"type":"integer","minimum":1,"maximum":5,"description":"Rating between 1 and 5"},"content":{"type":"string","description":"Optional textual feedback"}},"required":["rating"],"description":"Input for updating a review"},"PortalLink":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Link to the Stripe customer portal"}},"required":["url"],"description":"Temporary login link for the Stripe customer portal"},"InvoiceListResponse":{"type":"object","properties":{"invoices":{"type":"array","items":{"$ref":"#/components/schemas/InvoiceSummary"},"description":"Collection of Stripe invoices for the authenticated customer."},"hasMore":{"type":"boolean","description":"Indicates whether more invoices are available beyond the current page."},"nextStartingAfter":{"type":["string","null"],"description":"Identifier to pass as `startingAfter` in the next request when `hasMore` is true."}},"required":["invoices","hasMore","nextStartingAfter"]},"InvoiceSummary":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the Stripe invoice record."},"number":{"type":["string","null"],"description":"Human-friendly invoice number generated by Stripe when the invoice is finalized."},"amountDue":{"type":"number","description":"Total amount due for the invoice in the smallest currency unit."},"createdAt":{"type":"string","description":"ISO 8601 timestamp representing when the invoice was created."}},"required":["id","number","amountDue","createdAt"]},"InvoiceDownloadResponse":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Direct download URL for the invoice PDF generated by Stripe."}},"required":["url"]},"UserCases":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"purchaseId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}}},"required":["id","workflowId","purchaseId","reason","status","createdAt","updatedAt","outcomes","attachments"]}},"UserCaseSortDirection":{"type":"string","enum":["asc","desc"],"default":"desc","description":"Sort direction"},"UserCase":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"purchaseId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}}},"required":["id","workflowId","purchaseId","reason","status","createdAt","updatedAt","outcomes","attachments"]},"UpdatedUserCase":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"purchaseId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}}},"required":["id","workflowId","purchaseId","reason","status","createdAt","updatedAt","outcomes","attachments"]},"UserStats":{"type":"object","properties":{"purchases":{"type":"object","properties":{"total":{"type":"integer","minimum":0,"description":"Total number of purchases for the authenticated user"},"incomplete":{"type":"integer","minimum":0,"description":"Purchases in-flight that have not been completed"}},"required":["total","incomplete"],"description":"Aggregated purchase stats"},"cases":{"type":"object","properties":{"open":{"type":"integer","minimum":0,"description":"Cases linked to the user that are still open or active"}},"required":["open"],"description":"Aggregated case stats"},"messages":{"type":"object","properties":{"unread":{"type":"integer","minimum":0,"description":"Unread conversation messages for the user"}},"required":["unread"],"description":"Aggregated message stats"}},"required":["purchases","cases","messages"],"description":"Aggregated stats for the authenticated user, focusing on purchase progress, active cases, and unread messages."},"PersonalAccessTokens":{"type":"array","items":{"$ref":"#/components/schemas/PersonalAccessToken"}},"PersonalAccessToken":{"type":"object","properties":{"name":{"type":"string","description":"The personal access token name"},"value":{"type":"string","description":"The personal access token value. This is only available immediately after creation."},"createdAt":{"type":"string","format":"date-time","description":"ISO timestamp indicating when the token was created"},"expires":{"type":"string","format":"date-time","description":"ISO timestamp indicating when the token expires"}},"required":["name","value","createdAt"],"description":"Personal access token information returned to the client."},"CreatePersonalAccessToken":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":256,"description":"The personal access token name. Must be unique for the authenticated user."},"expires":{"type":"string","description":"Optional ISO timestamp indicating when the token should expire. Omit to create a non-expiring token.","format":"date-time"}},"required":["name"],"description":"Payload used to create a new personal access token."},"DeletePersonalAccessToken":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":256,"description":"The personal access token name to delete."}},"required":["name"],"description":"Payload used to delete a personal access token by name."},"Listing Attachment":{"type":"object","properties":{"id":{"type":"string","description":"Image identifier"},"url":{"type":"string","format":"uri","description":"Public URL for the attachment"}},"required":["id","url"],"description":"Image attachment linked to a listing"},"Listing Input":{"type":"object","properties":{"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"hidden":{"type":"boolean","default":false,"description":"True when the listing is hidden from buyers"},"urn":{"type":"string","description":"URN of the product being listed"},"notes":{"type":["string","null"],"maxLength":255,"description":"Private notes for the seller such as SKUs or storage locations"},"reference":{"type":["string","null"],"maxLength":255,"description":"Third-party integration reference for this listing"}},"required":["condition","price","language","urn"],"description":"Data required to create a listing"},"BulkListingResponse":{"type":"object","properties":{"successful":{"type":"array","items":{"type":"string"},"description":"URNs processed successfully"},"failed":{"type":"array","items":{"type":"string"},"description":"URNs that failed to process"}},"required":["successful","failed"],"description":"Result of processing bulk listings"},"BulkListingRequest":{"type":"object","properties":{"listings":{"type":"array","items":{"$ref":"#/components/schemas/Listing Input"},"maxItems":200,"description":"Listings to create or update"}},"required":["listings"],"description":"Request payload for bulk listing creation"},"SellerListingSuggestionResponse":{"type":"object","properties":{"suggestions":{"type":"array","items":{"$ref":"#/components/schemas/SellerListingSuggestion"},"description":"Price suggestions retrieved from the KV store. Suggestions are only returned for URNs that exist in the store."}},"required":["suggestions"],"description":"Response payload containing the price suggestions associated with the URNs provided in the request."},"SellerListingSuggestion":{"allOf":[{"$ref":"#/components/schemas/PriceSuggestionValue"},{"type":"object","properties":{"urn":{"type":"string","description":"URN identifying the item the price suggestion applies to."}},"required":["urn"]}],"description":"A price suggestion for a seller listing joined with the URN used to retrieve it."},"PriceSuggestionValue":{"type":"object","properties":{"default":{"type":"integer","description":"Suggested listing price for a normal copy stored as the lowest denomination (for example, pennies)."},"holo":{"type":"integer","description":"Suggested listing price for a holo/foil copy stored as the lowest denomination (for example, pennies)."}},"required":["default"],"description":"Suggested pricing for a listing. All values are represented as integers rather than floating point numbers to avoid rounding errors."},"SellerListingSuggestionRequest":{"type":"object","properties":{"urns":{"type":"array","items":{"type":"string","pattern":"[^/]$"},"minItems":1,"maxItems":50,"description":"Collection of URNs to retrieve price suggestions for."}},"required":["urns"],"description":"Request payload containing one or more URNs that should be resolved into price suggestions."},"Listing Search Result":{"type":"object","properties":{"total":{"type":"number","description":"Total number of results"},"hits":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item"]},"description":"List of listings"},"facets":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"number"}},"description":"Facets that can be applied to further refine the search results"}},"required":["total","hits","facets"],"description":"Result of a listings search query"},"SearchQuery":{"type":"object","properties":{"query":{"type":"string","description":"One or more free text search terms"},"filters":{"type":"array","items":{"type":"object","additionalProperties":{}}},"facets":{"type":"object","properties":{"Game":{"type":"array","items":{"type":"string"},"description":"Game name to match, e.g. Pokemon or Magic"},"Product Type":{"type":"array","items":{"type":"string"},"description":"Type of product, for example \"card\" or \"product\""},"Rarity":{"type":"array","items":{"type":"string"},"description":"Card rarity values"},"Series":{"type":"array","items":{"type":"string"},"description":"Series names"},"Set":{"type":"array","items":{"type":"string"},"description":"Set names"},"Illustrator":{"type":"array","items":{"type":"string"},"description":"Illustrator names as stored on item images"},"Condition":{"type":"array","items":{"type":"string"},"description":"Listing condition codes, e.g. MT, NM"},"Grading":{"type":"array","items":{"type":"string","enum":["Graded","Ungraded"]},"description":"Whether the card is \"Graded\" or \"Ungraded\""},"Price":{"type":"array","items":{"type":"string","enum":["Under £1","£1-£10","£10-£20","£20-£50","£50-£100","Over £100"]},"description":"Price buckets expressed in pounds sterling (inclusive of lower bounds)"},"Quantity":{"type":"array","items":{"type":"string","enum":["1","2-10","10-50","50+"]},"description":"Quantity buckets for available stock"},"Valid":{"type":"array","items":{"type":"string","enum":["Valid","Invalid"]},"description":"Listing validity status for seller views"},"Hidden":{"type":"array","items":{"type":"string","enum":["Hidden","Visible"]},"description":"Listing visibility status for seller views"},"Availability":{"type":"array","items":{"type":"string","enum":["In Stock"]},"description":"Filter listings or items to only those that are \"In Stock\""},"Category":{"type":"array","items":{"type":"string"},"description":"Item categories (metadata)"}},"additionalProperties":{"type":"array","items":{"type":"string"},"description":"Additional facets accepted by the search endpoints. Unknown keys are passed through verbatim and applied as term filters."},"description":"Facets to refine the search results. Values are case-sensitive unless noted otherwise."},"from":{"type":["number","null"],"default":0,"description":"Offset for pagination"},"size":{"type":"number","minimum":1,"maximum":50,"default":25,"description":"Number of results to return"},"sorting":{"type":"object","properties":{"field":{"type":"string","enum":["name","number","indexed","price"]},"order":{"type":"string","enum":["asc","desc"]}},"required":["field","order"],"description":"Sort results by field and order"}},"title":"Search Query","description":"A search query includes a free text query property, refinements in the form of facets, pagination controls and optional sorting."},"ListingListResponse":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"},"valid":{"type":"boolean","description":"True when the listing meets all requirements"},"hidden":{"type":"boolean","description":"True when the listing is hidden from buyers"},"notes":{"type":["string","null"],"maxLength":255,"description":"Private notes for the seller such as SKUs or storage locations"},"reference":{"type":["string","null"],"maxLength":255,"description":"Third-party integration reference for this listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked","valid","hidden"]},"title":"Seller Listings","description":"Listings for a specific item owned by the authenticated seller"},"Listing Update":{"type":"object","properties":{"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"hidden":{"type":"boolean","default":false,"description":"True when the listing is hidden from buyers"},"notes":{"type":["string","null"],"maxLength":255,"description":"Private notes for the seller such as SKUs or storage locations"},"reference":{"type":["string","null"],"maxLength":255,"description":"Third-party integration reference for this listing"}},"description":"Fields that can be updated on a listing"},"AttachmentClassificationFailure":{"type":"object","properties":{"reasons":{"type":"array","items":{"type":"string"},"description":"Reasons describing why the image was rejected"}},"required":["reasons"],"description":"Image rejected during moderation"},"ListingAttachmentDelete":{"type":"object","properties":{"id":{"type":"string","description":"Image identifier"}},"required":["id"],"description":"Attachment to delete"},"DeliveryConfiguration":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["LARGE_LETTER"],"description":"The configured package type"},"classifications":{"type":"array","items":{"type":"string","enum":["CARD"]}},"steps":{"type":"array","items":{"type":"object","properties":{"cost":{"type":"integer","minimum":0,"description":"The base cost for this package type, in pence"},"weight":{"type":"integer","minimum":0,"description":"Maximum weight in grams"}},"required":["cost","weight"]}},"id":{"type":"string","description":"Unique identifier for the configuration"}},"required":["type","classifications","steps","id"]},"title":"Delivery Configuration","description":"All package configurations for a seller, sorted by package type (large letter to large parcel"},"PackageConfigurationInput":{"type":"object","properties":{"type":{"type":"string","enum":["LARGE_LETTER"],"description":"The configured package type"},"classifications":{"type":"array","items":{"type":"string","enum":["CARD"]}},"steps":{"type":"array","items":{"type":"object","properties":{"cost":{"type":"integer","minimum":0,"description":"The base cost for this package type, in pence"},"weight":{"type":"integer","minimum":0,"description":"Maximum weight in grams"}},"required":["cost","weight"]}}},"required":["type","classifications","steps"],"title":"Package Configuration Input","description":"Values used to configure seller shipping configuration and costs"},"OrderSummaryResponse":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/Order"},{"type":"object","properties":{"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order was created"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order was last updated"},"items":{"type":"integer","description":"Number of items in the order"},"shipments":{"type":"integer","description":"Number of shipments"}}}],"title":"Order","description":"Order placed by a user for a seller, including items and shipments"},"title":"Order Summary List","description":"Paginated list of order summaries"},"Order":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the order"},"sellerId":{"type":"string","description":"Seller user ID"},"purchaseId":{"type":"string","description":"Purchase ID"},"deliveryCharge":{"type":"integer","description":"Delivery charge in pence"},"subtotal":{"type":"integer","description":"Subtotal in pence"},"total":{"type":"integer","description":"Total in pence"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the order was created"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp when the order was last updated"},"items":{"type":"array","items":{"$ref":"#/components/schemas/OrderItem"}},"shipments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the shipment"},"orderId":{"type":"string"},"trackingNumber":{"type":"string","description":"Carrier tracking number"},"trackingStatus":{"type":"string","description":"Latest tracking status"},"trackingStatusDetail":{"type":"string","description":"Detailed tracking status information"},"trackingUrl":{"type":"string","description":"Public URL to track the shipment"},"carrier":{"type":"string","description":"Shipping carrier"},"createdAt":{"type":"string","format":"date-time","default":"2026-10-22T06:06:46.587Z","description":"Timestamp when the shipment was created"},"updatedAt":{"type":"string","format":"date-time","default":"2026-10-22T06:06:46.587Z","description":"Timestamp when the shipment was last updated"}},"required":["id","orderId","trackingNumber","trackingStatus","trackingStatusDetail","trackingUrl","carrier"]}}},"required":["id","sellerId","purchaseId","deliveryCharge","subtotal","total","createdAt","updatedAt","items","shipments"],"title":"Order","description":"Order placed by a user for a seller, including items and shipments"},"OrderSortDirection":{"type":"string","enum":["asc","desc"],"default":"desc","description":"Sort direction"},"SellerOrderDetailResponse":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the order"},"sellerId":{"type":"string","description":"Seller user ID"},"purchaseId":{"type":"string","description":"Purchase ID"},"deliveryCharge":{"type":"integer","description":"Delivery charge in pence"},"subtotal":{"type":"integer","description":"Subtotal in pence"},"total":{"type":"integer","description":"Total in pence"},"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order was created"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order was last updated"},"items":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/OrderItem"},{"type":"object","properties":{"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order item was created"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order item was updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","minimum":0}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","minimum":0}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}]},"shipmentId":{"type":"string","description":"Identifier of the shipment associated with this item"}},"required":["item"]}],"title":"Order Item","description":"Item included in an order"},"description":"Items included in the order with item details"},"shipments":{"type":"array","items":{"$ref":"#/components/schemas/Shipment"},"description":"Shipments for the order"},"purchase":{"type":"object","properties":{"deliveryAddress":{"$ref":"#/components/schemas/DeliveryAddress"},"user":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that placed the order"}]}},"required":["deliveryAddress"]},"adjustments":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","description":"Adjustment amount in pence, positive or negative"},"comment":{"type":"string","description":"Reason for the adjustment"},"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the adjustment was created"}},"required":["amount","comment","createdAt"]},"default":[],"description":"Order-level adjustments (e.g., delivery refunds)"},"transfers":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["PAYOUT","REVERSAL"],"description":"Transfer type"},"amount":{"type":"integer","description":"Amount in pence moved by this transfer"},"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the transfer was created"}},"required":["type","amount","createdAt"]},"default":[],"description":"Payouts and reversals associated with this order"},"reviews":{"type":"object","additionalProperties":{"type":"integer"},"default":{},"description":"Reviews for the order keyed by the reviewer's user ID with their rating"},"cases":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}},"orderId":{"type":"string"}},"required":["id","workflowId","reason","status","createdAt","updatedAt","outcomes","attachments","orderId"]},"description":"Cases associated with the order"}},"required":["id","sellerId","purchaseId","deliveryCharge","subtotal","total","createdAt","updatedAt","items","shipments","purchase","cases"],"title":"Seller Order Detail","description":"Order with items and shipments for sellers"},"PackingSlipFormat":{"type":"string","enum":["pdf","csv"],"description":"Format to generate the packing slip in"},"Seller Order Update":{"oneOf":[{"type":"object","properties":{"action":{"type":"string","enum":["accept"]},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["id","quantity"]},"description":"Items to accept"}},"required":["action","items"]},{"type":"object","properties":{"action":{"type":"string","enum":["ship"]},"shipment":{"type":"object","properties":{"trackingNumber":{"type":"string"},"carrier":{"type":"string","enum":["Royal Mail","Evri","DHL Express","DPD UK","UPS","Parcelforce","FedEx"],"description":"Supported carriers for EasyPost tracking"}},"required":["trackingNumber","carrier"],"description":"Shipment details including tracking number and carrier"},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["id","quantity"]},"description":"Items to ship"}},"required":["action","shipment","items"]},{"type":"object","properties":{"action":{"type":"string","enum":["dispute"]},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"quantity":{"type":"integer","exclusiveMinimum":0}},"required":["id","quantity"]},"description":"Items to dispute"},"case":{"type":"object","properties":{"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":"string"},"outcomes":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["RETURN"]},"address":{"type":"object","properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"state":{"type":["string","null"]}}},"amount":{"type":"integer","minimum":0},"comment":{"type":"string","minLength":1}},"required":["type","address","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REFUND"]},"amount":{"type":"integer","minimum":0},"comment":{"type":"string","minLength":1}},"required":["type","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REPLACEMENT"]},"comment":{"type":"string","minLength":1}},"required":["type"]}]},"description":"Proposed outcomes"}},"required":["reason","outcomes"]}},"required":["action","items","case"]}],"description":"Update actions that can be performed by a seller"},"SellerCases":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}},"orderId":{"type":"string"}},"required":["id","workflowId","reason","status","createdAt","updatedAt","outcomes","attachments","orderId"]},"description":"Cases"},"SellerCaseSortDirection":{"type":"string","enum":["asc","desc"],"default":"desc","description":"Sort direction"},"SellerCase":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}},"orderId":{"type":"string"}},"required":["id","workflowId","reason","status","createdAt","updatedAt","outcomes","attachments","orderId"]},"UpdatedSellerCase":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}},"orderId":{"type":"string"}},"required":["id","workflowId","reason","status","createdAt","updatedAt","outcomes","attachments","orderId"]},"SellerStats":{"type":"object","properties":{"orders":{"type":"object","properties":{"total":{"type":"integer","minimum":0,"description":"Total number of orders associated with the seller"},"open":{"type":"integer","minimum":0,"description":"Total number of orders that have not been completed"},"waiting":{"type":"integer","minimum":0,"description":"Orders requiring action from the seller (e.g., orders that need shipping)"}},"required":["total","open","waiting"],"description":"Aggregated order stats for the seller"},"cases":{"type":"object","properties":{"open":{"type":"integer","minimum":0,"description":"Cases related to the seller that have not been closed, including escalations and remediation"}},"required":["open"],"description":"Aggregated case stats for the seller"},"listings":{"type":"object","properties":{"total":{"type":"integer","minimum":0,"description":"Total number of listings associated with the seller"},"invalid":{"type":"integer","minimum":0,"description":"Number of listings that are invalid (e.g., missing images)"}},"required":["total","invalid"],"description":"Aggregated listing stats for the seller"}},"required":["orders","cases","listings"],"description":"Aggregated stats for the authenticated seller, covering orders, cases, and listings."},"WebhookEventSeries":{"type":"array","items":{"type":"object","properties":{"time":{"type":"string","description":"ISO timestamp for the interval"},"events":{"$ref":"#/components/schemas/WebhookEventStats"}},"required":["time","events"]},"title":"Webhook Event Series","description":"Aggregated webhook event statistics over time"},"WebhookEventStats":{"type":"object","properties":{"type":{"type":"string","description":"Type of webhook event"},"success":{"type":"number","description":"Number of successful webhook events"},"failure":{"type":"number","description":"Number of failed webhook events"}},"required":["type","success","failure"],"title":"Webhook Event Statistics","description":"Statistics for webhook events over a time range"},"SellerWebhookListResponse":{"type":"object","properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/SellerWebhookEndpoint"},"description":"Collection of webhook endpoints owned by the seller"}},"required":["webhooks"],"title":"Seller Webhook List Response","description":"Response containing a list of the seller's webhook endpoints."},"SellerWebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the webhook endpoint"},"url":{"type":"string","format":"uri","description":"Destination URL for webhook deliveries"},"description":{"type":["string","null"],"description":"Optional human readable description"},"enabled":{"type":"boolean","description":"Indicates whether the webhook is currently active"},"additionalHeaders":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional headers sent with each webhook request"},"secret":{"type":"string","description":"Shared secret used to generate webhook signatures"},"lastSuccessAt":{"type":["string","null"],"format":"date-time","description":"Timestamp of the most recent successful delivery"},"lastFailureAt":{"type":["string","null"],"format":"date-time","description":"Timestamp of the most recent failed delivery"},"consecutiveFailures":{"type":"integer","description":"Current number of consecutive delivery failures"},"maxConsecutiveFailures":{"type":"integer","description":"Threshold at which the webhook will automatically be disabled"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the webhook endpoint was created"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp when the webhook endpoint was last updated"},"subscriptions":{"type":"array","items":{"type":"string","enum":["LISTING_CREATED","LISTING_UPDATED","LISTING_DELETED","ORDER_CREATED","ORDER_UPDATED","TEST"],"description":"Event types that can trigger a webhook notification"},"description":"Event types that the webhook is subscribed to"}},"required":["id","url","enabled","additionalHeaders","secret","lastSuccessAt","lastFailureAt","consecutiveFailures","maxConsecutiveFailures","createdAt","updatedAt","subscriptions"],"title":"Seller Webhook Endpoint","description":"Represents a webhook endpoint configured by a seller to receive event notifications."},"CreateSellerWebhookRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Destination URL that will receive webhook deliveries"},"description":{"type":"string","maxLength":1024,"description":"Optional human readable description"},"enabled":{"type":"boolean","description":"Whether the webhook should be active immediately"},"additionalHeaders":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional headers to include on webhook deliveries"},"subscriptions":{"type":"array","items":{"type":"string","enum":["LISTING_CREATED","LISTING_UPDATED","LISTING_DELETED","ORDER_CREATED","ORDER_UPDATED","TEST"],"description":"Event types that can trigger a webhook notification"},"minItems":1,"description":"Initial subscriptions to associate with the webhook"}},"required":["url","subscriptions"],"title":"Create Seller Webhook","description":"Request body for creating a new webhook endpoint."},"UpdateSellerWebhookRequest":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Destination URL that will receive webhook deliveries"},"description":{"type":"string","maxLength":1024,"description":"Optional human readable description"},"enabled":{"type":"boolean","description":"Whether the webhook should be active immediately"},"additionalHeaders":{"type":"object","additionalProperties":{"type":"string"},"description":"Additional headers to include on webhook deliveries"},"subscriptions":{"type":"array","items":{"type":"string","enum":["LISTING_CREATED","LISTING_UPDATED","LISTING_DELETED","ORDER_CREATED","ORDER_UPDATED","TEST"],"description":"Event types that can trigger a webhook notification"},"minItems":1,"description":"Initial subscriptions to associate with the webhook"}},"title":"Update Seller Webhook","description":"Fields that can be updated on a webhook endpoint"},"UpdateSellerWebhookSubscriptionsRequest":{"type":"object","properties":{"events":{"type":"array","items":{"type":"string","enum":["LISTING_CREATED","LISTING_UPDATED","LISTING_DELETED","ORDER_CREATED","ORDER_UPDATED","TEST"],"description":"Event types that can trigger a webhook notification"},"description":"Full list of event types that the webhook should be subscribed to"}},"required":["events"],"title":"Update Seller Webhook Subscriptions","description":"Request body for updating the event subscriptions of a webhook endpoint."},"SellerWebhookFailureListResponse":{"type":"object","properties":{"failures":{"type":"array","items":{"$ref":"#/components/schemas/SellerWebhookFailure"},"description":"Collection of recorded webhook delivery failures"}},"required":["failures"],"title":"Seller Webhook Failure List Response","description":"Response containing a list of webhook delivery failures for a specific webhook endpoint."},"SellerWebhookFailure":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the webhook failure"},"responseStatusCode":{"type":"integer","description":"HTTP response status code returned by the endpoint"},"responseTime":{"type":"integer","description":"Time taken for the endpoint to respond in milliseconds"},"reason":{"type":"string","description":"Reason describing why the delivery failed"},"harKey":{"type":"string","description":"Key for the HAR payload stored within the R2 bucket"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the failure was recorded"}},"required":["id","responseStatusCode","responseTime","reason","harKey","createdAt"],"title":"Seller Webhook Failure","description":"Represents a recorded failure of a webhook delivery attempt."},"Seller":{"type":"object","properties":{"sellerId":{"type":"string","description":"Stripe seller account ID"},"status":{"type":"string","description":"Current seller status"},"onboardingUrl":{"type":"string","format":"uri","description":"URL for the Stripe onboarding flow"}},"required":["sellerId","status","onboardingUrl"],"description":"Information about a user's seller account"},"SellerAccount":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the seller account"},"email":{"type":"string","format":"email","description":"Seller's contact email address"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"Two-letter ISO country code of the seller"},"defaultCurrency":{"type":"string","description":"Default currency code used by the seller (ISO 4217)"},"detailsSubmitted":{"type":"boolean","description":"Indicates if the seller has completed onboarding"},"chargesEnabled":{"type":"boolean","description":"Whether the seller is able to accept charges"},"payoutsEnabled":{"type":"boolean","description":"Whether the seller is able to receive payouts"},"requirements":{"type":"object","properties":{"currentlyDue":{"type":"array","items":{"type":"string"},"description":"List of fields immediately required from the seller"},"pastDue":{"type":"array","items":{"type":"string"},"description":"List of overdue fields required from the seller"},"eventuallyDue":{"type":"array","items":{"type":"string"},"description":"List of fields that will eventually be required"},"disabledReason":{"type":["string","null"],"description":"Reason why the seller's account might be disabled"}},"required":["currentlyDue","pastDue","eventuallyDue","disabledReason"],"description":"Details on account verification and compliance requirements"},"businessProfile":{"type":"object","properties":{"name":{"type":["string","null"],"description":"Seller's business name"},"url":{"type":["string","null"],"format":"uri","description":"URL of the seller's business website"},"supportEmail":{"type":["string","null"],"format":"email","description":"Email address for customer support inquiries"},"supportPhone":{"type":["string","null"],"description":"Phone number for customer support inquiries"}},"required":["name","url","supportEmail","supportPhone"],"description":"Business profile information provided by the seller"},"settings":{"type":"object","properties":{"payouts":{"type":"object","properties":{"schedule":{"type":"object","properties":{"delayDays":{"type":"number","description":"Number of days between transactions and payouts"},"interval":{"type":"string","enum":["daily","weekly","monthly","manual"],"description":"Frequency of payouts"}},"required":["delayDays","interval"],"description":"Schedule for seller payouts"},"statementDescriptor":{"type":["string","null"],"description":"Descriptor appearing on bank statements"}},"required":["schedule","statementDescriptor"],"description":"Seller payout configuration"},"dashboard":{"type":"object","properties":{"timezone":{"type":"string","description":"Configured timezone of the seller's dashboard"}},"required":["timezone"],"description":"Dashboard configuration settings"}},"required":["payouts","dashboard"],"description":"Seller-specific settings and preferences"}},"required":["id","email","country","defaultCurrency","detailsSubmitted","chargesEnabled","payoutsEnabled","requirements","businessProfile","settings"],"description":"Stripe account information for a seller, sourced from the Stripe API"},"Dashboard Link":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Link to the Stripe Express dashboard"}},"required":["url"],"description":"Stripe Express login link for a seller"},"SellerBalance":{"type":"object","properties":{"pending":{"type":"number","description":"Pending balance in the smallest currency unit"},"available":{"type":"number","description":"Available balance in the smallest currency unit"},"currency":{"type":"string","description":"Three-letter ISO currency code of the balance"}},"required":["pending","available","currency"],"description":"Current available balance for the seller account"},"Payout":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the payout"},"amount":{"type":"number","description":"Amount of the payout in the smallest currency unit"},"currency":{"type":"string","description":"Currency for the payout"},"arrivalDate":{"type":"string","description":"Estimated date when the payout will arrive"},"status":{"type":"string","description":"Current status of the payout"}},"required":["id","amount","currency","arrivalDate","status"],"description":"Information returned after creating a payout"},"PayoutInput":{"type":"object","properties":{"amount":{"type":"integer","exclusiveMinimum":0,"description":"Amount to withdraw in the smallest currency unit"},"currency":{"type":"string","description":"Three-letter ISO currency code for the payout"}},"required":["amount","currency"],"description":"Details required to initiate a payout"},"PayoutList":{"type":"object","properties":{"cursor":{"type":"string","description":"Cursor for the next page of results"},"payouts":{"$ref":"#/components/schemas/Payouts"}},"required":["payouts"],"description":"Paginated payouts using a cursor for more results"},"Payouts":{"type":"array","items":{"$ref":"#/components/schemas/Payout"},"description":"Payouts returned for this page"},"TransferList":{"type":"object","properties":{"cursor":{"type":"string","description":"Cursor for the next page of results"},"transfers":{"$ref":"#/components/schemas/Transfers"}},"required":["transfers"],"description":"Paginated transfers using a cursor for more results"},"Transfers":{"type":"array","items":{"$ref":"#/components/schemas/Transfer"},"description":"Transfers returned for this page"},"Transfer":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the transfer"},"amount":{"type":"number","description":"Amount of the transfer in the smallest currency unit"},"currency":{"type":"string","description":"Three-letter ISO currency code of the transfer"},"created":{"type":"string","description":"Timestamp when the transfer was created"},"reversed":{"type":"boolean","description":"True if the transfer has been fully reversed"},"description":{"type":"string","description":"Description/Reason for the transfer"},"orderId":{"type":"string","description":"An associated Order ID, if applicable"},"orderItemId":{"type":"string","description":"An associated item from the order, if applicable"}},"required":["id","amount","currency","created","reversed","description"],"description":"Transfer of funds sent to the seller account"},"Item Price Series":{"type":"array","items":{"$ref":"#/components/schemas/ItemPricePoint"},"title":"Item Price Series","description":"Aggregated pricing for an item"},"ItemPricePoint":{"type":"object","properties":{"time":{"type":"string","description":"ISO timestamp for the interval"},"listed":{"$ref":"#/components/schemas/PriceStats"},"sold":{"$ref":"#/components/schemas/PriceStats"}},"required":["time","listed","sold"],"title":"Item Price Point","description":"Price point for an item"},"PriceStats":{"type":"object","properties":{"min":{"type":"number","description":"Minimum price in pence"},"max":{"type":"number","description":"Maximum price in pence"},"avg":{"type":"number","description":"Average price in pence"},"vol":{"type":"number","description":"Total quantity captured for the aggregation window"}},"required":["min","max","avg","vol"],"title":"Pricing Information","description":"Statistics for a price range"},"SearchItemsResult":{"type":"object","properties":{"total":{"type":"number"},"hits":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set"]}]}},"facets":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"number"}}}},"required":["total","hits","facets"]},"VectorSearchResponse":{"type":"object","properties":{"count":{"type":"integer","minimum":0,"description":"Number of matches returned for the submitted vector."},"matches":{"type":"array","items":{"$ref":"#/components/schemas/VectorSearchMatch"},"description":"Scored vector matches sorted from most similar to least similar."}},"required":["count","matches"],"description":"Similarity search results for a single trading card image embedding."},"VectorSearchMatch":{"allOf":[{"$ref":"#/components/schemas/VectorizedCardMetadata"},{"type":"object","properties":{"score":{"type":"number"}},"required":["score"]}],"description":"A single scored vector match containing the matched card metadata."},"VectorizedCardMetadata":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"number":{"type":["string","null"]},"image":{"type":"string"}},"required":["urn","game","title","image"],"description":"Card metadata returned for a vector search match. This mirrors the searchable card attributes stored alongside the image embedding."},"VectorSearchRequest":{"type":"object","properties":{"limit":{"type":"integer","minimum":1,"maximum":10,"description":"Maximum number of matches to return. Must be between 1 and 10. Defaults to 5.","example":3},"vectors":{"type":"array","items":{"type":"number"},"description":"A 512-dimensional image embedding prepared from a single trading card image."}},"required":["vectors"],"description":"Request payload for similarity search using a precomputed trading card image embedding."},"LookupUsersResult":{"type":"array","items":{"$ref":"#/components/schemas/UserSummary"},"title":"User Lookup","description":"Array of users with their IDs and usernames."},"Conversations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the conversation"},"source":{"type":"object","properties":{"type":{"type":"string","enum":["ORDER","CASE"],"description":"Source type"},"id":{"type":"string","description":"Source identifier"}},"required":["type","id"],"description":"Conversation source"},"userA":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"First participant"}]},"userB":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Second participant"}]},"locked":{"type":"boolean","description":"Whether the conversation is locked"},"createdAt":{"type":["string","null"],"description":"Timestamp when the conversation was created"},"updatedAt":{"type":["string","null"],"description":"Timestamp when the conversation was last updated"},"lastMessage":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the message"},"conversationId":{"type":"string","description":"Conversation this message belongs to"},"sender":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that sent the message"}]},"body":{"type":"string","description":"Content of the message"},"createdAt":{"type":["string","null"],"description":"Timestamp when the message was created"},"viewedAt":{"type":["string","null"],"description":"Timestamp when the message was viewed"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Message Attachment"},"description":"Images attached to the message"}},"required":["id","conversationId","sender","body"],"description":"Latest message in the conversation"}},"required":["id","source","userA","userB","locked"]},"description":"List of conversations for the user, including the latest message"},"Message Attachment":{"type":"object","properties":{"id":{"type":"string","description":"Attachment identifier"},"imageId":{"type":"string","description":"Cloudflare image identifier"},"url":{"type":"string","format":"uri","description":"Public URL for the attachment"}},"required":["id","imageId","url"],"description":"Image attachment linked to a message"},"ConversationSortDirection":{"type":"string","enum":["asc","desc"],"default":"desc","description":"Sort direction"},"Create Conversation Input":{"type":"object","properties":{"source":{"type":"object","properties":{"type":{"type":"string","enum":["ORDER","CASE"],"description":"Source type"},"id":{"type":"string","description":"Source identifier"}},"required":["type","id"],"description":"Conversation source"},"recipientId":{"type":"string","description":"User ID of the conversation recipient"},"body":{"type":"string","description":"Initial message body. Links, emojis and profanity are sanitized."}},"required":["source","recipientId","body"],"description":"Data required to create a new conversation with an initial message"},"Messages":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the message"},"conversationId":{"type":"string","description":"Conversation this message belongs to"},"sender":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that sent the message"}]},"body":{"type":"string","description":"Content of the message"},"createdAt":{"type":["string","null"],"description":"Timestamp when the message was created"},"viewedAt":{"type":["string","null"],"description":"Timestamp when the message was viewed"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Message Attachment"},"description":"Images attached to the message"}},"required":["id","conversationId","sender","body"]},"description":"Paginated list of messages within a conversation"}},"parameters":{}},"paths":{"/profile/{identifier}":{"get":{"tags":["profile"],"operationId":"getProfile","summary":"Get profile","description":"\nRetrieve the public profile for a user.\n\nUse this endpoint for public profile pages and seller preview cards.\n\nPath behavior:\n- Accepts either a user ID or username as the identifier.\n","parameters":[{"schema":{"type":"string","description":"User ID or username for the requested profile"},"required":true,"description":"User ID or username for the requested profile","name":"identifier","in":"path"}],"responses":{"200":{"description":"User profile","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}}}}},"/profile/{identifier}/reviews":{"get":{"tags":["profile"],"operationId":"getProfileReviews","summary":"List reviews","description":"\nRetrieve paginated reviews for a public user profile.\n\nUse this endpoint to show profile reputation and feedback history.\n\nQuery behavior:\n- Supports pagination and timestamp sorting.\n","parameters":[{"schema":{"type":"string","description":"User ID or username for the requested profile"},"required":true,"description":"User ID or username for the requested profile","name":"identifier","in":"path"},{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number, defaults to 1"},"required":false,"description":"Page number, defaults to 1","name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Results per page, defaults to 20"},"required":false,"description":"Results per page, defaults to 20","name":"size","in":"query"},{"schema":{"type":"string","enum":["createdAt"],"default":"createdAt","description":"Field to sort by"},"required":false,"description":"Field to sort by","name":"sort","in":"query"},{"schema":{"$ref":"#/components/schemas/ProfileReviewSortDirection"},"required":false,"description":"Sort direction","name":"direction","in":"query"}],"responses":{"200":{"description":"User reviews","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Reviews"}}}}}}},"/user/addresses/lookup/find":{"post":{"operationId":"findAddresses","summary":"Find addresses","description":"\nSearch for address suggestions from a free-text query.\n\nUse this endpoint as step 1 in an assisted address-entry flow.\n\nRequest guidance:\n\n- Provide a user-entered text value such as postcode, street name, or partial address.\n- Provide container when refining from a previous response.\n- Include a valid bearer token; this is an authenticated user endpoint.\n\nRecommended flow:\n\n1. Call POST /user/addresses/lookup/find with text from the user input.\n2. If container-type results are returned, call this endpoint again with container to drill down.\n3. When an address result is selected, call POST /user/addresses/lookup/retrieve with its id.\n4. Persist the final address with POST /user/addresses.\n\nBehavior notes:\n\n- Returns suggestions only; no address is saved to the account.\n- Responses may include both final addresses and intermediate container nodes.\n- Empty results are valid and should be handled in UI as \"no matching addresses found\".\n","tags":["user-addresses"],"security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"The search term provided by the user","example":"55 Walnut tr"},"container":{"type":"string","description":"The ID of a container to refine the search","example":"GB|RM|A|10321882|ENG"},"limit":{"type":"number","maximum":20,"minimum":1,"default":10,"description":"The maximum number of results to return"}},"required":["text"]},"examples":{"Search by \"text\"":{"description":"Lookup an address by \"text\"","value":{"text":"34 Selborne Cl"}},"Refine search by \"container\"":{"description":"Lookup an address by \"text\" and \"container\"","value":{"text":"SW14 8E","container":"gb-rm|5uJwYJYB1H6m_iwEyrBr"}}}}}},"responses":{"200":{"description":"Find a list of addresses, or containers to refine the user's search","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The ID of the location, use this to retrieve the full address"},"description":{"type":"string","description":"A description of the location or \"container\""},"type":{"anyOf":[{"type":"string","enum":["Container"]},{"type":"string","enum":["Address"]},{"type":"string","enum":["Postcode"]},{"type":"string","enum":["Residential"]},{"type":"string","enum":["Street"]}],"description":"The type of location, e.g. \"Address\", \"Postcode\", etc."},"text":{"type":"string","description":"The text matching the provided search"},"highlight":{"type":"string","description":"A comma-separated list of highlighted indices in the text, ie. 0-2,3-9"}},"required":["id","description","type","text","highlight"]}},"examples":{"Search by text":{"description":"Lookup an address by \"text\"","value":[{"id":"GB|RM|A|10321882|ENG","description":"Petersfield GU32 2JB","type":"Address","text":"34 Selborne Close","highlight":"0-2,3-11,12-14"}]},"Refine search by container":{"description":"Lookup an address by \"text\" and \"container\"","value":[{"id":"GB|RM|A|23968914|ENG","description":"London SW14 8EX","type":"Address","text":"35 Victoria Road","highlight":""},{"id":"GB|RM|A|23968944|ENG","description":"London SW14 8EX","type":"Address","text":"36 Victoria Road","highlight":""},{"id":"GB|RM|A|23968944|A1|ENG","description":"London SW14 8EX","type":"Address","text":"Bucknor E-Commotion 36 Victoria Road","highlight":""},{"id":"GB|RM|A|23968945|ENG","description":"London SW14 8EX","type":"Address","text":"37 Victoria Road","highlight":""},{"id":"GB|RM|A|23968946|ENG","description":"London SW14 8EX","type":"Address","text":"38 Victoria Road","highlight":""}]}}}}}}}},"/user/addresses/lookup/retrieve":{"post":{"operationId":"retrieveAddress","summary":"Retrieve address details","description":"\nRetrieve full structured address fields for a selected lookup result.\n\nUse this endpoint as step 2 of the assisted lookup workflow, after POST /user/addresses/lookup/find.\n\nHow to use this endpoint:\n\n1. Call POST /user/addresses/lookup/find and let the user choose a specific address result.\n2. Send that result id to this endpoint.\n3. Use the returned structured fields to prefill or confirm the address form.\n4. Save the confirmed address with POST /user/addresses.\n\nBehavior notes:\n\n- This endpoint resolves data only; it does not create or update a saved address.\n- The returned payload is intended to reduce manual entry errors and improve consistency.\n- If the supplied id is invalid or unavailable, the request fails and the client should return to lookup.\n","tags":["user-addresses"],"security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"The ID of a specific address to retrieve","example":"GB|RM|A|10321882|ENG"}},"required":["id"]},"examples":{"Retrieve address by ID":{"description":"Retrieve a specific address by ID","value":{"id":"GB|RM|A|10321882|ENG"}}}}}},"responses":{"200":{"description":"Retrieve a specific address","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the address"},"department":{"type":"string","description":"Department or internal division"},"company":{"type":"string","description":"Company name associated with the address"},"subBuilding":{"type":"string","description":"Sub-building identifier (e.g., Apartment or Suite number)"},"buildingNumber":{"type":"string","description":"Building number in the street"},"buildingName":{"type":"string","description":"Name of the building"},"secondaryStreet":{"type":"string","description":"Secondary street address, if any"},"street":{"type":"string","description":"Primary street name"},"block":{"type":"string","description":"Block name or number"},"neighbourhood":{"type":"string","description":"Neighbourhood or locality"},"district":{"type":"string","description":"District or borough"},"city":{"type":"string","description":"City or town"},"line1":{"type":"string","description":"First line of the formatted address"},"line2":{"type":"string","description":"Second line of the formatted address"},"line3":{"type":"string","description":"Third line of the formatted address"},"line4":{"type":"string","description":"Fourth line of the formatted address"},"line5":{"type":"string","description":"Fifth line of the formatted address"},"adminArea":{"type":"string","description":"Administrative area name (e.g., county or region)"},"adminAreaCode":{"type":"string","description":"Administrative area code"},"state":{"type":"string","description":"State or province name"},"stateCode":{"type":"string","description":"State or province code"},"postalCode":{"type":"string","description":"Postal or ZIP code"},"country":{"type":"string","description":"Full country name"},"countryIso2":{"type":"string","description":"ISO 3166-1 alpha-2 country code"},"countryIso3":{"type":"string","description":"ISO 3166-1 alpha-3 country code"},"countryIsoNumber":{"type":["string","null"],"description":"ISO 3166-1 numeric country code"},"sortingNumber1":{"type":"string","description":"Primary sorting number (used in mail sorting)"},"sortingNumber2":{"type":"string","description":"Secondary sorting number (used in mail sorting)"},"barcode":{"type":"string","description":"Postal barcode for mail sorting"},"poBoxNumber":{"type":"string","description":"Post Office Box number"},"label":{"type":"string","description":"Formatted label for display"},"type":{"type":"string","description":"Type of address (e.g., Residential, Business, etc.)"}}},"examples":{"Retrieve address by ID":{"description":"Retrieve a specific address by ID","value":{"id":"GB|RM|A|10321882|ENG","department":"","company":"","subBuilding":"","buildingNumber":"34","buildingName":"","secondaryStreet":"","street":"Selborne Close","block":"","neighbourhood":"","district":"","city":"Petersfield","line1":"34 Selborne Close","line2":"","line3":"","line4":"","line5":"","adminArea":"Hampshire","adminAreaCode":"","state":"Hampshire","stateCode":"","postalCode":"GU32 2JB","country":"United Kingdom","countryIso2":"GB","countryIso3":"GBR","countryIsoNumber":"826","sortingNumber1":"82163","sortingNumber2":"","barcode":"(GU322JB2GJ)","poBoxNumber":"","label":"34 Selborne Close\nPETERSFIELD\nGU32 2JB\nUNITED KINGDOM","type":"Residential"}}}}}}}}},"/user/addresses":{"post":{"operationId":"createAddress","summary":"Create address","description":"\nCreate and persist a shipping or billing address for the authenticated user.\n\nUse this endpoint when the user confirms a new address in checkout or account settings.\n\nCommon ways to call this endpoint:\n\n1. Assisted flow: find address -> retrieve details -> create saved address.\n2. Manual flow: user enters address fields directly, then create.\n\nRequest guidance:\n\n- type must be shipping or billing.\n- country should be an ISO 3166-1 alpha-2 country code (for example, GB).\n- Set loqateId and isValidated when the address came from the lookup endpoints.\n- Set isPrimary to true when this should become the default address for that type.\n\nBehavior notes:\n\n- Returns 201 with the newly saved address record.\n- A user can store up to 10 addresses in total; additional creates return 400.\n- If isPrimary is true, existing primary addresses of the same type are replaced.\n- After creation, call GET /user/addresses to refresh the full address list in UI.\n","tags":["user-addresses"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":["string","null"],"description":"A recognisable label for the address, e.g. \"Home\", \"Work\""},"type":{"type":"string","enum":["shipping","billing"],"description":"Type of address, 'shipping' or 'billing'"},"line1":{"type":"string","minLength":1,"description":"First line of the formatted address"},"line2":{"type":["string","null"],"description":"Second line of the formatted address"},"city":{"type":"string","minLength":1,"description":"City or town"},"state":{"type":"string","description":"State or province name"},"postalCode":{"type":"string","minLength":1,"description":"Postal or ZIP code"},"country":{"type":"string","minLength":2,"maxLength":2,"description":"ISO 3166-1 alpha-2 country code"},"loqateId":{"type":["string","null"],"description":"The LoqateID of the address, if applicable"},"isValidated":{"type":["boolean","null"],"default":false,"description":"Whether the address has been validated using Loqate"},"isPrimary":{"type":["boolean","null"],"default":false,"description":"Whether the address is the primary address for this type"}},"required":["type","line1","city","state","postalCode","country"]},"examples":{"Create a new address":{"description":"Create a new shipping or billing address","value":{"label":"home","type":"shipping","line1":"67 Test Close","city":"Petersfield","state":"Hampshire","postalCode":"GU322JX","country":"GB","isValidated":false,"isPrimary":true}}}}}},"responses":{"201":{"description":"Address created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Address"}}}},"400":{"description":"Bad request"}}},"get":{"operationId":"getAddresses","summary":"List addresses","description":"\nList all addresses saved for the authenticated user account.\n\nUse this endpoint to load address books, checkout selectors, and default-address settings.\n\nResponse guidance:\n\n- type distinguishes shipping and billing records.\n- isPrimary identifies the current default for each type.\n- id is required for delete operations and address selection state.\n- An empty array means the user has no saved addresses yet.\n\nCommon workflow:\n\n1. Call this endpoint on account page load and checkout start.\n2. Use POST /user/addresses to add new addresses.\n3. Use DELETE /user/addresses/{id} to remove obsolete addresses.\n4. Call this endpoint again after any create/delete to refresh canonical state.\n","tags":["user-addresses"],"security":[{"Bearer":[]}],"responses":{"200":{"description":"A list of addresses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Addresses"},"examples":{"List of addresses":{"description":"A list of addresses for the user","value":[{"label":"home","type":"shipping","line1":"67 Test Close","city":"Petersfield","state":"Hampshire","postalCode":"GU322JX","country":"GB","loqateId":"GB|RM|A|10321882|ENG","isValidated":true,"isPrimary":true,"id":"cmausk7ty0001640xpr4efrul","createdAt":"Mon May 19 2025 08:56:31 GMT+0100 (British Summer Time)","updatedAt":"Mon May 19 2025 08:56:31 GMT+0100 (British Summer Time)"}]}}}}}}}},"/user/addresses/{id}":{"delete":{"operationId":"deleteAddress","summary":"Delete address","description":"\nDelete an address belonging to the authenticated user.\n\nUse this endpoint to remove obsolete or incorrect addresses from the user address book.\n\nBehavior notes:\n\n- The address is removed by id from the authenticated user's address set.\n- Returns 204 on success with no response body.\n- Returns 404 if the address id does not exist or is not owned by the current user.\n- If the deleted address was primary, another address of the same type may become primary.\n\nRecommended follow-up:\n\n1. Call GET /user/addresses after deletion.\n2. Refresh UI state using the updated list, including primary indicators.\n","tags":["user-addresses"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"The ID of the address to delete"},"required":true,"description":"The ID of the address to delete","name":"id","in":"path"}],"responses":{"204":{"description":"Address deleted"},"404":{"description":"Address not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}}}}},"/user/account":{"get":{"operationId":"getAccount","summary":"Retrieve account","description":"\nRetrieve the current account profile for the authenticated user.\n\nUse this endpoint to load account data in settings pages and to refresh client state after any account update.\n\nThis endpoint returns the canonical server-side view of account fields such as username, email, phone number,\nprofile text, avatar, and cover image metadata where available.\n","tags":["user-account"],"security":[{"Bearer":[]}],"responses":{"200":{"description":"Account details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Account"}}}}}}},"/user/account/password":{"put":{"operationId":"updatePassword","summary":"Update password","description":"\nUpdate the password for the authenticated user.\n\nThis endpoint is intended for credential rotation and account recovery flows after successful authentication.\n\nBehavior notes:\n\n- Returns 204 when the password update succeeds.\n- Does not return a response body on success.\n- Requires a valid authenticated bearer token.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePassword"},"examples":{"Default":{"value":{"password":"p@ssw0rd"}}}}}},"responses":{"204":{"description":"Password updated"}}}},"/user/account/profile":{"put":{"operationId":"updateProfile","summary":"Update profile","description":"\nUpdate account profile fields such as name, family name, username, and public profile text.\n\nUse this endpoint for profile editing screens.\n\nBehavior notes:\n\n- Returns 204 on success with no response body.\n- Username changes may be subject to update limits and can fail with a precondition-style error.\n- The resulting profile can be re-fetched using GET /user/account.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProfile"},"examples":{"Default":{"value":{"name":"John","familyName":"Doe","username":"johndoe","profile":"Avid collector"}}}}}},"responses":{"204":{"description":"Profile updated"}}}},"/user/account/email":{"patch":{"operationId":"updateEmail","summary":"Send email update code","description":"\nBegin a two-step email change flow by requesting a verification code.\n\nThis endpoint does not update the email address by itself.\n\nFlow:\n\n1. Call this endpoint with the target email address.\n2. Read the verification code delivered to that address.\n3. Call PUT /user/account/email to verify the code and complete the change.\n\nUse this split flow when you need proof that the new email address is controlled by the user.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmail"}}}},"responses":{"204":{"description":"A verification code was sent to the email address"}}},"put":{"operationId":"verifyUpdateEmail","summary":"Verify email address","description":"\nComplete the second step of the email change flow.\n\nThis endpoint consumes the verification payload and applies the new email address to the authenticated account.\n\nExpected usage:\n\n1. First request a code via PATCH /user/account/email.\n2. Then call this endpoint with the verification data.\n\nOn success, the email address is updated and the endpoint returns 204.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEmail"}}}},"responses":{"204":{"description":"The user's email address was updated"}}}},"/user/account/phone-number":{"patch":{"operationId":"updatePhoneNumber","summary":"Send update code","description":"\nBegin a two-step phone number change flow by requesting a verification code.\n\nThis endpoint starts verification only; it does not immediately change the stored phone number.\n\nFlow:\n\n1. Call this endpoint with the target phone number.\n2. Read the verification code sent to that phone number.\n3. Call PUT /user/account/phone-number to verify and complete the update.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyPhoneNumber"}}}},"responses":{"204":{"description":"A verification code was sent to the phone number"}}},"put":{"operationId":"verifyUpdatePhoneNumber","summary":"Verify phone number","description":"\nComplete the second step of the phone number change flow.\n\nCall this endpoint after the verification code has been requested and received.\n\nExpected usage:\n\n1. Request code via PATCH /user/account/phone-number.\n2. Submit verification payload to this endpoint.\n\nOn success, the phone number is updated and the endpoint returns 204.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePhoneNumber"}}}},"responses":{"204":{"description":"The user's phone number was updated"}}},"delete":{"operationId":"deletePhoneNumber","summary":"Delete phone number","description":"\nRemove the phone number associated with the authenticated user account.\n\nUse this endpoint when a user no longer wants a phone number linked to their profile.\n\nBehavior notes:\n\n- Returns 204 when removal succeeds.\n- The phone number field is cleared from the account profile.\n- Updated account data can be validated with GET /user/account.\n","tags":["user-account"],"security":[{"Bearer":[]}],"responses":{"204":{"description":"The user's phone number was deleted"}}}},"/user/account/avatar":{"post":{"operationId":"createAvatarUpload","summary":"Create avatar upload","description":"\nStart the avatar image upload workflow by requesting an upload target.\n\nThis endpoint is step 1 of a multi-step process and does not update the account avatar on its own.\n\nAvatar upload workflow:\n\n1. Call this endpoint to receive an upload payload, including image identifier and upload URL.\n2. Upload the binary image directly to the returned URL.\n3. Call PATCH /user/account/avatar with the returned image identifier to finalize.\n\nThe avatar is only applied after successful finalization.\n","tags":["user-account"],"security":[{"Bearer":[]}],"responses":{"200":{"description":"Upload URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload"}}}}}},"patch":{"operationId":"finalizeAvatarUpload","summary":"Finalize avatar upload","description":"\nFinalize a previously uploaded avatar image and apply it to the authenticated user account.\n\nThis endpoint is step 3 of the avatar workflow and must be called after uploading the image binary.\n\nFinalization behavior:\n\n- Validates the provided image identifier.\n- Confirms upload completion.\n- Performs content checks before applying the image.\n- Rejects disallowed content without updating the avatar.\n\nTypical sequence:\n\n1. POST /user/account/avatar\n2. Upload image to returned URL.\n3. PATCH /user/account/avatar, which is this endpoint.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload Complete"}}}},"responses":{"204":{"description":"Avatar updated"},"451":{"description":"Image rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageClassificationFailure"}}}}}}},"/user/account/cover":{"post":{"operationId":"createCoverUpload","summary":"Create cover upload","description":"\nStart the cover image upload workflow by requesting an upload target.\n\nThis endpoint only prepares upload and does not apply the cover image.\n\nCover upload workflow:\n\n1. Call this endpoint to receive upload data.\n2. Upload the image file directly to the returned URL.\n3. Call PATCH /user/account/cover to finalize and apply the uploaded image.\n\nThe account cover image changes only after the finalize step succeeds.\n","tags":["user-account"],"security":[{"Bearer":[]}],"responses":{"200":{"description":"Upload URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload"}}}}}},"patch":{"operationId":"finalizeCoverUpload","summary":"Finalize cover upload","description":"\nFinalize a previously uploaded cover image and apply it to the authenticated user account.\n\nThis endpoint completes the cover upload process after the binary upload has finished.\n\nFinalization behavior:\n\n- Validates that the uploaded image identifier is valid for the current user.\n- Confirms upload completion.\n- Performs content checks before applying the image.\n- Returns a rejection response if the uploaded content is not allowed.\n\nTypical sequence:\n\n1. POST /user/account/cover\n2. Upload image to returned URL.\n3. PATCH /user/account/cover, which is this endpoint.\n","tags":["user-account"],"security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload Complete"}}}},"responses":{"204":{"description":"Cover updated"},"451":{"description":"Image rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageClassificationFailure"}}}}}}},"/user/purchases":{"get":{"operationId":"listPurchases","summary":"List purchases","description":"\nList purchases for the authenticated buyer.\n\nUse this endpoint for purchase history overview pages.\n\nQuery behavior:\n- Supports pagination and sorting by creation/update timestamps.\n- Page size is capped at 50.\n- Useful for infinite-scroll and paged table UIs.\n\nResponse behavior:\n- Returns purchase summaries, not full order-level detail.\n- Includes derived seller-count information for each purchase.\n- Use the purchase `id` from this list with the purchase detail endpoint for deep inspection.\n","tags":["user-purchases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number, defaults to 1"},"required":false,"description":"Page number, defaults to 1","name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Results per page, defaults to 20"},"required":false,"description":"Results per page, defaults to 20","name":"size","in":"query"},{"schema":{"type":"string","enum":["createdAt","updatedAt"],"default":"createdAt","description":"Field to sort by"},"required":false,"description":"Field to sort by","name":"sort","in":"query"},{"schema":{"$ref":"#/components/schemas/SortDirection"},"required":false,"description":"Sort direction","name":"direction","in":"query"}],"responses":{"200":{"description":"User purchases","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseSummaryList"}}}}}}},"/user/purchases/{id}":{"get":{"operationId":"getPurchase","summary":"Get purchase","description":"\nGet full detail for one buyer purchase.\n\nUse this endpoint for order-tracking pages and deep purchase detail views.\n\nWhat is included:\n- Orders, items, shipments, adjustments, refunds, and linked cases.\n- Seller user summaries.\n- Item metadata resolved from catalog search infrastructure.\n\nRules:\n- Purchase must belong to the authenticated user.\n- Returns `404` when purchase is missing or not owned.\n","tags":["user-purchases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Purchase ID"},"required":true,"description":"Purchase ID","name":"id","in":"path"}],"responses":{"200":{"description":"Purchase","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the purchase"},"customerEmailAddress":{"type":"string","format":"email","description":"Email address used for the purchase"},"deliveryCharge":{"type":"integer","description":"Delivery charge in pence"},"deliveryAddress":{"$ref":"#/components/schemas/DeliveryAddress"},"subtotal":{"type":"integer","description":"Subtotal in pence"},"total":{"type":"integer","description":"Total in pence"},"serviceFee":{"type":"integer","description":"Service fee in pence"},"status":{"$ref":"#/components/schemas/PurchaseStatus"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the purchase was created"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp when the purchase was last updated"},"invoiceId":{"type":["string","null"],"description":"Invoice identifier generated for the purchase"},"user":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that purchased the items"}]},"orders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2","description":"Unique identifier for the order"},"sellerId":{"type":"string","description":"Seller user ID"},"purchaseId":{"type":"string","description":"Purchase ID"},"deliveryCharge":{"type":"integer","description":"Delivery charge in pence"},"subtotal":{"type":"integer","description":"Subtotal in pence"},"total":{"type":"integer","description":"Total in pence"},"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order was created"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order was last updated"},"items":{"type":"array","items":{"allOf":[{"$ref":"#/components/schemas/OrderItem"},{"type":"object","properties":{"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order item was created"},"updatedAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the order item was updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","minimum":0}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","minimum":0}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}]},"shipmentId":{"type":"string","description":"Identifier of the shipment associated with this item"}},"required":["item"]}],"title":"Order Item","description":"Item included in an order"},"description":"Items included in the order with item details"},"shipments":{"type":"array","items":{"$ref":"#/components/schemas/Shipment"},"description":"Shipments for the order"},"adjustments":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","description":"Adjustment amount in pence, positive or negative"},"comment":{"type":"string","description":"Reason for the adjustment"},"createdAt":{"type":["string","null"],"format":"date-time","description":"Timestamp when the adjustment was created"}},"required":["amount","comment","createdAt"]},"default":[],"description":"Order-level adjustments (e.g., delivery refunds)"},"reviews":{"type":"object","additionalProperties":{"type":"integer"},"default":{},"description":"Reviews for the order keyed by the reviewer's user ID with their rating"},"user":{"$ref":"#/components/schemas/UserSummary"}},"required":["id","sellerId","purchaseId","deliveryCharge","subtotal","total","createdAt","updatedAt","items","shipments","user"]},"description":"Orders included in the purchase"},"cases":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"workflowId":{"type":"string"},"purchaseId":{"type":"string"},"reason":{"type":"string","enum":["SNAD","DAMAGED","WRONG_ITEM","NOT_RECEIVED","OTHER","CHARGEBACK"]},"comment":{"type":["string","null"]},"status":{"type":"string","enum":["OPEN","REMEDIATION","SETTLED","CLOSED","ESCALATED"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"outcomes":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"status":{"type":"string","enum":["PENDING","ACCEPTED","REJECTED","RESOLVED"]},"caseId":{"type":"string","format":"cuid2"},"amount":{"type":"integer","minimum":0},"comment":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"deliveryAddress":{}},"required":["id","type","party","status","caseId","amount","createdAt","updatedAt"]}},"attachments":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}}},"required":["id","workflowId","purchaseId","reason","status","createdAt","updatedAt","outcomes","attachments"]},"description":"Cases associated with the purchase"},"refunds":{"type":"array","items":{"type":"object","properties":{"amount":{"type":"integer","description":"Amount refunded in pence"},"status":{"type":"string","enum":["CREATED","SUCCEEDED","FAILED"],"description":"Refund processing status"},"initiator":{"type":"string","enum":["BUYER","SELLER","SYSTEM","EXTERNAL"],"description":"Who initiated the refund"},"comment":{"type":["string","null"],"description":"Reason/comment associated with the refund"},"orderId":{"type":["string","null"],"description":"Related order ID if applicable"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp when the refund was created"}},"required":["amount","status","initiator","createdAt"]},"default":[],"description":"Refunds against this purchase (Stripe IDs omitted)"}},"required":["id","customerEmailAddress","deliveryCharge","deliveryAddress","subtotal","total","serviceFee","createdAt","updatedAt","orders","cases"]}}}},"404":{"description":"Purchase not found"}}}},"/user/purchases/{id}/history":{"get":{"operationId":"getPurchaseHistory","summary":"Get purchase history","description":"\nRetrieve audit-style history entries for one purchase.\n\nUse this endpoint to render chronological activity feeds for a purchase.\n\nBehavior:\n- Verifies purchase ownership first.\n- Returns entries newest-first.\n- Includes related order/order-item references and user metadata where available.\n- Captures cross-party actions so buyers can understand exactly what changed and when.\n\nResponses:\n- Returns `404` for missing or non-owned purchases.\n- Returns a normalized timeline payload suitable for rendering directly in activity feeds.\n","tags":["user-purchases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Purchase ID"},"required":true,"description":"Purchase ID","name":"id","in":"path"}],"responses":{"200":{"description":"Purchase history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseHistoryResponse"}}}},"404":{"description":"Purchase not found"}}}},"/user/purchases/{id}/{orderId}":{"post":{"operationId":"updatePurchaseOrder","summary":"Update purchase order","description":"\nApply a buyer-side update to a specific order inside a purchase.\n\nUse this endpoint for post-purchase item actions such as delivery confirmation or opening a dispute.\n\nRules:\n- Purchase must belong to the authenticated user.\n- Target `orderId` must exist within that purchase.\n- Cancellation is intentionally excluded from this endpoint and handled by the dedicated cancel route.\n\nResponses:\n- Returns `204` on success.\n- Returns `404` for missing purchase or order.\n","tags":["user-purchases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Purchase ID"},"required":true,"description":"Purchase ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"orderId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerOrderUpdateRequestWithoutCancel"},"examples":{"Delivered":{"summary":"Order has been delivered","description":"Mark items within a shipment(s) as delivered","value":{"action":"delivered","items":[{"id":"order-item-id-1"},{"id":"order-item-id-2"}]}},"Dispute":{"summary":"Open a dispute","description":"Open a dispute for one or more items in an order.","value":{"action":"dispute","items":[{"id":"order-item-id-1","quantity":1}],"case":{"reason":"OTHER","comment":"Item was not as described","outcomes":[{"type":"REFUND","amount":100}]}}}}}}},"responses":{"204":{"description":"Order updated"},"404":{"description":"Purchase or order not found"}}}},"/user/purchases/{id}/cancel":{"post":{"operationId":"cancelPurchase","summary":"Cancel purchase","description":"\nCancel an entire purchase from the buyer side.\n\nUse this endpoint when a user requests cancellation before fulfillment state makes cancellation invalid.\n\nRules:\n- Purchase must belong to the authenticated user.\n- Cancellation may fail when items are already shipped or otherwise non-cancellable.\n\nResponses:\n- Returns `204` when cancellation succeeds.\n- Returns `400` when cancellation is not allowed by current order/item state.\n- Returns `404` when purchase is missing or not owned.\n","tags":["user-purchases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Purchase ID"},"required":true,"description":"Purchase ID","name":"id","in":"path"}],"responses":{"204":{"description":"Purchase cancelled"},"400":{"description":"Purchase cannot be cancelled because no orders or items are available, or some items have already shipped."},"404":{"description":"Purchase not found"}}}},"/user/reviews":{"get":{"operationId":"listUserReviews","summary":"List reviews","description":"\nList reviews authored by the authenticated user.\n\nUse this endpoint for “my reviews” pages and moderation/self-audit screens.\n\nQuery behavior:\n- Supports pagination and timestamp sorting.\n- Works well for account settings pages and creator reputation management views.\n\nResponse behavior:\n- Returns authored review records with source references.\n- Expands each reviewed user into summary data (rating, score, sales/purchases, review counts).\n- Lets clients render review cards without additional user lookup calls.\n","tags":["user-reviews"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number, defaults to 1"},"required":false,"description":"Page number, defaults to 1","name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Results per page, defaults to 20"},"required":false,"description":"Results per page, defaults to 20","name":"size","in":"query"},{"schema":{"type":"string","enum":["createdAt"],"default":"createdAt","description":"Field to sort by"},"required":false,"description":"Field to sort by","name":"sort","in":"query"},{"schema":{"$ref":"#/components/schemas/ReviewSortDirection"},"required":false,"description":"Sort direction","name":"direction","in":"query"}],"responses":{"200":{"description":"List of reviews","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthoredReviews"}}}}}},"post":{"operationId":"createUserReview","summary":"Create review","description":"\nCreate a new review authored by the authenticated user.\n\nUse this endpoint after a qualifying interaction (for example an order flow) when collecting user feedback.\n\nValidation and moderation:\n- Review must pass source/actor validation checks.\n- Review text is sanitized before persistence.\n- Empty content after sanitization is treated as no comment.\n\nResponses:\n- Returns `201` with the created authored review.\n- Returns `403` when the review is not valid for the source/user combination.\n","tags":["user-reviews"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewInput"}}}},"responses":{"201":{"description":"Review created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthoredReview"}}}},"403":{"description":"Invalid review"}}}},"/user/reviews/{id}":{"get":{"operationId":"getUserReview","summary":"Get review","description":"\nGet one review authored by the authenticated user.\n\nUse this endpoint for review detail screens and edit prefill flows.\n\nOwnership rules:\n- Review must exist and be authored by the caller.\n- Non-owned reviews are treated as not found.\n\nResponse behavior:\n- Returns authored review data plus reviewed-user summary metadata.\n","tags":["user-reviews"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Review ID"},"required":true,"description":"Review ID","name":"id","in":"path"}],"responses":{"200":{"description":"Review","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthoredReview"}}}},"404":{"description":"Review not found"}}},"put":{"operationId":"updateUserReview","summary":"Update review","description":"\nRevise an existing authored review.\n\nUse this endpoint when a user edits rating/comment after posting.\n\nRules:\n- Caller must be the original author.\n- Reviews are single-revision only; additional revisions return `409`.\n- Updated content is sanitized before persistence.\n\nSide effects:\n- Recalculates and persists reviewed-user rating aggregates when rating changes.\n","tags":["user-reviews"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Review ID"},"required":true,"description":"Review ID","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewUpdateInput"}}}},"responses":{"200":{"description":"Review","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthoredReview"}}}},"404":{"description":"Review not found"},"409":{"description":"Review already revised"}}},"delete":{"operationId":"deleteUserReview","summary":"Delete review","description":"\nDelete one authored review.\n\nUse this endpoint when a user needs to remove previously submitted feedback.\n\nRules:\n- Caller must be the original review author.\n- Returns `404` when review does not exist or is not owned by the caller.\n\nResponse:\n- Returns `204` with no body on successful deletion.\n- Downstream rating recalculation is handled by server-side deletion logic.\n","tags":["user-reviews"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Review ID"},"required":true,"description":"Review ID","name":"id","in":"path"}],"responses":{"204":{"description":"Review deleted"},"404":{"description":"Review not found"}}}},"/user/portal":{"get":{"operationId":"getCustomerPortal","summary":"Get customer portal link","description":"\nCreate a Stripe customer portal session link for the authenticated user.\n\nUse this endpoint to send users into self-serve billing management.\n\nBehavior:\n- Reuses existing Stripe customer link when present.\n- If missing, creates a Stripe customer record using account/profile + address data.\n- Returns a fresh customer portal URL for immediate redirect.\n\nFailure mode:\n- Returns `404` if the upstream user account cannot be resolved.\n","tags":["user-portal"],"security":[{"Bearer":[]}],"responses":{"200":{"description":"Stripe customer portal URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalLink"}}}}}}},"/user/invoices":{"get":{"operationId":"listUserInvoices","summary":"List invoices","description":"\nList Stripe invoices for the authenticated customer.\n\nUse this endpoint for billing history pages and invoice tables.\n\nPagination:\n- `limit` controls page size (1-100).\n- `startingAfter` continues from a previous page token.\n- Response includes `hasMore` and `nextStartingAfter` for pagination UX.\n\nBehavior:\n- If the user has no Stripe customer link yet, returns an empty list rather than an error.\n","tags":["user-invoices"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":10,"description":"Maximum number of invoices to return."},"required":false,"description":"Maximum number of invoices to return.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Stripe invoice ID to start after. Use the value from `nextStartingAfter` of the previous response."},"required":false,"description":"Stripe invoice ID to start after. Use the value from `nextStartingAfter` of the previous response.","name":"startingAfter","in":"query"}],"responses":{"200":{"description":"Paginated Stripe invoices for the authenticated user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceListResponse"}}}}}}},"/user/invoices/{invoiceId}":{"get":{"operationId":"getInvoiceDownloadUrl","summary":"Get invoice download URL","description":"\nGet a PDF download URL for one invoice.\n\nUse this endpoint when a user clicks “download invoice” in billing UI.\n\nSecurity behavior:\n- Verifies the invoice exists.\n- Verifies the invoice belongs to the authenticated user’s Stripe customer account.\n- Returns `404` for unknown invoices or ownership mismatch.\n\nResponse:\n- Returns a direct PDF URL when available.\n- Returns `404` if the invoice has no PDF yet.\n","tags":["user-invoices"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Stripe invoice identifier returned by the list endpoint."},"required":true,"description":"Stripe invoice identifier returned by the list endpoint.","name":"invoiceId","in":"path"}],"responses":{"200":{"description":"Download URL for the requested invoice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceDownloadResponse"}}}},"404":{"description":"Invoice not found"}}}},"/user/cases":{"get":{"operationId":"listUserCases","summary":"List cases","description":"\nList support/dispute cases for the authenticated buyer.\n\nUse this endpoint for account case inboxes and resolution tracking views.\n\nQuery behavior:\n- Supports pagination and sorting by creation/update timestamps.\n\nResponse behavior:\n- Returns only cases belonging to purchases made by the authenticated user.\n- Includes outcomes and attachments.\n- Redacts seller delivery address data on seller outcomes until those outcomes are accepted.\n","tags":["user-cases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number, defaults to 1"},"required":false,"description":"Page number, defaults to 1","name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Results per page, defaults to 20"},"required":false,"description":"Results per page, defaults to 20","name":"size","in":"query"},{"schema":{"type":"string","enum":["createdAt","updatedAt"],"default":"createdAt","description":"Field to sort by"},"required":false,"description":"Field to sort by","name":"sort","in":"query"},{"schema":{"$ref":"#/components/schemas/UserCaseSortDirection"},"required":false,"description":"Sort direction","name":"direction","in":"query"}],"responses":{"200":{"description":"User cases","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCases"}}}}}}},"/user/cases/{id}":{"get":{"operationId":"getUserCase","summary":"Get case","description":"\nGet one buyer-owned case by ID.\n\nUse this endpoint for case detail screens and buyer follow-up workflows.\n\nRules:\n- Case must belong to a purchase owned by the authenticated user.\n- Returns `404` when not found or not owned.\n\nResponse behavior:\n- Returns full case state with outcomes and attachments.\n- Seller delivery address data is hidden for non-accepted seller outcomes.\n","tags":["user-cases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"responses":{"200":{"description":"Case details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCase"}}}},"404":{"description":"Case not found"}}},"put":{"operationId":"updateUserCase","summary":"Update case","description":"\nApply a buyer action to an existing case.\n\nUse this endpoint for buyer-side case progression (for example accepting, rejecting, or escalating outcomes).\n\nRules:\n- Case must belong to the authenticated user.\n- Returns `409` when an accepted outcome can no longer be modified.\n\nSide effects:\n- Escalation actions trigger case update notifications.\n- Returns the refreshed case record with outcomes and attachments.\n","tags":["user-cases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"type":"string","enum":["escalate"]}},"required":["action"]},{"type":"object","properties":{"action":{"type":"string","enum":["outcome"]},"outcome":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["RETURN"]},"comment":{"type":"string","minLength":1},"amount":{"type":"integer","minimum":0}},"required":["type","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REFUND"]},"comment":{"type":"string","minLength":1},"amount":{"type":"integer","minimum":0}},"required":["type","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REPLACEMENT"]},"comment":{"type":"string","minLength":1}},"required":["type"]}]}},"required":["action","outcome"]},{"type":"object","properties":{"action":{"type":"string","enum":["accept"]},"outcome":{"type":"object","properties":{"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"id":{"type":"string","format":"cuid2"}},"required":["type","id"]}},"required":["action","outcome"]},{"type":"object","properties":{"action":{"type":"string","enum":["reject"]},"outcome":{"type":"object","properties":{"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"id":{"type":"string","format":"cuid2"}},"required":["type","id"]}},"required":["action","outcome"]}]}}}},"responses":{"200":{"description":"Updated case","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatedUserCase"}}}},"404":{"description":"Case not found"},"409":{"description":"Outcome already accepted"}}}},"/user/cases/{id}/attachments":{"post":{"operationId":"createUserCaseAttachment","summary":"Create attachment","description":"\nCreate a draft upload URL for a buyer case attachment.\n\nThis is step 1 of the buyer case attachment workflow.\n\nWorkflow:\n1. Request upload credentials for the case.\n2. Upload the image directly.\n3. Finalize in a follow-up call.\n\nRules:\n- Case must belong to a purchase owned by the authenticated user.\n- Returns `404` when case ownership validation fails.\n","tags":["user-cases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"responses":{"200":{"description":"Upload URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload"}}}},"404":{"description":"Case not found"}}},"patch":{"operationId":"finalizeUserCaseAttachment","summary":"Finalize attachment","description":"\nFinalize an uploaded buyer case attachment.\n\nThis is step 2 of the buyer case attachment workflow.\n\nValidation:\n- `imageId` must match the expected case attachment URN.\n- Upload must be completed (draft uploads are rejected).\n- Case must belong to the authenticated user.\n\nResponses:\n- `400` for invalid IDs or incomplete uploads.\n- `404` for missing/non-owned cases.\n- Returns attachment metadata with a display-ready URL.\n","tags":["user-cases"],"security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload Complete"}}}},"responses":{"200":{"description":"Attachment saved","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}}}},"400":{"description":"Invalid image ID"},"404":{"description":"Case not found"}}}},"/user/stats":{"get":{"operationId":"getUserStats","summary":"Retrieve stats","description":"\nRetrieves the following statistics for the authenticated user:\n\n- Total & Ongoing Purchases\n- Open Cases\n- Unread Messages\n\n:::info\nThis endpoint is cached for ~1 hour and may not reflect real-time data. When the underlying data changes, \nwe do our best to invalidate the cache quickly.\n:::\n","tags":["user-stats"],"security":[{"Bearer":[]}],"responses":{"200":{"description":"User stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStats"},"examples":{"Example statistics":{"description":"An example response showing typical user statistics.","value":{"purchases":{"total":42,"incomplete":3},"cases":{"open":1},"messages":{"unread":2}}}}}}}}}},"/user/personal-access-tokens":{"get":{"operationId":"listPersonalAccessTokens","summary":"List PATs","description":"\nReturn all personal access tokens that belong to the authenticated user.\n\nUse this endpoint to audit and manage active API credentials for your account.\n\nEach item includes:\n\n- `name` - Human-readable identifier for the token.\n- `createdAt` - When the token was issued.\n- `expires` - Optional expiry timestamp (if configured).\n\nTypical usage pattern:\n\n1. Call this endpoint to review existing tokens.\n2. Delete tokens that are no longer needed.\n3. Keep only the minimum number of active tokens required for your integrations.\n\nThis endpoint is for token management only. To authenticate API requests with a personal access token,\nsend it in the `Authorization` header as `Bearer <token>`.\n","tags":["user-personal-access-tokens"],"security":[{"Bearer":[]}],"responses":{"200":{"description":"Personal access tokens for the user","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalAccessTokens"}}}}}},"post":{"operationId":"createPersonalAccessToken","summary":"Create a PAT","description":"\nCreate a new personal access token for the authenticated user.\n\nUse personal access tokens for server-to-server or CLI integrations where interactive user login is not practical.\n\nImportant behavior:\n\n- A user can have up to 5 personal access tokens.\n- Token names must be unique per user.\n- `expires` is optional, but if provided it must be at least 24 hours in the future.\n- Treat the token value as a secret and store it securely.\n\nHow to use the token with API requests:\n\n```http\nAuthorization: ApiKey <personal-access-token>\n```\n\nExample request flow:\n\n1. Create token via this endpoint.\n2. Save the token value in your secret store.\n3. Send it as an API key on subsequent API calls.\n4. Rotate and revoke tokens regularly as part of your security process.\n","tags":["user-personal-access-tokens"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePersonalAccessToken"}}}},"responses":{"201":{"description":"Personal access token created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalAccessToken"}}}},"409":{"description":"Personal access token limit reached or duplicate name"}}},"delete":{"operationId":"deletePersonalAccessToken","summary":"Delete PAT","description":"\nDelete an existing personal access token for the authenticated user.\n\nUse this endpoint to revoke credentials that are no longer trusted or needed.\n\nCommon scenarios:\n\n- A token was exposed or shared accidentally.\n- An integration was decommissioned.\n- You are rotating credentials on a schedule.\n\nDeletion is name-based and should be treated as an immediate revocation step.\nAfter deletion, requests authenticated with that token should no longer be authorized.\n\nRecommended rotation workflow:\n\n1. Create a replacement token.\n2. Update your integration to use the new token.\n3. Delete the old token with this endpoint.\n","tags":["user-personal-access-tokens"],"security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletePersonalAccessToken"}}}},"responses":{"204":{"description":"Personal access token deleted"},"404":{"description":"Personal access token not found"}}}},"/seller/listings":{"post":{"tags":["seller-listings"],"operationId":"createListing","summary":"Create listing","description":"\nCreate a new listing for the authenticated seller.\n\nUse this endpoint for single listing creation when you already know the target item URN and listing attributes.\n\nAuthentication and ownership:\n- The caller must authenticate as a seller account.\n- The seller must be active; inactive or missing seller records are rejected.\n\nInput validation:\n- `urn` must resolve to an existing catalog item.\n- `gradingProvider`, `gradingScore`, and `gradingNumber` must be supplied together or omitted together.\n- `notes` is optional, normalized by the API, and limited to 255 characters.\n- `reference` is optional seller/integration metadata, normalized by the API, and limited to 255 characters.\n- Empty-string `reference` values are treated as a clear request (`null` in storage).\n\nListing validity rules:\n- Listings priced at `>= 2000` (lowest-denomination integer) require an attachment photo.\n- Listings that include grading metadata also require an attachment photo.\n- When a photo is required, the listing is created with `valid: false` and becomes valid after a qualifying attachment is finalized.\n\nSide effects:\n- Emits `LISTING_CREATED` to seller webhooks.\n- Invalidates seller stats cache tags.\n- Records listing analytics events for internal reporting.\n\nReturns the complete listing resource with seller, item, attachment metadata, and the normalized `reference` value.\n","security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Listing Input"}}}},"responses":{"201":{"description":"Listing created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"},"valid":{"type":"boolean","description":"True when the listing meets all requirements"},"hidden":{"type":"boolean","description":"True when the listing is hidden from buyers"},"notes":{"type":["string","null"],"maxLength":255,"description":"Private notes for the seller such as SKUs or storage locations"},"reference":{"type":["string","null"],"maxLength":255,"description":"Third-party integration reference for this listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked","valid","hidden"]}}}},"400":{"description":"Seller not onboarded"}}}},"/seller/listings/bulk":{"post":{"tags":["seller-listings"],"operationId":"bulkCreateListings","summary":"Bulk create listings","description":"\nCreate many listings in one request with per-record success tracking.\n\nUse this endpoint for high-volume listing ingestion from seller tools or migration flows.\n\nRequest limits and validation:\n- Accepts up to `200` listing payloads per call.\n- Each listing uses the same schema and validation rules as single listing creation.\n- Optional `reference` metadata is accepted per listing and normalized the same way as single-create.\n- Duplicate URNs in the request are allowed but each array entry is still processed independently.\n\nProcessing model:\n- Listings are processed one by one; one failure does not stop other records.\n- Missing items, validation failures, or persistence errors are captured per listing.\n- Empty-string `reference` values are treated as a clear request (`null` in storage).\n- The response always returns two URN arrays: `successful` and `failed`.\n\nSeller and listing rules:\n- Caller must be an active seller.\n- Item URNs must exist in the catalog index to create a listing.\n- Listing validity follows the same photo requirement logic as single-create:\n  - price `>= 2000` or grading metadata requires at least one attachment to become valid.\n\nSide effects:\n- Emits `LISTING_CREATED` webhook events for each successfully created listing.\n- Invalidates seller stats cache tags as successful records are written.\n- Writes per-listing analytics events.\n","security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkListingRequest"}}}},"responses":{"200":{"description":"Result of processing each listing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkListingResponse"}}}},"400":{"description":"Seller not onboarded"}}}},"/seller/listings/suggest":{"post":{"tags":["seller-listings"],"operationId":"suggestSellerListingPrices","summary":"Suggest listing prices","description":"\nRetrieve stored price suggestions for one or more item URNs.\n\nUse this endpoint to prefill listing prices in seller tooling before creating listings.\n\nRequest limits:\n- Minimum of `1` URN.\n- Maximum of `50` URNs per request.\n- Duplicate URNs are deduplicated before lookup.\n\nResponse behavior:\n- Suggestions are returned only for URNs that exist in the price suggestion store.\n- Missing URNs are silently omitted from the `suggestions` array.\n- Prices are integer values in the lowest denomination (for example, pennies), not floating point values.\n\nAuthentication and availability:\n- Caller must be an active seller.\n- The backing price suggestion store must be configured in the runtime environment.\n\nData quality handling:\n- Stored suggestion payloads are runtime-validated.\n- Invalid stored records are ignored and reported internally; valid records continue to be returned.\n","security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerListingSuggestionRequest"}}}},"responses":{"200":{"description":"Price suggestions stored for the provided URNs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerListingSuggestionResponse"}}}},"401":{"description":"Seller not active"},"404":{"description":"Seller not found"}}}},"/seller/listings/search":{"post":{"tags":["seller-listings"],"operationId":"searchSellerListingsSelf","summary":"Search your listings","description":"\nSearch the authenticated seller's listings using full-text query and facets.\n\nThis endpoint is optimized for seller backoffice listing management views.\n\nSearch behavior:\n- Executes against the listings search index with seller-scoped filtering.\n- The API enforces seller ownership by injecting the authenticated seller facet server-side.\n- Additional user-provided facets are merged with seller scoping.\n\nResponse enrichment:\n- Returns indexed listing hits plus seller-specific metadata from the primary database.\n- Adds:\n  - `valid` and `hidden` flags from listing records.\n  - `locked` status when active listing holds exist.\n  - `attachments` array with public URLs.\n\nAuthentication:\n- Caller must map to an existing seller account.\n\nUse this endpoint when you need filterable, paginated, relevance-aware listing search for the current seller.\n","security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuery"}}}},"responses":{"200":{"description":"Seller listings","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Listing Search Result"},{"type":"object","properties":{"hits":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"},"valid":{"type":"boolean","description":"True when the listing meets all requirements"},"hidden":{"type":"boolean","description":"True when the listing is hidden from buyers"},"notes":{"type":["string","null"],"maxLength":255,"description":"Private notes for the seller such as SKUs or storage locations"},"reference":{"type":["string","null"],"maxLength":255,"description":"Third-party integration reference for this listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked","valid","hidden"]}}}}],"description":"Result of a listings search query"}}}},"404":{"description":"Seller not found"}}}},"/seller/listings/items":{"get":{"tags":["seller-listings"],"operationId":"listSellerListingsByItem","summary":"List listings by item","description":"\nList the authenticated seller's active listings for a specific item URN.\n\nThis endpoint is useful for item-centric listing management screens where a seller wants all of their offers for one product.\n\nQuery and ownership rules:\n- Requires `urn` query parameter.\n- Returns only listings owned by the authenticated seller.\n- Returns only listings with `quantity > 0` (active listings).\n\nData sources:\n- Listing rows are loaded from the primary database.\n- Item metadata is enriched from the catalog search index.\n- Listing lock state is derived from listing hold records.\n- Attachment URLs are attached to each listing in the response.\n\nResponse notes:\n- If no active listings exist for the provided URN, the API returns an empty array.\n- The `available` quantity in this response mirrors listing quantity.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"URN of the item to retrieve listings for"},"required":true,"description":"URN of the item to retrieve listings for","name":"urn","in":"query"}],"responses":{"200":{"description":"Listings for item","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingListResponse"}}}}}}},"/seller/listings/{id}":{"get":{"tags":["seller-listings"],"operationId":"getListing","summary":"Get listing","description":"\nRetrieve one active listing owned by the authenticated seller.\n\nUse this endpoint for listing detail pages and edit forms.\n\nLookup rules:\n- Requires listing `id` path parameter.\n- Returns only seller-owned listings with `quantity > 0`.\n- Returns `404` if the listing does not exist or does not belong to the caller.\n\nResponse enrichment:\n- Joins item metadata from the catalog index.\n- Includes seller summary and attachment URLs.\n- Computes hold-aware availability:\n  - `available = quantity - heldQuantity`.\n  - `locked = true` when one or more units are currently held.\n\nFailure behavior:\n- Returns `400` if the listing exists but its associated item can no longer be resolved.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Listing ID"},"required":true,"description":"Listing ID","name":"id","in":"path"}],"responses":{"200":{"description":"Listing","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"},"valid":{"type":"boolean","description":"True when the listing meets all requirements"},"hidden":{"type":"boolean","description":"True when the listing is hidden from buyers"},"notes":{"type":["string","null"],"maxLength":255,"description":"Private notes for the seller such as SKUs or storage locations"},"reference":{"type":["string","null"],"maxLength":255,"description":"Third-party integration reference for this listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked","valid","hidden"]}}}},"404":{"description":"Listing not found"}}},"put":{"tags":["seller-listings"],"operationId":"updateListing","summary":"Update listing","description":"\nUpdate fields on an existing seller-owned listing.\n\nUse this endpoint for partial updates such as price changes, quantity adjustments, visibility toggles, notes, reference metadata, and grading details.\n\nAuthorization and state rules:\n- Caller must be an active seller.\n- Listing must belong to the authenticated seller.\n- Listing updates are blocked while active holds exist; locked listings return `423`.\n\nValidation:\n- Request body is partial, but grading metadata must remain complete:\n  - `gradingProvider`, `gradingScore`, and `gradingNumber` must be provided together.\n- `notes` is optional, normalized by the API, and limited to 255 characters.\n- `reference` is optional integration metadata, normalized by the API, and limited to 255 characters.\n- Setting `reference: null` clears any previously stored value.\n\nValidity recalculation:\n- The API recalculates `valid` during update.\n- Listings priced at `>= 2000` or containing grading metadata require at least one attachment.\n- If photo requirements are not met, `valid` is set to `false`.\n\nSide effects:\n- Emits `LISTING_UPDATED` webhook events after a successful update.\n- Returns the refreshed listing with item, seller, attachment metadata, and the normalized `reference` value.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Listing ID"},"required":true,"description":"Listing ID","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Listing Update"}}}},"responses":{"200":{"description":"Listing","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"},"valid":{"type":"boolean","description":"True when the listing meets all requirements"},"hidden":{"type":"boolean","description":"True when the listing is hidden from buyers"},"notes":{"type":["string","null"],"maxLength":255,"description":"Private notes for the seller such as SKUs or storage locations"},"reference":{"type":["string","null"],"maxLength":255,"description":"Third-party integration reference for this listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked","valid","hidden"]}}}},"404":{"description":"Listing not found"}}},"delete":{"tags":["seller-listings"],"operationId":"deleteListing","summary":"Delete listing","description":"\nDelete a seller-owned listing by deactivating it.\n\nDeletion in this API is soft-delete behavior for marketplace safety:\n- The listing is not physically removed immediately.\n- The API sets listing `quantity` to `0`, which removes it from active selling flow and indexing pipelines.\n\nRules and constraints:\n- Listing must belong to the authenticated seller.\n- Listing must currently be active (`quantity > 0`).\n- Deletion is blocked when active holds exist and returns `423`.\n\nResponse:\n- Returns `204 No Content` when the listing is successfully scheduled for deletion.\n- Returns `404` when the listing cannot be found for the authenticated seller.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Listing ID"},"required":true,"description":"Listing ID","name":"id","in":"path"}],"responses":{"204":{"description":"Listing deleted"},"404":{"description":"Listing not found"}}}},"/seller/listings/{id}/attachments":{"post":{"tags":["seller-listings"],"operationId":"createListingAttachment","summary":"Create attachment","description":"\nCreate a draft attachment upload for a listing and return a direct upload URL.\n\nThis is step 1 of the listing attachment workflow.\n\nWorkflow:\n1. Call this endpoint to obtain `id` and `uploadURL`.\n2. Upload the image bytes directly to the returned URL.\n3. Call finalize attachment to validate and persist the attachment on the listing.\n\nRules:\n- Listing must belong to the authenticated seller.\n- Listing must be active (`quantity > 0`).\n- The returned image identifier is namespaced to the listing and seller context.\n\nResponse:\n- Returns an `ImageUpload` payload with the image identifier and direct upload URL.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Listing ID"},"required":true,"description":"Listing ID","name":"id","in":"path"}],"responses":{"200":{"description":"Upload URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload"}}}},"404":{"description":"Listing not found"}}},"patch":{"tags":["seller-listings"],"operationId":"finalizeListingAttachment","summary":"Finalize attachment","description":"\nFinalize a previously uploaded listing attachment and persist it on the listing.\n\nThis is step 2 of the listing attachment workflow and must be called after a successful direct upload.\n\nValidation and integrity checks:\n- Listing must belong to the authenticated seller and remain active.\n- `id` must match the expected listing-scoped attachment URN format.\n- Uploaded image must no longer be in draft state.\n\nModeration:\n- The uploaded image is downloaded and passed through moderation checks.\n- Rejected images are deleted and the API returns `451` with rejection reasons.\n\nSide effects:\n- Persists a listing attachment record when validation succeeds.\n- Re-evaluates listing validity:\n  - If the listing requires a photo (price `>= 2000` or grading metadata present), finalizing an attachment marks the listing as `valid: true`.\n\nResponse:\n- Returns the persisted attachment identifier and public URL.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Listing ID"},"required":true,"description":"Listing ID","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload Complete"}}}},"responses":{"200":{"description":"Attachment saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Listing Attachment"}}}},"404":{"description":"Listing not found"},"451":{"description":"Image rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentClassificationFailure"}}}}}},"delete":{"tags":["seller-listings"],"operationId":"deleteListingAttachment","summary":"Delete attachment","description":"\nDelete an existing attachment from a seller listing.\n\nUse this endpoint to remove outdated or incorrect listing images.\n\nValidation and ownership:\n- Listing must belong to the authenticated seller and be active.\n- Attachment `id` must match the expected listing-scoped image URN format.\n\nDeletion behavior:\n- Removes the image from storage.\n- Deletes the listing attachment association in the database.\n- Re-evaluates listing validity after deletion:\n  - Listings that require photos (price `>= 2000` or grading metadata) become `valid: false` when no attachments remain.\n\nResponse:\n- Returns `204 No Content` when deletion completes.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Listing ID"},"required":true,"description":"Listing ID","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingAttachmentDelete"}}}},"responses":{"204":{"description":"Attachment deleted"},"404":{"description":"Listing not found"}}}},"/seller/imports":{"get":{"tags":["seller-imports"],"operationId":"getSellerImports","summary":"List imports","description":"\nList import jobs for the authenticated seller.\n\nUse this endpoint to power import history tables and job monitoring screens.\n\nQuery behavior:\n- Supports page/pageSize pagination.\n- Supports sorting by `createdAt` or `updatedAt` and sort direction.\n\nResponse behavior:\n- Returns summary records only (status and high-level counters).\n- Includes only imports belonging to the authenticated seller.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":20,"default":20},"required":false,"name":"pageSize","in":"query"},{"schema":{"type":"string","enum":["createdAt"],"default":"createdAt"},"required":false,"name":"sortBy","in":"query"},{"schema":{"type":"string","enum":["asc"],"default":"desc"},"required":false,"name":"sortOrder","in":"query"}],"responses":{"200":{"description":"List of seller import summaries","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"status":{"type":"string","enum":["RUNNING"]},"total":{"type":"integer","minimum":0},"successful":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["id","status","total","successful","failed","createdAt","updatedAt"]}}}}},"404":{"description":"Configuration not found"}}},"post":{"tags":["seller-imports"],"operationId":"createSellerImport","summary":"Create an import","description":"\nCreate a new seller import job from a CSV file upload.\n\nUse this endpoint for bulk listing ingestion and migration workflows.\n\nFile validation:\n- Accepts `multipart/form-data` with a CSV file.\n- CSV header must include the `REFERENCE` column as the final field.\n- Rejects empty files and files beyond the maximum row threshold.\n\nProcessing model:\n- Stores the CSV in object storage.\n- Creates import + batch records and queues background workflows.\n- Returns `201` with import details and initial batch states.\n","security":[{"Bearer":[]}],"requestBody":{"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"CSV file to import"}},"required":["file"]}}}},"responses":{"201":{"description":"Seller import details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"status":{"type":"string","enum":["RUNNING"]},"total":{"type":"integer","minimum":0},"successful":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]},"key":{"type":"string"},"batches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"total":{"type":"integer"},"successful":{"type":"integer"},"failed":{"type":"integer"},"status":{"type":"string"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["id","total","successful","failed","status","updatedAt"]}},"errors":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"code":{"type":"integer"},"message":{"type":"string"},"line":{"type":"string"}},"required":["id","code","message","line"]}}},"required":["id","status","total","successful","failed","createdAt","updatedAt","key","batches","errors"]}}}}}}},"/seller/imports/{id}":{"get":{"tags":["seller-imports"],"operationId":"getSellerImport","summary":"Retrieve an import","description":"\nRetrieve detailed status for one import job.\n\nUse this endpoint for import detail pages where per-batch progress and errors are needed.\n\nWhat you get:\n- Import metadata, batch records, and import errors.\n- Best-effort live workflow status for each batch.\n\nRules:\n- Import must belong to the authenticated seller.\n- Returns `404` for missing seller or non-owned import IDs.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Import ID"},"required":true,"description":"Import ID","name":"id","in":"path"}],"responses":{"200":{"description":"Seller import details","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"status":{"type":"string","enum":["RUNNING"]},"total":{"type":"integer","minimum":0},"successful":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]},"key":{"type":"string"},"batches":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"total":{"type":"integer"},"successful":{"type":"integer"},"failed":{"type":"integer"},"status":{"type":"string"},"updatedAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["id","total","successful","failed","status","updatedAt"]}},"errors":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"cuid2"},"code":{"type":"integer"},"message":{"type":"string"},"line":{"type":"string"}},"required":["id","code","message","line"]}}},"required":["id","status","total","successful","failed","createdAt","updatedAt","key","batches","errors"]}}}},"404":{"description":"Import not found"}}}},"/seller/imports/{id}/status/{mode}":{"patch":{"tags":["seller-imports"],"operationId":"updateSellerImport","summary":"Stop/Start an import","description":"\nChange runtime mode for an active import (`pause`, `resume`, `terminate`).\n\nUse this endpoint when operators need to control long-running import processing.\n\nMode rules:\n- `pause`: allowed only for active imports.\n- `resume`: allowed only when status is `PAUSED`.\n- `terminate`: blocked for already completed/failed/terminated imports.\n\nBehavior:\n- Applies the mode to all underlying batch workflows.\n- Persists the new import status.\n- Returns `400` when the requested transition is invalid.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Import ID"},"required":true,"description":"Import ID","name":"id","in":"path"},{"schema":{"type":"string","enum":["pause","resume","terminate"]},"required":true,"name":"mode","in":"path"}],"responses":{"200":{"description":"Import paused successfully"},"400":{"description":"Invalid request"},"404":{"description":"Import not found"}}}},"/seller/delivery-options":{"get":{"tags":["seller-delivery-options"],"operationId":"getDeliveryConfiguration","summary":"Get configuration","description":"\nRetrieve package and delivery configuration for the authenticated seller.\n\nUse this to prefill shipping settings UIs or validate what package profiles are currently active.\n\nBehavior:\n- Reads all package configuration rows for the seller.\n- Returns the normalized delivery configuration array.\n- Falls back to an empty/default configuration set when no rows exist.\n\nAccess rules:\n- Requires seller authentication.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Seller delivery configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryConfiguration"},"example":[{"id":"default-large_letter","type":"LARGE_LETTER","classifications":["CARD","PACK"],"steps":[{"cost":300,"weight":750}]},{"id":"default-small_parcel","type":"SMALL_PARCEL","classifications":["CARD","PACK","BOX","DECK"],"steps":[{"cost":400,"weight":2000}]},{"id":"default-medium_parcel","type":"MEDIUM_PARCEL","classifications":["CARD","PACK","BOX","DECK","CASE"],"steps":[{"weight":2000,"cost":570},{"weight":10000,"cost":750},{"weight":20000,"cost":1200}]},{"id":"default-large_parcel","type":"LARGE_PARCEL","classifications":["CARD","PACK","BOX","DECK","CASE","MISCELLANEOUS"],"steps":[{"weight":5000,"cost":1200},{"weight":10000,"cost":1450},{"weight":20000,"cost":1800},{"weight":30000,"cost":2400}]}]}}},"404":{"description":"Configuration not found"}}},"put":{"tags":["seller-delivery-options"],"operationId":"upsertPackageConfiguration","summary":"Update configuration","description":"\nCreate or update one package configuration entry for the authenticated seller.\n\nUse this endpoint from shipping settings forms when a seller edits package presets.\n\nBehavior:\n- Upserts configuration by `(sellerId, type)`.\n- Returns the full refreshed configuration list after the update.\n- Runs write and read in a transaction so returned data reflects the latest state.\n\nAccess rules:\n- Requires seller authentication and a valid package configuration payload.\n","security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PackageConfigurationInput"}}}},"responses":{"200":{"description":"Updated package configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeliveryConfiguration"},"example":[{"id":"default-large_letter","type":"LARGE_LETTER","classifications":["CARD","PACK"],"steps":[{"cost":300,"weight":750}]},{"id":"default-small_parcel","type":"SMALL_PARCEL","classifications":["CARD","PACK","BOX","DECK"],"steps":[{"cost":400,"weight":2000}]},{"id":"default-medium_parcel","type":"MEDIUM_PARCEL","classifications":["CARD","PACK","BOX","DECK","CASE"],"steps":[{"weight":2000,"cost":570},{"weight":10000,"cost":750},{"weight":20000,"cost":1200}]},{"id":"default-large_parcel","type":"LARGE_PARCEL","classifications":["CARD","PACK","BOX","DECK","CASE","MISCELLANEOUS"],"steps":[{"weight":5000,"cost":1200},{"weight":10000,"cost":1450},{"weight":20000,"cost":1800},{"weight":30000,"cost":2400}]}]}}},"404":{"description":"Seller not found"}}}},"/seller/orders/carriers":{"get":{"tags":["seller-orders"],"operationId":"listCarriers","summary":"List carrier","description":"\nList supported carrier identifiers for shipment tracking.\n\nUse this endpoint to populate shipping carrier dropdowns in seller fulfillment UIs.\n\nBehavior:\n- Returns a key/value map of supported carriers.\n- Data is cached for long periods because carrier lists change infrequently.\n\nTip:\n- Use the returned value exactly when sending shipment update requests.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Carriers","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"description":"Supported carriers for EasyPost tracking"}}}}}}},"/seller/orders":{"get":{"tags":["seller-orders"],"operationId":"listOrders","summary":"List orders","description":"\nList orders assigned to the authenticated seller.\n\nUse this endpoint for seller fulfillment dashboards and order queue pages.\n\nQuery behavior:\n- Supports pagination (`page`, `size`) and sorting (`sort`, `direction`).\n- Caps page size at 50 records.\n\nResponse behavior:\n- Returns summary-level order records.\n- Includes derived item and shipment counts per order.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number"},"required":false,"description":"Page number","name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Results per page"},"required":false,"description":"Results per page","name":"size","in":"query"},{"schema":{"type":"string","enum":["createdAt","updatedAt"],"default":"createdAt","description":"Field to sort by"},"required":false,"description":"Field to sort by","name":"sort","in":"query"},{"schema":{"$ref":"#/components/schemas/OrderSortDirection"},"required":false,"description":"Sort direction","name":"direction","in":"query"}],"responses":{"200":{"description":"Orders","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderSummaryResponse"}}}}}}},"/seller/orders/{id}":{"get":{"tags":["seller-orders"],"operationId":"getOrder","summary":"Get order","description":"\nGet full details for one seller order.\n\nUse this endpoint for order detail screens and fulfillment workflows.\n\nWhat is included:\n- Order items enriched with catalog item details.\n- Shipment data with attachment metadata.\n- Linked case summaries, adjustments, transfers, and review context.\n- Buyer user summary and delivery details for fulfillment.\n\nRules:\n- Order must belong to the authenticated seller or `404` is returned.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"id","in":"path"}],"responses":{"200":{"description":"Order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerOrderDetailResponse"}}}},"404":{"description":"Order not found"}}},"post":{"tags":["seller-orders"],"operationId":"updateOrder","summary":"Update order","description":"\nApply a seller action to an order (for example shipping or dispute actions).\n\nUse this endpoint to progress fulfillment or open item-level disputes from seller tools.\n\nBehavior:\n- Validates order ownership against the authenticated seller.\n- Applies order-item updates through the shared order update engine.\n- Supports structured action payloads (including shipment metadata when required).\n\nResponses:\n- Returns `204` on success.\n- Returns `404` if the order cannot be found for the seller.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Seller Order Update"},"examples":{"Shipped":{"summary":"Mark items as \"shipped\"","description":"Mark one or more items within an order as shipped.","value":{"action":"ship","shipment":{"trackingNumber":"000000000000","carrier":"Royal Mail"},"items":[{"id":"order-item-id-1","quantity":1},{"id":"order-item-id-2","quantity":2}]}},"Dispute":{"summary":"Open a dispute","description":"Open a dispute for one or more items in an order.","value":{"action":"dispute","items":[{"id":"order-item-id-1","quantity":1}],"case":{"reason":"OTHER","comment":"Item not as described","outcomes":[{"type":"REFUND","amount":100}]}}}}}}},"responses":{"204":{"description":"Order updated"},"404":{"description":"Order not found"}}}},"/seller/orders/{id}/packing-slip":{"get":{"tags":["seller-orders"],"operationId":"exportPackingSlip","summary":"Create packing slip","description":"\nGenerate a packing slip document for an order.\n\nUse this endpoint right before packing/dispatch to produce a printable artifact.\n\nInput behavior:\n- Accepts optional `format` query parameter.\n- Supports document output in `pdf` or `csv` depending on request format.\n\nRules:\n- Order must belong to the authenticated seller.\n- Returns `404` when the order cannot be found.\n\nResponse:\n- Returns generated document bytes with a format-appropriate content type.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"id","in":"path"},{"schema":{"$ref":"#/components/schemas/PackingSlipFormat"},"required":false,"description":"Format to generate the packing slip in","name":"format","in":"query"}],"responses":{"200":{"description":"Packing Slip","content":{"application/pdf":{"schema":{"description":"Packing slip document in PDF format"}},"text/csv":{"schema":{"description":"Packing slip document in CSV format"}}}},"404":{"description":"Order not found"}}}},"/seller/orders/{id}/history":{"get":{"tags":["seller-orders"],"operationId":"getSellerOrderHistory","summary":"Get order history","description":"\nRetrieve timeline history entries for a seller order.\n\nUse this endpoint to render audit/history timelines in seller order detail pages.\n\nBehavior:\n- Verifies seller ownership of the order first.\n- Returns history entries in reverse chronological order.\n- Expands each entry with related order item IDs and user context when available.\n\nResponses:\n- Returns `404` for missing or non-owned orders.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"id","in":"path"}],"responses":{"200":{"description":"Order history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurchaseHistoryResponse"}}}},"404":{"description":"Order not found"}}}},"/seller/orders/{id}/cancel":{"post":{"tags":["seller-orders"],"operationId":"cancelSellerOrder","summary":"Cancel order","description":"\nCancel an order from the seller side.\n\nUse this endpoint when a seller cannot fulfill an order and needs to trigger cancellation logic.\n\nRules:\n- Seller must own the order.\n- Cancellation is blocked for invalid states (for example already shipped or non-cancellable items).\n\nResponses:\n- Returns `204` when cancellation succeeds.\n- Returns `400` for non-cancellable orders.\n- Returns `404` when the order is not found for the seller.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"id","in":"path"}],"responses":{"204":{"description":"Order cancelled"},"400":{"description":"Order cannot be cancelled because it has already shipped or contains items that cannot be cancelled."},"404":{"description":"Order not found"}}}},"/seller/orders/{id}/shipments/{shipmentId}/attachments":{"post":{"tags":["seller-orders"],"operationId":"createShipmentAttachment","summary":"Create attachment","description":"\nCreate a draft upload URL for a shipment attachment.\n\nThis is step 1 of the shipment attachment workflow.\n\nWorkflow:\n1. Request an upload URL for a specific order + shipment.\n2. Upload image bytes directly.\n3. Finalize the attachment in a second call.\n\nRules:\n- Shipment must belong to an order owned by the authenticated seller.\n- Attachments are only allowed within a limited time window after shipment creation.\n- Returns `403` when attachment uploads are no longer allowed.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Shipment ID"},"required":true,"description":"Shipment ID","name":"shipmentId","in":"path"}],"responses":{"200":{"description":"Upload URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload"}}}},"403":{"description":"Attachments disabled"},"404":{"description":"Shipment not found"}}},"patch":{"tags":["seller-orders"],"operationId":"finalizeShipmentAttachment","summary":"Finalize attachment","description":"\nFinalize a shipment attachment after direct upload.\n\nThis is step 2 of the shipment attachment workflow.\n\nValidation pipeline:\n- Validates that `imageId` matches the expected shipment attachment URN.\n- Confirms shipment ownership and time-window eligibility.\n- Ensures image upload is complete (not draft).\n- Runs moderation and rejects unsuitable content.\n\nResponses:\n- `451` when moderation rejects the image.\n- `400/403/404` for invalid ID, disabled uploads, or missing shipment.\n- Returns saved attachment metadata on success.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Order ID"},"required":true,"description":"Order ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Shipment ID"},"required":true,"description":"Shipment ID","name":"shipmentId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Image Upload Complete"},{"type":"object","properties":{"hidden":{"type":"boolean","description":"Hide attachment from the buyer"}}}],"description":"Image identifier to finalize upload"}}}},"responses":{"200":{"description":"Attachment saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Shipment Attachment"}}}},"400":{"description":"Invalid image ID"},"403":{"description":"Attachments disabled"},"404":{"description":"Shipment not found"},"451":{"description":"Image rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentClassificationFailure"}}}}}}},"/seller/cases":{"get":{"tags":["seller-cases"],"operationId":"listSellerCases","summary":"List case","description":"\nList cases related to orders sold by the authenticated seller.\n\nUse this endpoint to build case inboxes and moderation queues for seller support teams.\n\nQuery behavior:\n- Supports pagination with `page` and `size`.\n- Supports sorting by `createdAt` or `updatedAt` with explicit direction.\n\nResponse behavior:\n- Returns only cases linked to orders owned by the authenticated seller.\n- Expands outcomes and attachments, with attachment URLs ready for display.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number"},"required":false,"description":"Page number","name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"default":20,"description":"Results per page"},"required":false,"description":"Results per page","name":"size","in":"query"},{"schema":{"type":"string","enum":["createdAt","updatedAt"],"default":"createdAt","description":"Field to sort by"},"required":false,"description":"Field to sort by","name":"sort","in":"query"},{"schema":{"$ref":"#/components/schemas/SellerCaseSortDirection"},"required":false,"description":"Sort direction","name":"direction","in":"query"}],"responses":{"200":{"description":"Seller cases","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerCases"}}}}}}},"/seller/cases/{id}/attachments":{"post":{"tags":["seller-cases"],"operationId":"createSellerCaseAttachment","summary":"Create case attachment","description":"\nCreate a draft upload URL for a seller case attachment.\n\nThis is step 1 of the case attachment flow.\n\nWorkflow:\n1. Call this endpoint to receive an image `id` and direct `uploadURL`.\n2. Upload image bytes directly to the returned URL.\n3. Finalize the upload with the finalize attachment endpoint.\n\nRules:\n- Case must exist and belong to one of the seller’s orders.\n- Non-owned or missing cases return `404`.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"responses":{"200":{"description":"Upload URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload"}}}},"404":{"description":"Case or associated seller not found"}}},"patch":{"tags":["seller-cases"],"operationId":"finalizeSellerCaseAttachment","summary":"Finalize attachment","description":"\nFinalize a previously uploaded seller case attachment.\n\nThis is step 2 of the case attachment flow.\n\nValidation:\n- `imageId` must match the expected URN shape for the case and attachment ID.\n- Uploaded image must exist and no longer be in draft state.\n- Case must belong to one of the authenticated seller’s orders.\n\nResponses:\n- Returns `400` for invalid IDs or unfinished uploads.\n- Returns `404` when the case is missing/not owned.\n- Returns the saved attachment descriptor on success.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload Complete"}}}},"responses":{"200":{"description":"Attachment saved","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"party":{"type":"string","enum":["SELLER","BUYER","SYSTEM"]},"createdAt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date-time"}]}},"required":["url","party","createdAt"]}}}},"400":{"description":"Invalid image ID"},"404":{"description":"Case not found"}}}},"/seller/cases/{id}":{"get":{"tags":["seller-cases"],"operationId":"getSellerCase","summary":"Get case","description":"\nGet one seller-visible case by ID.\n\nUse this endpoint to load a dedicated case details page.\n\nOwnership and visibility:\n- The case must be linked to an order owned by the authenticated seller.\n- Non-owned or missing cases return `404`.\n\nResponse behavior:\n- Returns the full case, outcomes, and attachment metadata.\n- Attachment objects include resolved asset URLs for immediate rendering.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"responses":{"200":{"description":"Case details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerCase"}}}},"404":{"description":"Case not found"}}},"put":{"tags":["seller-cases"],"operationId":"updateSellerCase","summary":"Update case","description":"\nApply a seller action to an existing case.\n\nUse this endpoint for case workflow actions like accepting/rejecting outcomes or escalating.\n\nRules:\n- Seller must own the order associated with the case.\n- Returns `404` for missing/non-owned cases.\n- Returns `409` when an outcome has already been accepted and cannot be changed.\n\nSide effects:\n- Escalation actions trigger case update notifications.\n- Returns the refreshed case representation after mutation.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Case ID"},"required":true,"description":"Case ID","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"type":"string","enum":["escalate"]}},"required":["action"]},{"type":"object","properties":{"action":{"type":"string","enum":["outcome"]},"outcome":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["RETURN"]},"address":{"type":"object","properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"state":{"type":["string","null"]}}},"amount":{"type":"integer","minimum":0},"comment":{"type":"string","minLength":1}},"required":["type","address","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REFUND"]},"amount":{"type":"integer","minimum":0},"comment":{"type":"string","minLength":1}},"required":["type","amount"]},{"type":"object","properties":{"type":{"type":"string","enum":["REPLACEMENT"]},"comment":{"type":"string","minLength":1}},"required":["type"]}]}},"required":["action","outcome"]},{"type":"object","properties":{"action":{"type":"string","enum":["accept"]},"outcome":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["RETURN"]},"id":{"type":"string","format":"cuid2"},"address":{"type":"object","properties":{"city":{"type":["string","null"]},"country":{"type":["string","null"]},"line1":{"type":["string","null"]},"line2":{"type":["string","null"]},"postal_code":{"type":["string","null"]},"state":{"type":["string","null"]}}}},"required":["type","id","address"]},{"type":"object","properties":{"type":{"type":"string","enum":["REFUND"]},"id":{"type":"string","format":"cuid2"}},"required":["type","id"]},{"type":"object","properties":{"type":{"type":"string","enum":["REPLACEMENT"]},"id":{"type":"string","format":"cuid2"}},"required":["type","id"]}]}},"required":["action","outcome"]},{"type":"object","properties":{"action":{"type":"string","enum":["reject"]},"outcome":{"type":"object","properties":{"type":{"type":"string","enum":["RETURN","REFUND","REPLACEMENT"]},"id":{"type":"string","format":"cuid2"}},"required":["type","id"]}},"required":["action","outcome"]},{"type":"object","properties":{"action":{"type":"string","enum":["resolve"]},"outcome":{"type":"object","properties":{"type":{"type":"string","enum":["RETURN"]},"id":{"type":"string","format":"cuid2"}},"required":["type","id"]}},"required":["action","outcome"]}]}}}},"responses":{"200":{"description":"Updated case","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatedSellerCase"}}}},"404":{"description":"Case not found"},"409":{"description":"Outcome already accepted"}}}},"/seller/stats":{"get":{"tags":["seller-stats"],"operationId":"getSellerStats","summary":"Get seller stat","description":"\nRetrieve aggregated seller dashboard statistics.\n\nUse this endpoint for seller home dashboards where you need quick operational totals.\n\nIncluded metrics:\n- Orders: total, open, and waiting-for-action counts.\n- Cases: open case count for the seller’s orders.\n- Listings: total and invalid listing counts.\n\nCaching:\n- Backed by cached counts with tag invalidation.\n- Stats are optimized for fast dashboard loads rather than per-request deep queries.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Seller stats","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerStats"}}}},"404":{"description":"Seller not found"}}}},"/seller/webhooks/metrics":{"get":{"tags":["seller-webhooks"],"operationId":"listSellerWebhookMetrics","summary":"Get delivery metrics","description":"\nRetrieve aggregated webhook delivery metrics for the authenticated seller.\n\nUse this endpoint to monitor webhook reliability over time and detect delivery regressions across event types.\n\nQuery behavior:\n\n- Accepts a 'range' parameter controlling how much historical data is returned.\n- If omitted, the default range is used by the API.\n\nReturned data is designed for dashboards and alerting workflows, including:\n\n- Time-bucketed event series.\n- Separation by webhook event type.\n- Delivery outcome trends across the selected time window.\n\nRecommended monitoring workflow:\n\n1. Query metrics on a regular schedule (for example, dashboard refresh intervals).\n2. Detect spikes in failures or drops in successful deliveries.\n3. Pivot to /failures endpoints for endpoint-level investigation.\n4. Re-run metrics after remediation to confirm recovery.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","enum":["1M","3M","6M","1Y"],"default":"1M","description":"Time range describing how much historical data should be returned"},"required":false,"description":"Time range describing how much historical data should be returned","name":"range","in":"query"}],"responses":{"200":{"description":"Aggregated webhook metrics for the authenticated seller","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventSeries"}}}},"404":{"description":"Seller not found"}}}},"/seller/webhooks":{"get":{"tags":["seller-webhooks"],"operationId":"listSellerWebhooks","summary":"List webhooks","description":"\nRetrieve all webhook endpoints configured for the authenticated seller.\n\nUse this endpoint to build a webhook management screen or to reconcile expected webhook configuration during deployments.\n\nThe response includes per-endpoint configuration and health indicators, including:\n\n- URL and optional description.\n- Enabled/disabled status.\n- Additional headers currently configured.\n- Secret value used by your receiver-side verification logic.\n- Last success/failure timestamps.\n- Consecutive failure counters and subscription events.\n\nOperational guidance:\n\n- Call this endpoint after create, update, subscription changes, or delete operations.\n- Use 'enabled' plus failure counters to detect endpoints that require attention.\n- Persist webhook ids from this response for follow-up operations such as test, update, or failure inspection.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Seller webhook endpoints","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerWebhookListResponse"}}}},"404":{"description":"Seller not found"}}},"post":{"tags":["seller-webhooks"],"operationId":"createSellerWebhook","summary":"Create webhook","description":"\nCreate a new webhook endpoint for the authenticated seller.\n\nUse this endpoint when onboarding a receiver service that should receive seller-side events.\n\nWhat this endpoint configures:\n\n- The destination 'url' where deliveries are sent.\n- Optional 'description' so teams can identify endpoint purpose (for example, 'Production OMS').\n- Optional 'enabled' flag to control whether deliveries start immediately.\n- Optional 'additionalHeaders' that are included with each webhook request.\n- Initial 'subscriptions' defining which event types are delivered.\n\nImportant behavior:\n\n- A seller can register up to 5 webhook endpoints.\n- URL uniqueness is enforced per seller; creating a duplicate URL returns 409.\n- At least one subscription event is required in the request.\n- The response includes the webhook secret and generated webhook id.\n","security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSellerWebhookRequest"}}}},"responses":{"201":{"description":"Webhook endpoint created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerWebhookEndpoint"}}}},"400":{"description":"Invalid request"},"404":{"description":"Seller not found"},"409":{"description":"A webhook already exists for the provided URL"}}}},"/seller/webhooks/{webhookId}":{"get":{"tags":["seller-webhooks"],"operationId":"getSellerWebhook","summary":"Retrieve a webhook","description":"\nRetrieve one webhook endpoint by 'webhookId' for the authenticated seller.\n\nUse this endpoint when loading details for a specific endpoint before editing, testing, or troubleshooting.\n\nTypical use cases:\n\n- Populate a webhook details page.\n- Confirm the active subscription set before replacing subscriptions.\n- Inspect latest delivery health fields (last success/failure and failure counters).\n\nBehavior notes:\n\n- Returns 404 when the webhook id is unknown or does not belong to the current seller.\n- Response shape matches webhook records returned by list endpoints, including subscriptions.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint to retrieve"},"required":true,"description":"Identifier of the webhook endpoint to retrieve","name":"webhookId","in":"path"}],"responses":{"200":{"description":"Webhook endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerWebhookEndpoint"}}}},"404":{"description":"Webhook or seller not found"}}},"patch":{"tags":["seller-webhooks"],"operationId":"updateSellerWebhook","summary":"Update a webhook","description":"\nUpdate mutable configuration fields for an existing seller webhook endpoint.\n\nThis is a partial update endpoint. Send only the fields you want to change.\n\nUpdatable fields:\n\n- 'url'\n- 'description'\n- 'enabled'\n- 'additionalHeaders'\n\nBehavior notes:\n\n- URL uniqueness is enforced; updating to a duplicate URL returns 409.\n- If no updatable fields are supplied, the current webhook state is returned unchanged.\n- Subscription events are not modified here; use PUT /seller/webhooks/{webhookId}/subscriptions.\n\nRecommended change flow:\n\n1. GET /seller/webhooks/{webhookId} to load current configuration.\n2. PATCH this endpoint with only the fields being changed.\n3. GET /seller/webhooks/{webhookId}/test to validate connectivity after URL/header changes.\n4. Review failures and metrics to confirm post-change stability.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint to update"},"required":true,"description":"Identifier of the webhook endpoint to update","name":"webhookId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSellerWebhookRequest"}}}},"responses":{"200":{"description":"Updated webhook endpoint","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerWebhookEndpoint"}}}},"400":{"description":"Invalid request"},"404":{"description":"Webhook or seller not found"},"409":{"description":"A webhook already exists for the provided URL"}}},"delete":{"tags":["seller-webhooks"],"operationId":"deleteSellerWebhook","summary":"Delete webhook","description":"\nDelete a webhook endpoint owned by the authenticated seller.\n\nUse this endpoint to remove deprecated integrations, rotate to a replacement endpoint, or clean up unused environments.\n\nBehavior notes:\n\n- Deletion is permanent for the webhook record.\n- Returns 204 with no response body when deletion succeeds.\n- Returns 404 when the webhook does not exist or is not owned by the current seller.\n\nSafe rollout guidance:\n\n1. Create and verify a replacement endpoint first when continuity is required.\n2. Disable the old endpoint before deletion if you want a staged cutover.\n3. Call GET /seller/webhooks to confirm the endpoint has been removed.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint to delete"},"required":true,"description":"Identifier of the webhook endpoint to delete","name":"webhookId","in":"path"}],"responses":{"204":{"description":"Webhook deleted"},"404":{"description":"Webhook or seller not found"}}}},"/seller/webhooks/{webhookId}/test":{"get":{"tags":["seller-webhooks"],"operationId":"testSellerWebhook","summary":"Test webhook delivery","description":"\nSend a synthetic test event to a specific webhook endpoint.\n\nUse this endpoint to validate receiver reachability, authentication/signature handling, and payload processing before relying on live events.\n\nResponse behavior:\n\n- On success, returns statusCode 200.\n- On delivery failure, returns the failure statusCode and a Base64-encoded HAR payload in 'har' for deep diagnostics.\n\nRecommended usage:\n\n1. Create or update webhook configuration.\n2. Run this test endpoint.\n3. If it fails, decode the HAR payload and inspect request/response details.\n4. Re-test after receiver-side fixes until statusCode is 200.\n\nThis endpoint is intended for validation and troubleshooting, not production event simulation at scale.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint to retrieve"},"required":true,"description":"Identifier of the webhook endpoint to retrieve","name":"webhookId","in":"path"}],"responses":{"200":{"description":"Webhook endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","description":"HTTP status code of the test webhook delivery"},"har":{"type":"string","description":"When a failure occurs, this property contains a Base 64 encoded HAR file of the webhook delivery attempt"}},"required":["statusCode"]}}}},"404":{"description":"Webhook or seller not found"}}}},"/seller/webhooks/{webhookId}/subscriptions":{"put":{"tags":["seller-webhooks"],"operationId":"updateSellerWebhookSubscriptions","summary":"Replace a subscription","description":"\nReplace the full subscription event set for a webhook endpoint.\n\nThis endpoint uses replacement semantics, not patch semantics.\n\nHow replacement works:\n\n- The provided 'events' array becomes the complete source of truth.\n- Existing subscriptions not included in the request are removed.\n- New events in the request are added.\n\nUsage guidance:\n\n- Send the complete desired event list every time.\n- Send an empty array to unsubscribe from all events.\n- Fetch current state first with GET /seller/webhooks/{webhookId} when building edit flows.\n\nTypical workflow:\n\n1. Read current subscriptions.\n2. Build and submit the full desired 'events' array.\n3. Verify with GET /seller/webhooks/{webhookId} or GET /seller/webhooks.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint to update"},"required":true,"description":"Identifier of the webhook endpoint to update","name":"webhookId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSellerWebhookSubscriptionsRequest"}}}},"responses":{"200":{"description":"Updated webhook endpoint including subscriptions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerWebhookEndpoint"}}}},"404":{"description":"Webhook or seller not found"}}}},"/seller/webhooks/{webhookId}/failures":{"get":{"tags":["seller-webhooks"],"operationId":"listSellerWebhookFailures","summary":"List delivery failures","description":"\nList recent delivery failures for a specific webhook endpoint.\n\nUse this endpoint for operational triage when webhook deliveries are failing or when reliability metrics show regressions.\n\nQuery behavior:\n\n- Supports an optional 'limit' parameter.\n- If omitted, the endpoint returns up to 20 failures.\n- Failures are returned in reverse chronological order (newest first).\n\nEach failure includes:\n\n- Response status code from the receiver endpoint.\n- Response time in milliseconds.\n- Failure reason.\n- HAR storage key and timestamp.\n\nRecommended incident workflow:\n\n1. Call this endpoint to identify the latest failing attempts.\n2. Open a specific failure via GET /seller/webhooks/{webhookId}/failures/{failureId}.\n3. Download the HAR when needed for deep HTTP-level debugging.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint to inspect"},"required":true,"description":"Identifier of the webhook endpoint to inspect","name":"webhookId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"Maximum number of failures to return. Defaults to 20."},"required":false,"description":"Maximum number of failures to return. Defaults to 20.","name":"limit","in":"query"}],"responses":{"200":{"description":"Webhook delivery failures","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerWebhookFailureListResponse"}}}},"404":{"description":"Webhook or seller not found"}}}},"/seller/webhooks/{webhookId}/failures/{failureId}":{"get":{"tags":["seller-webhooks"],"operationId":"getSellerWebhookFailure","summary":"Retrieve webhook failure","description":"\nRetrieve detailed metadata for one recorded delivery failure.\n\nUse this endpoint after listing failures to inspect a specific failed attempt in detail.\n\nThe response provides failure-level diagnostics including:\n\n- Receiver HTTP status code.\n- Delivery latency.\n- Failure reason.\n- Timestamp and HAR key reference.\n\nBehavior notes:\n\n- Returns 404 if the webhook is not found for the seller.\n- Returns 404 if the specified failure id is not associated with that webhook.\n\nFor full request/response trace data, call the HAR download endpoint for the same failure id.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint that experienced the failure"},"required":true,"description":"Identifier of the webhook endpoint that experienced the failure","name":"webhookId","in":"path"},{"schema":{"type":"string","description":"Identifier of the failure to retrieve"},"required":true,"description":"Identifier of the failure to retrieve","name":"failureId","in":"path"}],"responses":{"200":{"description":"Webhook delivery failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerWebhookFailure"}}}},"404":{"description":"Webhook, seller, or failure not found"}}}},"/seller/webhooks/{webhookId}/failures/{failureId}/download":{"get":{"tags":["seller-webhooks"],"operationId":"downloadSellerWebhookFailureHar","summary":"Download failure HAR","description":"\nDownload the HAR artifact associated with a specific webhook delivery failure.\n\nUse this endpoint for low-level troubleshooting when you need the full HTTP exchange for a failed delivery.\n\nWhat to expect:\n\n- Response is returned as a downloadable attachment named with the failure id.\n- Content type is preserved from stored HAR metadata when available.\n- Returns 404 if webhook, failure, or HAR payload is unavailable.\n\nRecommended usage:\n\n1. List failures for a webhook.\n2. Select a failure id that needs investigation.\n3. Download the HAR and inspect request headers, payload, response headers, and timing details.\n\nThis endpoint is intended for diagnostics workflows and post-incident analysis.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Identifier of the webhook endpoint that experienced the failure"},"required":true,"description":"Identifier of the webhook endpoint that experienced the failure","name":"webhookId","in":"path"},{"schema":{"type":"string","description":"Identifier of the failure containing the HAR payload"},"required":true,"description":"Identifier of the failure containing the HAR payload","name":"failureId","in":"path"}],"responses":{"200":{"description":"HAR file for the webhook failure","content":{"application/json":{"schema":{}}}},"404":{"description":"Webhook, seller, failure, or HAR payload not found"}}}},"/seller":{"post":{"tags":["seller-account"],"operationId":"createSeller","summary":"Create seller account","description":"\n\nCreate a Stripe seller account for the authenticated user and return the onboarding URL.\n\nWhen a new seller account is created, **a URL will be returned that the user should be forwarded to** in order to complete the Stripe KYC/AML onboarding process.\n\nIf the user already has a seller account (this endpoint is idempotent), a new onboarding URL will be generated.\n\nThis endpoint requires to URLs to be provided in the request body:\n\n- `returnUrl`: The URL to redirect to after the onboarding is complete.\n- `refreshUrl`: The URL to redirect to if the onboarding needs to be refreshed. Ie. the user went to make a coffee.\n\n","security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"returnUrl":{"type":"string","format":"uri","description":"The URL to redirect to after onboarding is complete"},"refreshUrl":{"type":"string","format":"uri","description":"The URL to redirect to if the onboarding needs to be refreshed"}},"required":["returnUrl","refreshUrl"],"description":"Seller onboarding return URLs"}}}},"responses":{"201":{"description":"Seller created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Seller"}}}}}},"get":{"tags":["seller-account"],"operationId":"getSeller","summary":"Get seller account","description":"\nRetrieve the authenticated user’s seller account record.\n\nUse this endpoint to load seller onboarding/account state before rendering seller tools.\n\nWhat is returned:\n- Stripe-connected seller account information for the authenticated seller.\n- Current seller status and account-level fields required by seller-facing dashboards.\n\nAccess rules:\n- Requires seller authentication.\n- Returns `404` if no seller account exists for the caller.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Seller account","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerAccount"}}}},"404":{"description":"Seller not found"}}}},"/seller/status":{"get":{"tags":["seller-account"],"operationId":"getSellerStatus","summary":"Get seller status","description":"\nReturn only the current seller status for the authenticated account.\n\nUse this lightweight endpoint when you only need status gating (for example: pending vs active) and do not need full seller details.\n\nBehavior:\n- Resolves the caller’s seller record and returns a single `status` field.\n- Helpful for fast checks in UI guards and conditional navigation.\n\nAccess rules:\n- Requires seller authentication.\n- Returns `404` if no seller record exists for the user.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Seller account","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"The status of the seller's account"}},"required":["status"]}}}},"404":{"description":"Seller not found"}}}},"/seller/vacation":{"patch":{"tags":["seller-account"],"operationId":"updateVacation","summary":"Update vacation mode","description":"\nEnable or disable vacation mode for the authenticated seller.\n\nUse this when a seller needs to temporarily stop receiving new orders.\n\nState changes:\n- Updates the seller `vacation` flag.\n- Hides all seller listings when vacation mode is enabled.\n- Removes existing listing holds when vacation mode is enabled so baskets can self-clean on next access.\n\nAccess and validation:\n- Seller must exist and be `active`.\n- Returns `401` when the seller is not active.\n- Returns `204` on success with no body.\n","security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vacation":{"type":"boolean","description":"Whether the seller should be set as on vacation"}},"required":["vacation"]}}}},"responses":{"204":{"description":"Vacation mode updated"},"401":{"description":"Seller is not active"},"404":{"description":"Seller not found"}}}},"/seller/dashboard":{"get":{"tags":["seller-account"],"operationId":"getSellerDashboardLink","summary":"Get dashboard link","description":"\nGenerate a seller dashboard login link.\n\nUse this endpoint to redirect sellers into their connected payout/account management dashboard.\n\nBehavior:\n- Looks up the authenticated seller account.\n- Requests a fresh dashboard URL from the payment provider.\n- Returns a one-time link payload suitable for immediate redirect.\n\nAccess rules:\n- Requires seller authentication.\n- Returns `404` if the seller account cannot be found.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Dashboard login link","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Dashboard Link"}}}},"404":{"description":"Seller not found"}}}},"/seller/balance":{"get":{"tags":["seller-finance"],"operationId":"getSellerBalance","summary":"Retrieve balance","description":"\nGet the seller's current balance snapshot.\n\nUse this endpoint to power payout cards and finance overview widgets.\n\nWhat is included:\n- Provider-reported balance values (for example available/pending).\n- Additional pending amount derived from local order state.\n\nAccess rules:\n- Requires seller authentication.\n- Returns `404` if the seller record does not exist.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Seller balance","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SellerBalance"}}}},"404":{"description":"Seller not found"}}}},"/seller/payouts/withdraw":{"post":{"tags":["seller-finance"],"operationId":"withdrawPayout","summary":"Create payout","description":"\nCreate a payout request for the authenticated seller.\n\nUse this endpoint when a seller explicitly requests withdrawal of available funds.\n\nValidation and rules:\n- Reads current balance before creating a payout.\n- Enforces a minimum available balance of `1000` (smallest currency unit).\n- Returns `400` if balance is below the minimum threshold.\n\nResponse:\n- Returns `201` with the created payout resource on success.\n","security":[{"Bearer":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutInput"}}}},"responses":{"201":{"description":"Payout created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Payout"}}}},"400":{"description":"Balance below minimum"},"404":{"description":"Seller not found"}}}},"/seller/payouts":{"get":{"tags":["seller-finance"],"operationId":"listPayouts","summary":"List payouts","description":"\nList seller payouts with cursor pagination.\n\nUse this endpoint for payout history screens and finance reporting views.\n\nQuery behavior:\n- `cursor` continues listing after a prior payout ID.\n- `size` controls page size (defaults to 20 when omitted).\n\nResponse behavior:\n- Returns provider payout records scoped to the authenticated seller.\n- Use the returned pagination metadata to request additional pages.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Payout ID to continue listing from"},"required":false,"description":"Payout ID to continue listing from","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Number of payouts per page, defaults to 20"},"required":false,"description":"Number of payouts per page, defaults to 20","name":"size","in":"query"}],"responses":{"200":{"description":"Paginated payouts","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutList"}}}},"404":{"description":"Seller not found"}}}},"/seller/transfers":{"get":{"tags":["seller-finance"],"operationId":"listTransfers","summary":"List transfers","description":"\nList balance transfer records for the authenticated seller.\n\nUse this endpoint for ledger-style finance views and reconciliation flows.\n\nQuery behavior:\n- Supports cursor pagination with `cursor` and `size`.\n- `size` defaults to 20 when omitted.\n- Cursor values should be taken from the previous page response to avoid gaps or duplicates.\n\nResponse:\n- Returns transfer records from the connected payout provider for this seller account.\n- Ideal for payout reconciliation and showing money movement history alongside payouts.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Transfer ID to continue listing from"},"required":false,"description":"Transfer ID to continue listing from","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Number of transfers per page, defaults to 20"},"required":false,"description":"Number of transfers per page, defaults to 20","name":"size","in":"query"}],"responses":{"200":{"description":"Paginated transfers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferList"}}}},"404":{"description":"Seller not found"}}}},"/listings":{"post":{"operationId":"searchListings","description":"\nSearch public listings using free-text terms, facet filters, sorting, and pagination.\n\nUse this endpoint for marketplace browse pages, category landing pages, and search-result views.\n\nWhat it does:\n- Applies your query text and facet filters against public listing data.\n- Returns only listings with available stock (`available > 0`).\n- Enriches each hit with seller summary data, lock status, and attachment URLs.\n\nPerformance and caching:\n- Results are cached briefly (~30 seconds) for fast repeat searches.\n- The cache key is based on the request body, so different filter sets are isolated.\n","summary":"Search all live listings","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuery"},"examples":{"SearchForPokemonCards":{"summary":"Search for Pokemon cards","description":"Find listings matching a free-text query and basic paging.","value":{"query":"pikachu","from":0,"size":10}},"SearchUsingFacets":{"summary":"Filter by facets","description":"Filter results by game and condition.","value":{"facets":{"Game":["Pokemon"],"Condition":["NM"]},"from":0,"size":25}}}}}},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Listing Search Result"},{"type":"object","properties":{"hits":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked"]}}}}],"description":"Result of a listings search query"},"examples":{"SearchResults":{"description":"An example paginated search response.","value":{"total":1,"hits":[{"id":"lst_123","sellerId":"sel_456","condition":"NM","price":1299,"quantity":2,"available":2,"language":"English","variants":[],"createdAt":"2026-03-01T12:00:00.000Z","updatedAt":"2026-03-01T12:00:00.000Z","item":{"urn":"urn:managem:pokemon:card/base1/58-pikachu","type":"card","game":"Pokemon","title":"Pikachu","name":"Pikachu","rarity":"Common","number":"58","set":{"name":"Base Set","urn":"urn:managem:pokemon:set/base1","counts":{},"references":[]},"series":{"name":"Base","urn":"urn:managem:pokemon:series/base"},"images":[{"urn":"urn:managem:pokemon:image/base1-58","orientation":"portrait","url":"https://assets.managem.co.uk/images/base1-58.png"}],"alternatives":[],"metadata":[],"slug":"/pokemon/card/base1/58-pikachu"},"seller":{"id":"usr_789","username":"cardsmith","avatar":"https://assets.managem.co.uk/avatars/usr_789.png","reviews":120,"rating":4.9,"score":4.8,"sales":540,"purchases":83},"locked":false,"attachments":[]}],"facets":{"Game":{"Pokemon":1},"Condition":{"NM":1}}}}}}}}}}},"/listings/seller/{id}":{"post":{"operationId":"searchSellerListings","summary":"Search a seller's listings","description":"\nSearch listings that belong to a specific seller.\n\nUse this endpoint for seller storefront pages, seller profile inventory tabs, and seller-specific search experiences.\n\nSeller targeting:\n- The `id` path parameter accepts either a user ID or a username.\n- Returns `404` when the seller cannot be found.\n\nSearch behavior:\n- Applies your query text/facets plus an enforced filter for that seller.\n- Returns only listings with available stock (`available > 0`).\n- Enriches hits with seller profile, listing lock status, and attachment URLs.\n\nPerformance:\n- Uses short-lived body-signature caching for repeated seller searches.\n","tags":["listings"],"parameters":[{"schema":{"type":"string","minLength":1,"description":"User ID or username of the seller"},"required":true,"description":"User ID or username of the seller","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuery"},"examples":{"SearchSellerByUsername":{"summary":"Search by seller username","description":"Filter a seller's listings using a text query.","value":{"query":"charizard","from":0,"size":20}}}}}},"responses":{"200":{"description":"Seller listings","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Listing Search Result"},{"type":"object","properties":{"hits":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked"]}}}}],"description":"Result of a listings search query"},"examples":{"SellerListings":{"description":"A filtered listing response for one seller.","value":{"total":1,"hits":[{"id":"lst_987","sellerId":"sel_123","condition":"LP","price":4500,"quantity":1,"available":1,"language":"English","variants":["Holo"],"createdAt":"2026-03-02T12:00:00.000Z","updatedAt":"2026-03-02T12:00:00.000Z","item":{"urn":"urn:managem:pokemon:card/base2/4-charizard","type":"card","game":"Pokemon","title":"Charizard","name":"Charizard","rarity":"Rare","number":"4","set":{"name":"Jungle","urn":"urn:managem:pokemon:set/base2","counts":{},"references":[]},"series":{"name":"Base","urn":"urn:managem:pokemon:series/base"},"images":[{"urn":"urn:managem:pokemon:image/base2-4","orientation":"portrait","url":"https://assets.managem.co.uk/images/base2-4.png"}],"alternatives":[],"metadata":[],"slug":"/pokemon/card/base2/4-charizard"},"seller":{"id":"usr_222","username":"vintagecards","avatar":"https://assets.managem.co.uk/avatars/usr_222.png","reviews":87,"rating":4.7,"score":4.6,"sales":302,"purchases":41},"locked":false,"attachments":[]}],"facets":{"Condition":{"LP":1}}}}}}}},"404":{"description":"Seller not found"}}}},"/listings/item":{"post":{"operationId":"searchItemListings","summary":"Search listings for an item","description":"\nSearch listings for one specific catalog item while still supporting filters and pagination.\n\nUse this when you already know the item reference (`urn` or `slug`) and want live offers for that item.\n\nLookup and filtering behavior:\n- Resolves the item first from `urn` or `slug`.\n- If the item cannot be resolved, the API returns an empty result set instead of an error.\n- Applies additional listing filters and paging controls from the request body.\n- Returns only listings with available stock and enriches hits with seller, lock, and attachment metadata.\n\nPerformance:\n- Responses are cacheable for short periods to support high-traffic product pages.\n","tags":["listings"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"One or more free text search terms"},"filters":{"type":"array","items":{"type":"object","additionalProperties":{}}},"facets":{"type":"object","properties":{"Game":{"type":"array","items":{"type":"string"},"description":"Game name to match, e.g. Pokemon or Magic"},"Product Type":{"type":"array","items":{"type":"string"},"description":"Type of product, for example \"card\" or \"product\""},"Rarity":{"type":"array","items":{"type":"string"},"description":"Card rarity values"},"Series":{"type":"array","items":{"type":"string"},"description":"Series names"},"Set":{"type":"array","items":{"type":"string"},"description":"Set names"},"Illustrator":{"type":"array","items":{"type":"string"},"description":"Illustrator names as stored on item images"},"Condition":{"type":"array","items":{"type":"string"},"description":"Listing condition codes, e.g. MT, NM"},"Grading":{"type":"array","items":{"type":"string","enum":["Graded","Ungraded"]},"description":"Whether the card is \"Graded\" or \"Ungraded\""},"Price":{"type":"array","items":{"type":"string","enum":["Under £1","£1-£10","£10-£20","£20-£50","£50-£100","Over £100"]},"description":"Price buckets expressed in pounds sterling (inclusive of lower bounds)"},"Quantity":{"type":"array","items":{"type":"string","enum":["1","2-10","10-50","50+"]},"description":"Quantity buckets for available stock"},"Valid":{"type":"array","items":{"type":"string","enum":["Valid","Invalid"]},"description":"Listing validity status for seller views"},"Hidden":{"type":"array","items":{"type":"string","enum":["Hidden","Visible"]},"description":"Listing visibility status for seller views"},"Availability":{"type":"array","items":{"type":"string","enum":["In Stock"]},"description":"Filter listings or items to only those that are \"In Stock\""},"Category":{"type":"array","items":{"type":"string"},"description":"Item categories (metadata)"}},"additionalProperties":{"type":"array","items":{"type":"string"},"description":"Additional facets accepted by the search endpoints. Unknown keys are passed through verbatim and applied as term filters."},"description":"Facets to refine the search results. Values are case-sensitive unless noted otherwise."},"from":{"type":["number","null"],"default":0,"description":"Offset for pagination"},"size":{"type":"number","minimum":1,"maximum":50,"default":25,"description":"Number of results to return"},"sorting":{"type":"object","properties":{"field":{"type":"string","enum":["name","number","indexed","price"]},"order":{"type":"string","enum":["asc","desc"]}},"required":["field","order"],"description":"Sort results by field and order"},"urn":{"type":"string","description":"URN of the item to lookup","example":"urn:managem:pokemon:product/pop8/pop-series-8-pack-4c899e14"},"slug":{"type":"string","description":"Slug of the item to lookup","example":"/pokemon/product/pop8/pop-series-8-pack-4c899e14"}}},"examples":{"SearchByUrn":{"summary":"Search by item URN","description":"Retrieve listings for a known item URN.","value":{"urn":"urn:managem:pokemon:card/base1/58-pikachu","from":0,"size":25}},"SearchBySlug":{"summary":"Search by item slug","description":"Retrieve listings for a known item slug.","value":{"slug":"/pokemon/card/base1/58-pikachu","from":0,"size":25}}}}}},"responses":{"200":{"description":"Listings for the item","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Listing Search Result"},{"type":"object","properties":{"hits":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Seller of the listing"}]},"locked":{"type":"boolean","description":"True when the listing has active item holds"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Listing Attachment"},"default":[],"description":"Image attachments for the listing"}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller","locked"]}}}}],"description":"Result of a listings search query"},"examples":{"ItemListings":{"description":"A populated item listings result.","value":{"total":1,"hits":[{"id":"lst_654","sellerId":"sel_321","condition":"NM","price":1599,"quantity":3,"available":3,"language":"English","variants":[],"createdAt":"2026-03-03T12:00:00.000Z","updatedAt":"2026-03-03T12:00:00.000Z","item":{"urn":"urn:managem:pokemon:card/base1/58-pikachu","type":"card","game":"Pokemon","title":"Pikachu","name":"Pikachu","rarity":"Common","number":"58","set":{"name":"Base Set","urn":"urn:managem:pokemon:set/base1","counts":{},"references":[]},"series":{"name":"Base","urn":"urn:managem:pokemon:series/base"},"images":[{"urn":"urn:managem:pokemon:image/base1-58","orientation":"portrait","url":"https://assets.managem.co.uk/images/base1-58.png"}],"alternatives":[],"metadata":[],"slug":"/pokemon/card/base1/58-pikachu"},"seller":{"id":"usr_100","username":"tcgtrader","avatar":"https://assets.managem.co.uk/avatars/usr_100.png","reviews":24,"rating":4.5,"score":4.4,"sales":91,"purchases":12},"locked":false,"attachments":[]}],"facets":{"Availability":{"In Stock":1}}}},"ItemNotFound":{"description":"When no item matches the provided URN or slug, the response is empty.","value":{"total":0,"hits":[],"facets":{}}}}}}}}}},"/listings/prices":{"get":{"operationId":"getItemPrices","summary":"Retrieve historical prices","description":"\nRetrieve time-series price history for a catalog item.\n\nUse this endpoint for pricing charts, trend indicators, and historical comparison views.\n\nInput behavior:\n- Accepts item lookup via `urn` or `slug`.\n- Supports a predefined `range` window (for example `1M`).\n\nRules and responses:\n- Returns `404` when the item cannot be resolved.\n- Returns normalized series data for the resolved item across the selected range.\n- Short-lived caching is applied to improve chart load times.\n","tags":["listings"],"parameters":[{"schema":{"type":"string","description":"URN of the item to lookup","example":"urn:managem:pokemon:product/pop8/pop-series-8-pack-4c899e14"},"required":false,"description":"URN of the item to lookup","name":"urn","in":"query"},{"schema":{"type":"string","description":"Slug of the item to lookup","example":"/pokemon/product/pop8/pop-series-8-pack-4c899e14"},"required":false,"description":"Slug of the item to lookup","name":"slug","in":"query"},{"schema":{"type":"string","enum":["1M","3M","6M","1Y"],"default":"1M"},"required":false,"name":"range","in":"query"}],"responses":{"200":{"description":"Price history","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Item Price Series"},"examples":{"PriceSeries":{"description":"Example aggregated listing and sale prices over time.","value":[{"time":"2026-03-01T00:00:00.000Z","listed":{"min":1000,"max":1500,"avg":1250,"vol":8},"sold":{"min":1100,"max":1400,"avg":1280,"vol":4}},{"time":"2026-03-02T00:00:00.000Z","listed":{"min":900,"max":1600,"avg":1210,"vol":11},"sold":{"min":1000,"max":1500,"avg":1300,"vol":6}}]}}}}},"404":{"description":"Item not found"}}}},"/search":{"post":{"tags":["search"],"operationId":"search","summary":"Full-text faceted search","description":"\nThis is the main marketplace search endpoint.\n\nUse it for:\n- global search bars\n- category and filter pages\n- any browse/results screen where users need discoverability\n\nBehavior:\n- Accepts free-text query, facet filters, sorting, and paging input.\n- Returns matching items plus facet aggregations so the UI can render filter chips and counts.\n\nGood to know:\n- Results are cached briefly (~30s) for identical request bodies.\n- Different JSON bodies generate different cache keys.\n","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuery"},"examples":{"PokemonTextSearch":{"summary":"Simple text search for \"pokemon\"","description":"Returns the first page of Pokemon-related items.","value":{"query":"pokemon","size":2}},"PokemonCardsOnly":{"summary":"Pokemon cards only","description":"Filters Pokemon results to card items only.","value":{"query":"pokemon","facets":{"Game":["Pokemon"],"Product Type":["card"]},"size":2}},"PikachuInSet151SortedByPrice":{"summary":"Pikachu in set 151 sorted by price","description":"Combines free text, set filtering, and explicit price sorting.","value":{"query":"pikachu","facets":{"Game":["Pokemon"],"Set":["151"]},"sorting":{"field":"price","order":"asc"},"size":2}},"PokemonInStockBrowse":{"summary":"Facet-only browse for in-stock Pokemon","description":"Uses only facets (no query text) for browse-first interfaces.","value":{"facets":{"Game":["Pokemon"],"Availability":["In Stock"]},"size":2}},"PokemonPaginationOffset":{"summary":"Paginated Pokemon search with offset","description":"Shows a later page window using `from` + `size`.","value":{"query":"pokemon","from":10,"size":2}}}}}},"responses":{"200":{"description":"Search items and available facets","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchItemsResult"},"examples":{"PokemonTextSearchResponse":{"description":"Observed live response for a simple Pokemon text search (`query: pokemon`, `size: 1`).","value":{"total":4217,"hits":[{"urn":"urn:managem:pokemon:set/miscellaneous/product/pokemon-stacking-tin-paradox-pokemon-a4cf2283","type":"product","game":"Pokemon","title":"Miscellaneous: Pokemon Stacking Tin: Paradox Pokemon","name":"Pokemon Stacking Tin: Paradox Pokemon","classification":"BOX","count":1,"description":"Stack 'Em High! Choose a tin with powerful Pokemon from Paldea or Kitakami.","images":[{"urn":"urn:managem:pokemon:set/miscellaneous/product/pokemon-stacking-tin-paradox-pokemon-a4cf2283/image/0","orientation":"portrait","url":"https://images.managem.co.uk/urn:managem:pokemon:set/miscellaneous/product/pokemon-stacking-tin-paradox-pokemon-a4cf2283/image/0"}],"series":{"name":"Miscellaneous","urn":"urn:managem:pokemon:series/miscellaneous"},"set":{"name":"Miscellaneous","urn":"urn:managem:pokemon:set/miscellaneous","counts":{"printed":0,"total":0},"symbol":{"url":"https://images.managem.co.uk/7722e2a1-df84-41ff-9c0f-41b82b144500"},"references":[]},"available":0,"quantity":0,"slug":"pokemon/product/miscellaneous/pokemon-stacking-tin-paradox-pokemon-a4cf2283"}],"facets":{"Game":{"Pokemon":4203,"Magic: The Gathering":14},"Product Type":{"card":2589,"product":1628},"Set":{"151":63,"Miscellaneous":564,"Pokemon GO":125},"Availability":{"In Stock":120},"Price":{"Under £1":118,"£1-£10":2,"£10-£20":0,"£20-£50":0,"£50-£100":0,"Over £100":1}}}},"PokemonCardsOnlyResponse":{"description":"Observed live response when filtering to Pokemon card results only.","value":{"total":2581,"hits":[{"urn":"urn:managem:pokemon:set/base-set-2/card/105","type":"card","game":"Pokemon","title":"Base Set 2: Pokemon Breeder","name":"Pokemon Breeder","rarity":"Rare","number":"105","set":{"name":"Base Set 2","urn":"urn:managem:pokemon:set/base-set-2","counts":{"printed":130,"total":130},"symbol":{"url":"https://images.managem.co.uk/urn:managem:pokemon:set/base-set-2/symbol/0"},"released":"2000-02-24T00:00:00.000Z","references":["base4","base04","B2","b2"]},"series":{"name":"Base","urn":"urn:managem:pokemon:series/base"},"images":[{"urn":"urn:managem:pokemon:set/base-set-2/card/105/image/0","illustrator":"Ken Sugimori","orientation":"portrait","url":"https://images.managem.co.uk/urn:managem:pokemon:set/base-set-2/card/105/image/0"}],"available":0,"quantity":0,"slug":"pokemon/card/base-set-2/105"}],"facets":{"Game":{"Pokemon":2581},"Product Type":{"card":2581},"Set":{"Pokemon GO":88,"Paldea Evolved":82,"Paradox Rift":70},"Availability":{"In Stock":118},"Price":{"Under £1":117,"£1-£10":1,"£10-£20":0,"£20-£50":0,"£50-£100":0,"Over £100":0}}}},"PikachuSetSortedByPriceResponse":{"description":"Observed live response for `pikachu` in set `151`, sorted by ascending price.","value":{"total":2,"hits":[{"urn":"urn:managem:pokemon:set/151/card/25","type":"card","game":"Pokemon","title":"151: Pikachu","name":"Pikachu","rarity":"Common","number":"25","description":"When it is angered, it immediately discharges the energy stored in the pouches in its cheeks.","set":{"name":"151","urn":"urn:managem:pokemon:set/151","counts":{"printed":165,"total":207},"symbol":{"url":"https://images.managem.co.uk/urn:managem:pokemon:set/151/symbol/0"},"released":"2023-09-21T23:00:00.000Z","references":["sv3pt5","sv03t5","MEW","mew"]},"series":{"name":"Scarlet & Violet","urn":"urn:managem:pokemon:series/scarlet-and-violet"},"images":[{"urn":"urn:managem:pokemon:set/151/card/25/image/0","illustrator":"Naoyo Kimura","orientation":"portrait","url":"https://images.managem.co.uk/urn:managem:pokemon:set/151/card/25/image/0"}],"available":2,"quantity":2,"min":{"price":3},"max":{"price":3},"slug":"pokemon/card/151/25"}],"facets":{"Game":{"Pokemon":2},"Product Type":{"card":2},"Set":{"151":2},"Availability":{"In Stock":1},"Price":{"Under £1":1,"£1-£10":0,"£10-£20":0,"£20-£50":0,"£50-£100":0,"Over £100":0}}}},"PokemonInStockBrowseResponse":{"description":"Observed live response for facet-only in-stock Pokemon browsing.","value":{"total":768,"hits":[{"urn":"urn:managem:pokemon:set/chilling-reign/card/15","type":"card","game":"Pokemon","title":"Chilling Reign: Tsareena","name":"Tsareena","rarity":"Rare","number":"15","description":"A kick from the hardened tips of this Pokemon's legs leaves a wound in the opponent's body and soul that will never heal.","set":{"name":"Chilling Reign","urn":"urn:managem:pokemon:set/chilling-reign","counts":{"printed":198,"total":233},"symbol":{"url":"https://images.managem.co.uk/urn:managem:pokemon:set/chilling-reign/symbol/0"},"released":"2021-06-17T23:00:00.000Z","references":["swsh6","swsh06","CRE","cre"]},"series":{"name":"Sword & Shield","urn":"urn:managem:pokemon:series/sword-and-shield"},"images":[{"urn":"urn:managem:pokemon:set/chilling-reign/card/15/image/0","illustrator":"Yuu Nishida","orientation":"portrait","url":"https://images.managem.co.uk/urn:managem:pokemon:set/chilling-reign/card/15/image/0"}],"available":1,"quantity":1,"min":{"price":10},"max":{"price":10},"slug":"pokemon/card/chilling-reign/15"}],"facets":{"Game":{"Pokemon":768},"Product Type":{"card":765,"product":3},"Set":{"151":60,"Fusion Strike":183,"Chilling Reign":129},"Availability":{"In Stock":768},"Price":{"Under £1":709,"£1-£10":50,"£10-£20":4,"£20-£50":3,"£50-£100":0,"Over £100":2}}}}}}}}}}},"/search/vector":{"post":{"tags":["search"],"operationId":"searchVector","summary":"Vector image search","description":"\nFind visually similar trading cards using a precomputed image embedding.\n\n**Use this endpoint for:**\n- image-based card recognition flows\n- camera upload search\n- similarity search from a cropped card artwork image\n\n**Preparation requirements:**\n- Generate a single image embedding from one card image at a time.\n- Use CLIP ViT-B/32-compatible image preprocessing so the model input is prepared as float32 pixel values with shape `[1, 3, 224, 224]`.\n- Use the model embedding output with shape `[1, 512]`.\n- L2-normalize the 512-dimensional vector before sending it to this API.\n- Send only the normalized numeric vector in `vectors`. Do not send raw pixels, base64 image data, or wrapped model response objects.\n\n**Behavior:**\n- Accepts exactly one 512-dimensional embedding per request.\n- Accepts an optional `limit` between 1 and 10. If omitted, the API returns up to 5 matches.\n- Returns visually similar card matches, ordered by similarity score.\n- Each match includes the scored card identifier fields needed to resolve the card and display a primary image preview.\n\n**Good to know:**\n- This route is designed for image embeddings only. It does not generate embeddings from uploaded files.\n- Invalid vectors are rejected before any similarity search is performed.\n","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VectorSearchRequest"},"examples":{"NormalizedCardEmbedding":{"summary":"Normalized 512-dimensional card embedding","description":"Example payload structure for a single normalized card image embedding.","value":{"limit":3,"vectors":[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}}}}}},"responses":{"200":{"description":"Scored vector matches for the submitted image embedding","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VectorSearchResponse"},"examples":{"SimilarPokemonCards":{"description":"Example response showing visually similar Pokemon card matches for one submitted embedding.","value":{"count":2,"matches":[{"score":0.9987,"urn":"urn:managem:pokemon:set/151/card/25","game":"Pokemon","title":"151: Pikachu","number":"25","image":"https://images.managem.co.uk/urn:managem:pokemon:set/151/card/25/image/0"},{"score":0.9921,"urn":"urn:managem:pokemon:set/base-set/card/58","game":"Pokemon","title":"Base Set: Pikachu","number":"58","image":"https://images.managem.co.uk/urn:managem:pokemon:set/base-set/card/58/image/0"}]}}}}}},"400":{"description":"Validation error. The request must include a single non-zero 512-dimensional numeric vector."}}}},"/search/users":{"post":{"tags":["search"],"operationId":"searchUsers","summary":"Search users","description":"\nLookup one or more users by ID and/or username.\n\nUse this for quick user hydration in:\n- conversation lists\n- activity feeds\n- review lists\n- any UI that only has IDs/usernames and needs profile summaries\n\nBehavior:\n- Accepts a mix of `ids` and `usernames`.\n- Returns matched user records in one round-trip.\n\nGood to know:\n- Responses are cached briefly for repeated lookup payloads.\n","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"ids":{"type":"array","items":{"type":"string"},"maxItems":25,"description":"List of user IDs to lookup"},"usernames":{"type":"array","items":{"type":"string"},"maxItems":25,"description":"List of usernames to lookup"}}}}}},"responses":{"200":{"description":"List of users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LookupUsersResult"}}}}}}},"/search/lookup":{"get":{"tags":["search"],"operationId":"lookup","summary":"Lookup item","description":"\nResolve a single indexed item using either a URN or a slug.\n\nUse this when opening an item detail page from a stable identifier.\n\nBehavior:\n- Accepts query parameters for `urn` or `slug`.\n- Returns the matched indexed item document when found.\n- Returns `404` when no matching item exists.\n\nGood to know:\n- 200 and 404 responses are both cacheable for a short period, which helps repeated lookups.\n","parameters":[{"schema":{"type":"string","description":"URN of the item to lookup","example":"urn:managem:pokemon:product/pop8/pop-series-8-pack-4c899e14"},"required":false,"description":"URN of the item to lookup","name":"urn","in":"query"},{"schema":{"type":"string","description":"Slug of the item to lookup","example":"/pokemon/product/pop8/pop-series-8-pack-4c899e14"},"required":false,"description":"Slug of the item to lookup","name":"slug","in":"query"}],"responses":{"200":{"description":"A specific item, if it exists","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set"]}]}}}},"404":{"description":"Item not found"}}}},"/search/lookup/bulk":{"post":{"tags":["search"],"operationId":"bulkLookup","summary":"Lookup items by URN","description":"\nResolve many indexed items in one request using a batch of URNs.\n\nUse this for:\n- import previews\n- server-side enrichment jobs\n- list views that need to hydrate many URNs quickly\n\nBehavior:\n- Accepts between 1 and 200 URNs per request.\n- Returns found indexed item records for matching URNs.\n\nGood to know:\n- URNs are normalized into a stable cache signature, so repeated batches are efficient.\n","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"urns":{"type":"array","items":{"type":"string","pattern":"[^/]$"},"minItems":1,"maxItems":200,"description":"List of URNs to lookup. Maximum of 200 items to match search limits"}},"required":["urns"]}}}},"responses":{"200":{"description":"List of found items and unprocessed URNs","content":{"application/json":{"schema":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}]},"description":"Items found for the provided URNs"}}}}}}},"/search/hierarchy":{"get":{"tags":["search"],"operationId":"hierarchy","summary":"Full hierarchy","description":"\nFetch the browse hierarchy grouped by game, set, and type.\n\nUse this endpoint to build:\n- top-level navigation menus\n- browse trees\n- game/set/type landing pages\n\nBehavior:\n- Returns a hierarchical map with slugs and facets for each node.\n- Designed to power browse-first experiences before users type a query.\n\nGood to know:\n- This response is cached for longer than regular search to keep navigation fast.\n","responses":{"200":{"description":"The hierarchy of items, grouped by game, set, and type","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"facets":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"},"minItems":1}},"slug":{"type":"string"},"title":{"type":"string"},"count":{"type":"number"},"cards":{"type":"number"},"products":{"type":"number"},"hierarchy":{"type":"array","items":{"type":"object","properties":{"facets":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"},"minItems":1}},"slug":{"type":"string"},"title":{"type":"string"},"count":{"type":"number"},"cards":{"type":"number"},"products":{"type":"number"},"released":{"type":"string"},"symbol":{"type":"object","properties":{"url":{"type":"string","format":"uri"}},"required":["url"]},"hierarchy":{"type":"array","items":{"type":"object","properties":{"facets":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"},"minItems":1}},"slug":{"type":"string"},"title":{"type":"string"},"count":{"type":"number"}},"required":["facets","slug","title","count"]}}},"required":["facets","slug","title","count","cards","products","hierarchy"]}}},"required":["facets","slug","title","count","cards","products","hierarchy"]}}}}}}}},"/search/hierarchy/{game}":{"post":{"tags":["search"],"operationId":"getGameHierarchy","summary":"Hierarchy by games","description":"\nSearch within a single game node from the hierarchy.\n\nUse this for game-level pages like \"Pokemon\", \"Yu-Gi-Oh!\", and similar browse routes.\n\nBehavior:\n- Resolves the `{game}` slug to hierarchy facets.\n- Merges those facets with any user-provided query filters.\n- Runs a normal search using the merged query.\n\nFailure behavior:\n- Returns `404` if the game slug does not exist in the current hierarchy.\n","parameters":[{"schema":{"type":"string","description":"The slug of the game to retrieve results for","example":"pokemon"},"required":true,"description":"The slug of the game to retrieve results for","name":"game","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuery"}}}},"responses":{"200":{"description":"Results for the matching game","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchItemsResult"}}}}}}},"/search/hierarchy/{game}/{set}":{"post":{"tags":["search"],"operationId":"getSetHierarchy","summary":"Hierarchy by set","description":"\nSearch within a specific set under a game hierarchy node.\n\nUse this for set-specific pages such as \"Base Set\", \"Jungle\", and other collection views.\n\nBehavior:\n- Resolves `{game}` and `{set}` slugs in the hierarchy tree.\n- Merges node facets with any user-provided filters from the request body.\n- Returns standard search results for that scoped set.\n\nFailure behavior:\n- Returns `404` when the set slug is not found for the selected game.\n","parameters":[{"schema":{"type":"string","description":"The slug of the game to retrieve results for","example":"pokemon"},"required":true,"description":"The slug of the game to retrieve results for","name":"game","in":"path"},{"schema":{"type":"string","description":"The slug of the set to retrieve results for","example":"base-set"},"required":true,"description":"The slug of the set to retrieve results for","name":"set","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuery"}}}},"responses":{"200":{"description":"Results for the matching set","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchItemsResult"}}}}}}},"/search/hierarchy/{game}/{set}/{type}":{"post":{"tags":["search"],"operationId":"getTypeHierarchy","summary":"Hierarchy by product","description":"\nSearch within a specific type node under a game and set.\n\nUse this for focused views like:\n- cards-only in a set\n- products-only in a set\n- any browse page scoped to `game + set + type`\n\nBehavior:\n- Resolves `{game}`, `{set}`, and `{type}` slugs in the hierarchy.\n- Merges hierarchy facets with request-body filters.\n- Returns standard search results within that narrowed scope.\n\nFailure behavior:\n- Returns `404` when no matching type exists for the selected game/set path.\n","parameters":[{"schema":{"type":"string","description":"The slug of the game to retrieve results for","example":"pokemon"},"required":true,"description":"The slug of the game to retrieve results for","name":"game","in":"path"},{"schema":{"type":"string","description":"The slug of the set to retrieve results for","example":"base-set"},"required":true,"description":"The slug of the set to retrieve results for","name":"set","in":"path"},{"schema":{"type":"string","description":"The slug of the type to retrieve results for","example":"card"},"required":true,"description":"The slug of the type to retrieve results for","name":"type","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchQuery"}}}},"responses":{"200":{"description":"Results for the matching type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchItemsResult"}}}}}}},"/conversations":{"get":{"tags":["conversations"],"operationId":"getInbox","summary":"List conversations","description":"\nRetrieve conversations for the authenticated user, including each conversation's latest message.\n\nUse this endpoint for inbox views and messaging sidebars.\n\nQuery behavior:\n- Supports pagination and sorting by creation or update timestamp.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"default":1,"description":"Page number, defaults to 1"},"required":false,"description":"Page number, defaults to 1","name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Results per page, defaults to 20"},"required":false,"description":"Results per page, defaults to 20","name":"size","in":"query"},{"schema":{"type":"string","enum":["createdAt","updatedAt"],"default":"updatedAt","description":"Field to sort by"},"required":false,"description":"Field to sort by","name":"sort","in":"query"},{"schema":{"$ref":"#/components/schemas/ConversationSortDirection"},"required":false,"description":"Sort direction","name":"direction","in":"query"}],"responses":{"200":{"description":"List of conversations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Conversations"}}}}}},"post":{"tags":["conversations"],"operationId":"createConversation","summary":"Create conversation","description":"\nCreate a conversation and send the first message.\n\nUse this endpoint to start buyer/seller conversations from listing or order context.\n\nBehavior:\n- Creates the conversation and initial message in one request.\n- Sends an email notification when the recipient is inactive.\n","security":[{"Bearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Create Conversation Input"}}}},"responses":{"201":{"description":"Conversation created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the conversation"},"source":{"type":"object","properties":{"type":{"type":"string","enum":["ORDER","CASE"],"description":"Source type"},"id":{"type":"string","description":"Source identifier"}},"required":["type","id"],"description":"Conversation source"},"userA":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"First participant"}]},"userB":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Second participant"}]},"locked":{"type":"boolean","description":"Whether the conversation is locked"},"createdAt":{"type":["string","null"],"description":"Timestamp when the conversation was created"},"updatedAt":{"type":["string","null"],"description":"Timestamp when the conversation was last updated"},"lastMessage":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the message"},"conversationId":{"type":"string","description":"Conversation this message belongs to"},"sender":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that sent the message"}]},"body":{"type":"string","description":"Content of the message"},"createdAt":{"type":["string","null"],"description":"Timestamp when the message was created"},"viewedAt":{"type":["string","null"],"description":"Timestamp when the message was viewed"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Message Attachment"},"description":"Images attached to the message"}},"required":["id","conversationId","sender","body"],"description":"Latest message in the conversation"}},"required":["id","source","userA","userB","locked"]}}}}}}},"/conversations/unread-count":{"get":{"tags":["conversations"],"operationId":"getUnreadCount","summary":"Count unread messages","description":"\nReturn the unread message count for the authenticated user.\n\nUse this endpoint for inbox badges, navigation indicators, and notification counters.\n","security":[{"Bearer":[]}],"responses":{"200":{"description":"Unread message count","content":{"application/json":{"schema":{"type":"object","properties":{"count":{"type":"number","description":"Count of unread messages"}},"required":["count"]}}}}}}},"/conversations/{id}/lock":{"post":{"tags":["conversations"],"operationId":"lockConversation","summary":"Lock conversation","description":"\nLock a conversation to prevent any new messages.\n\nUse this endpoint when a conversation should be closed after resolution.\n\nBehavior:\n- Only conversation participants may lock a conversation.\n- Returns the conversation state after the lock operation.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Conversation ID"},"required":true,"description":"Conversation ID","name":"id","in":"path"}],"responses":{"200":{"description":"Conversation locked","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the conversation"},"source":{"type":"object","properties":{"type":{"type":"string","enum":["ORDER","CASE"],"description":"Source type"},"id":{"type":"string","description":"Source identifier"}},"required":["type","id"],"description":"Conversation source"},"userA":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"First participant"}]},"userB":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"Second participant"}]},"locked":{"type":"boolean","description":"Whether the conversation is locked"},"createdAt":{"type":["string","null"],"description":"Timestamp when the conversation was created"},"updatedAt":{"type":["string","null"],"description":"Timestamp when the conversation was last updated"},"lastMessage":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the message"},"conversationId":{"type":"string","description":"Conversation this message belongs to"},"sender":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that sent the message"}]},"body":{"type":"string","description":"Content of the message"},"createdAt":{"type":["string","null"],"description":"Timestamp when the message was created"},"viewedAt":{"type":["string","null"],"description":"Timestamp when the message was viewed"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Message Attachment"},"description":"Images attached to the message"}},"required":["id","conversationId","sender","body"],"description":"Latest message in the conversation"}},"required":["id","source","userA","userB","locked"]}}}},"404":{"description":"Conversation not found"}}}},"/conversations/{id}/messages":{"get":{"tags":["conversations"],"operationId":"getMessages","summary":"List messages","description":"\nRetrieve paginated messages for a conversation.\n\nUse this endpoint for conversation message timelines.\n\nQuery behavior:\n- Supports pagination through `page` and `size`.\n- Returns newest messages first.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Conversation ID"},"required":true,"description":"Conversation ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Page number, defaults to 1"},"required":false,"description":"Page number, defaults to 1","name":"page","in":"query"},{"schema":{"type":"string","description":"Number of messages per page, defaults to 20"},"required":false,"description":"Number of messages per page, defaults to 20","name":"size","in":"query"}],"responses":{"200":{"description":"List of messages","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Messages"}}}},"404":{"description":"Conversation not found"}}},"post":{"tags":["conversations"],"operationId":"sendMessage","summary":"Send message","description":"\nSend a message in an existing conversation.\n\nUse this endpoint when a participant replies in an active conversation.\n\nBehavior:\n- Validates participant access and conversation lock state.\n- Sends an email notification when the recipient is inactive.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Conversation ID"},"required":true,"description":"Conversation ID","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","description":"Message body"}},"required":["body"]}}}},"responses":{"201":{"description":"Message created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier for the message"},"conversationId":{"type":"string","description":"Conversation this message belongs to"},"sender":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"User that sent the message"}]},"body":{"type":"string","description":"Content of the message"},"createdAt":{"type":["string","null"],"description":"Timestamp when the message was created"},"viewedAt":{"type":["string","null"],"description":"Timestamp when the message was viewed"},"attachments":{"type":"array","items":{"$ref":"#/components/schemas/Message Attachment"},"description":"Images attached to the message"}},"required":["id","conversationId","sender","body"]}}}},"404":{"description":"Conversation not found"}}}},"/conversations/{id}/messages/{messageId}/attachments":{"post":{"tags":["conversations"],"operationId":"createMessageAttachment","summary":"Create attachment","description":"\nCreate a direct-upload target for a message attachment.\n\nUse this endpoint before uploading an image attachment for a message.\n\nBehavior:\n- Validates conversation membership and message ownership.\n- Returns upload metadata for the attachment image.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Conversation ID"},"required":true,"description":"Conversation ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Message ID"},"required":true,"description":"Message ID","name":"messageId","in":"path"}],"responses":{"200":{"description":"Upload URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload"}}}},"404":{"description":"Conversation or message not found"}}},"patch":{"tags":["conversations"],"operationId":"finalizeMessageAttachment","summary":"Finalize attachment","description":"\nFinalize an uploaded message attachment and save it to the message.\n\nUse this endpoint after the direct upload to confirm the attachment.\n\nBehavior:\n- Validates conversation membership and message ownership.\n- Rejects unsafe images when moderation fails.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Conversation ID"},"required":true,"description":"Conversation ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Message ID"},"required":true,"description":"Message ID","name":"messageId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Image Upload Complete"}}}},"responses":{"200":{"description":"Attachment saved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message Attachment"}}}},"404":{"description":"Conversation or message not found"},"451":{"description":"Image rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AttachmentClassificationFailure"}}}}}}},"/conversations/{id}/messages/{messageId}/attachments/{attachmentId}":{"delete":{"tags":["conversations"],"operationId":"deleteMessageAttachment","summary":"Delete attachment","description":"\nDelete an attachment from a conversation message.\n\nUse this endpoint when a sender removes an attachment from their message.\n\nBehavior:\n- Validates conversation membership.\n- Removes the attachment record and returns a no-content response.\n","security":[{"Bearer":[]}],"parameters":[{"schema":{"type":"string","description":"Conversation ID"},"required":true,"description":"Conversation ID","name":"id","in":"path"},{"schema":{"type":"string","description":"Message ID"},"required":true,"description":"Message ID","name":"messageId","in":"path"},{"schema":{"type":"string","description":"Attachment ID"},"required":true,"description":"Attachment ID","name":"attachmentId","in":"path"}],"responses":{"204":{"description":"Attachment deleted"},"404":{"description":"Conversation or message not found"}}}},"/basket/{id}":{"get":{"tags":["basket"],"operationId":"getBasket","summary":"Get basket items","description":"\nThink of this as the \"show me my cart\" endpoint.\n\nUse it any time you need the full, current list of basket items, for example:\n- loading the basket page\n- refreshing after add/update/remove actions\n- showing item-level basket details before checkout\n\nHow it works:\n- You pass a basket ID in the path.\n- The API returns the full item list for that basket.\n\nGood to know:\n- Basket IDs are caller-generated unique identifiers.\n- The basket becomes associated with the user who first modifies it.\n- Once owned, other users cannot update that basket.\n","parameters":[{"schema":{"type":"string","description":"The ID of the basket to retrieve"},"required":true,"description":"The ID of the basket to retrieve","name":"id","in":"path"}],"responses":{"200":{"description":"List of items in the basket","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","description":"The URN of the item"},"price":{"type":"integer","exclusiveMinimum":0,"description":"The price in pence, per item (in the basket)"},"quantity":{"type":"integer","exclusiveMinimum":0,"default":1,"description":"The quantity of the item in the basket, defaults to 1"},"condition":{"type":"string","description":"Condition of the listed item"},"language":{"type":"string","description":"Language of the listed item"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed item"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"sellerId":{"type":"string","description":"The sellers ID"},"classification":{"type":"string","enum":["CARD"],"description":"The classification of the basket item (CARD, BOX, CASE, etc.)"},"count":{"type":"integer","minimum":0,"description":"The count of product per quantity, eg. 2x 'set of 2'"},"listing":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"The seller of the listing"}]}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller"],"description":"The latest listing data for the item"},"expires":{"type":"string","format":"date-time","description":"When the item hold expires"}},"required":["urn","price","condition","language","sellerId","classification","count","listing","expires"]}}}}}}}},"post":{"tags":["basket"],"security":[{"Bearer":[]}],"operationId":"addBasketItem","summary":"Add item to basket","description":"\nAdds a listing to the basket and gives you the updated basket state back.\n\nTypical usage:\n- user clicks \"Add to basket\" on a listing page\n- client sends `listingId` and `quantity`\n- UI refreshes from the returned basket payload\n\nWhy this response is handy:\n- You can re-render the whole basket immediately without an extra read call.\n\nImportant behavior:\n- Requires authentication.\n- If stock is unavailable (or the listing is invalid), the API returns structured listing errors.\n","parameters":[{"schema":{"type":"string","description":"The ID of the basket to retrieve"},"required":true,"description":"The ID of the basket to retrieve","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"listingId":{"type":"string","description":"The ID of the listing"},"quantity":{"type":"integer","exclusiveMinimum":0,"default":1,"description":"The quantity of the item in the basket, defaults to 1"}},"required":["listingId"]}}}},"responses":{"200":{"description":"Updated list of items in the basket","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","description":"The URN of the item"},"price":{"type":"integer","exclusiveMinimum":0,"description":"The price in pence, per item (in the basket)"},"quantity":{"type":"integer","exclusiveMinimum":0,"default":1,"description":"The quantity of the item in the basket, defaults to 1"},"condition":{"type":"string","description":"Condition of the listed item"},"language":{"type":"string","description":"Language of the listed item"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed item"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"sellerId":{"type":"string","description":"The sellers ID"},"classification":{"type":"string","enum":["CARD"],"description":"The classification of the basket item (CARD, BOX, CASE, etc.)"},"count":{"type":"integer","minimum":0,"description":"The count of product per quantity, eg. 2x 'set of 2'"},"listing":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"The seller of the listing"}]}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller"],"description":"The latest listing data for the item"},"expires":{"type":"string","format":"date-time","description":"When the item hold expires"}},"required":["urn","price","condition","language","sellerId","classification","count","listing","expires"]}}}}}},"404":{"description":"A listing in the basket was not found","content":{"application/json":{"schema":{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]}}}},"409":{"description":"The listings in the response body are no longer available in their requested quantity","content":{"application/json":{"schema":{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]}}}},"500":{"description":"A listing in the basket was not found","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]},{},{"type":"null"}]}}}}}},"put":{"tags":["basket"],"security":[{"Bearer":[]}],"operationId":"updateBasketItem","summary":"Update basket item","description":"\nUpdates quantity for an item that is already in the basket.\n\nUse this for quantity steppers, inline quantity edits, and \"update cart\" actions.\n\nWhat you get back:\n- the refreshed basket item list, ready to re-render in the UI\n\nImportant behavior:\n- Requires authentication.\n- Validates listing availability for the new quantity.\n- Returns listing-level errors when stock cannot satisfy the requested update.\n","parameters":[{"schema":{"type":"string","description":"The ID of the basket to retrieve"},"required":true,"description":"The ID of the basket to retrieve","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"listingId":{"type":"string","description":"The ID of the listing"},"quantity":{"type":"integer","exclusiveMinimum":0,"default":1,"description":"The quantity to reduce by, defaults to 1"}},"required":["listingId"]}}}},"responses":{"200":{"description":"The updated basket items","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","description":"The URN of the item"},"price":{"type":"integer","exclusiveMinimum":0,"description":"The price in pence, per item (in the basket)"},"quantity":{"type":"integer","exclusiveMinimum":0,"default":1,"description":"The quantity of the item in the basket, defaults to 1"},"condition":{"type":"string","description":"Condition of the listed item"},"language":{"type":"string","description":"Language of the listed item"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed item"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"sellerId":{"type":"string","description":"The sellers ID"},"classification":{"type":"string","enum":["CARD"],"description":"The classification of the basket item (CARD, BOX, CASE, etc.)"},"count":{"type":"integer","minimum":0,"description":"The count of product per quantity, eg. 2x 'set of 2'"},"listing":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"The seller of the listing"}]}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller"],"description":"The latest listing data for the item"},"expires":{"type":"string","format":"date-time","description":"When the item hold expires"}},"required":["urn","price","condition","language","sellerId","classification","count","listing","expires"]}}}}}},"404":{"description":"A listing in the basket was not found","content":{"application/json":{"schema":{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]}}}},"409":{"description":"The listings in the response body are no longer available in their requested quantity","content":{"application/json":{"schema":{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]}}}},"500":{"description":"A listing in the basket was not found","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]},{},{"type":"null"}]}}}}}},"delete":{"tags":["basket"],"security":[{"Bearer":[]}],"operationId":"removeBasketItem","summary":"Remove item from basket","description":"\nRemoves an item from the basket and returns the updated basket payload.\n\nUse this for \"Remove\" actions in basket/cart UI.\n\nBehavior:\n- Requires authentication.\n- Removes the requested listing from the basket.\n- Returns the new basket state so the client can update immediately.\n","parameters":[{"schema":{"type":"string","description":"The ID of the basket to retrieve"},"required":true,"description":"The ID of the basket to retrieve","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"listingId":{"type":"string","description":"The ID of the listing"}},"required":["listingId"]}}}},"responses":{"200":{"description":"The updated basket items","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","description":"The URN of the item"},"price":{"type":"integer","exclusiveMinimum":0,"description":"The price in pence, per item (in the basket)"},"quantity":{"type":"integer","exclusiveMinimum":0,"default":1,"description":"The quantity of the item in the basket, defaults to 1"},"condition":{"type":"string","description":"Condition of the listed item"},"language":{"type":"string","description":"Language of the listed item"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed item"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"sellerId":{"type":"string","description":"The sellers ID"},"classification":{"type":"string","enum":["CARD"],"description":"The classification of the basket item (CARD, BOX, CASE, etc.)"},"count":{"type":"integer","minimum":0,"description":"The count of product per quantity, eg. 2x 'set of 2'"},"listing":{"type":"object","properties":{"id":{"type":"string"},"sellerId":{"type":"string"},"condition":{"type":"string","description":"Product condition"},"price":{"type":"integer","description":"Price in pence"},"quantity":{"type":"integer","default":1,"description":"Total quantity for this listings"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"language":{"type":"string","description":"Languages of the card"},"variants":{"type":"array","items":{"type":"string"},"default":[],"description":"Variants of the listed card"},"comment":{"type":["string","null"],"description":"Seller's comment about the listing"},"gradingProvider":{"type":["string","null"],"description":"Provider responsible for grading the card"},"gradingScore":{"type":["string","null"],"description":"Score assigned to the card by the grading provider"},"gradingNumber":{"type":["string","null"],"description":"Certificate or registration number issued by the grading provider"},"createdAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was created"},"updatedAt":{"anyOf":[{"type":"string"},{"type":"string","format":"date-time"}],"description":"Timestamp when the listing was last updated"},"item":{"oneOf":[{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["card"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"rarity":{"type":"string"},"number":{"type":["string","null"]},"description":{"type":"string"},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"alternatives":{"type":"array","items":{"type":"string"}},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","rarity","set","series","images","alternatives","metadata"]},{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"type":{"type":"string","enum":["product"]},"game":{"type":"string","enum":["Pokemon"]},"title":{"type":"string"},"name":{"type":"string"},"classification":{"type":"string","enum":["CARD"]},"count":{"type":"number"},"description":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"urn":{"type":"string","pattern":"[^/]$"},"illustrator":{"type":"string"},"orientation":{"type":"string","enum":["portrait","landscape"]},"url":{"type":"string","format":"uri"}},"required":["urn","orientation","url"]}},"series":{"type":"object","properties":{"name":{"type":"string"},"urn":{"type":"string","pattern":"[^/]$"}},"required":["name","urn"]},"set":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"urn":{"type":"string","pattern":"[^/]$"},"counts":{"type":"object","properties":{"printed":{"type":"number"},"total":{"type":"number"}}},"symbol":{"type":"object","properties":{"url":{"type":"string"}},"required":["url"]},"released":{"type":"string"},"references":{"type":"array","items":{"type":"string"}}},"required":["name","urn","counts","references"]},"metadata":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}},{"type":"number"},{"type":"array","items":{"type":"number"}}]},"detail":{"anyOf":[{},{"type":"array","items":{}},{"type":"null"}]}},"required":["name"]}},"price":{"type":"integer"},"available":{"type":"integer","default":0,"description":"Total available for this listing"},"quantity":{"type":"integer","default":0,"description":"Total quantity available"},"min":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the cheapest listing in pence"}},"required":["price"]},"max":{"type":"object","properties":{"price":{"type":["integer","null"],"description":"Price of the most expensive listing in pence"}},"required":["price"]}},"required":["urn","type","game","title","name","classification","count","images","series","set","metadata"]}],"description":"Details of the item being listed"},"seller":{"allOf":[{"$ref":"#/components/schemas/UserSummary"},{"description":"The seller of the listing"}]}},"required":["id","sellerId","condition","price","language","createdAt","updatedAt","item","seller"],"description":"The latest listing data for the item"},"expires":{"type":"string","format":"date-time","description":"When the item hold expires"}},"required":["urn","price","condition","language","sellerId","classification","count","listing","expires"]}}}}}}}}},"/basket/{id}/summary":{"get":{"tags":["basket"],"operationId":"getBasketSummary","summary":"Get basket summary","description":"\nUse this when you only need quick totals, not the full item list.\n\nGreat for:\n- navbar basket badges\n- mini-cart totals\n- lightweight polling for basket changes\n\nWhy this exists:\n- It is cheaper than fetching every item row.\n- It gives you enough data to show \"how much is in the basket\" at a glance.\n","parameters":[{"schema":{"type":"string","description":"The ID of the basket to retrieve"},"required":true,"description":"The ID of the basket to retrieve","name":"id","in":"path"}],"responses":{"200":{"description":"The summary totals for the basket","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"integer","minimum":0,"description":"Total number of items in the basket or for a seller"},"cards":{"type":"integer","minimum":0,"description":"Total number of cards in the basket or for a seller"},"products":{"type":"integer","minimum":0,"description":"Total number of products in the basket or for a seller"},"subTotal":{"type":"integer","minimum":0,"description":"Total price of the items in pence in the basket or for a seller"},"sellers":{"type":"object","additionalProperties":{"type":"object","properties":{"items":{"type":"integer","minimum":0,"description":"Total number of items in the basket or for a seller"},"cards":{"type":"integer","minimum":0,"description":"Total number of cards in the basket or for a seller"},"products":{"type":"integer","minimum":0,"description":"Total number of products in the basket or for a seller"},"subTotal":{"type":"integer","minimum":0,"description":"Total price of the items in pence in the basket or for a seller"}},"required":["items","cards","products","subTotal"]}}},"required":["items","cards","products","subTotal","sellers"]}}}}}}},"/basket/{id}/info":{"get":{"tags":["basket"],"security":[{"Bearer":[]}],"operationId":"getBasketInformation","summary":"Get basket information","description":"\nThis is the \"full pricing breakdown\" endpoint.\n\nCall this right before checkout (or on a checkout review screen) when you need:\n- basket summary totals\n- platform/service fee\n- delivery costs calculated per seller\n\nWhat makes it useful:\n- Delivery is computed from each seller's delivery configuration.\n- You get one payload with the financial details needed to render final pricing.\n\nHeads up:\n- This endpoint requires an authenticated user.\n","parameters":[{"schema":{"type":"string","description":"The ID of the basket to retrieve"},"required":true,"description":"The ID of the basket to retrieve","name":"id","in":"path"}],"responses":{"200":{"description":"The information for the items contained in the basket","content":{"application/json":{"schema":{"type":"object","properties":{"fee":{"type":"number","description":"The service fee for the basket, calculated based on the total value of the items and the number of sellers"},"summary":{"type":"object","properties":{"items":{"type":"integer","minimum":0,"description":"Total number of items in the basket or for a seller"},"cards":{"type":"integer","minimum":0,"description":"Total number of cards in the basket or for a seller"},"products":{"type":"integer","minimum":0,"description":"Total number of products in the basket or for a seller"},"subTotal":{"type":"integer","minimum":0,"description":"Total price of the items in pence in the basket or for a seller"},"sellers":{"type":"object","additionalProperties":{"type":"object","properties":{"items":{"type":"integer","minimum":0,"description":"Total number of items in the basket or for a seller"},"cards":{"type":"integer","minimum":0,"description":"Total number of cards in the basket or for a seller"},"products":{"type":"integer","minimum":0,"description":"Total number of products in the basket or for a seller"},"subTotal":{"type":"integer","minimum":0,"description":"Total price of the items in pence in the basket or for a seller"}},"required":["items","cards","products","subTotal"]}}},"required":["items","cards","products","subTotal","sellers"]},"delivery":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["LARGE_LETTER"]},"quantity":{"type":"integer","minimum":0},"cost":{"type":"integer","minimum":0}},"required":["type","quantity","cost"]}}}},"required":["fee","summary","delivery"]}}}}}}},"/basket/{id}/checkout":{"post":{"tags":["basket"],"security":[{"Bearer":[]}],"operationId":"createBasketCheckoutSession","summary":"Create checkout session","description":"\nCreates a checkout session and returns the URL the client should redirect the user to.\n\nUse this as the final \"continue to payment\" step from basket/checkout pages.\n\nWhat this endpoint checks before creating a session:\n- listing availability and purchasability\n- seller authorization constraints\n- basket consistency at checkout time\n\nResponse behavior:\n- On success: returns a checkout URL.\n- On failure: returns listing-level validation errors for unavailable/invalid items.\n\nHeads up:\n- Requires authentication.\n","parameters":[{"schema":{"type":"string","description":"The ID of the basket to retrieve"},"required":true,"description":"The ID of the basket to retrieve","name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"successUrl":{"type":"string","format":"uri","description":"The URL to redirect to after a successful payment. A `?purchase=` query parameter will be appended to this URL containing the ID of the resulting purchase."}},"required":["successUrl"]}}}},"responses":{"200":{"description":"The response containing the checkout URL","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"The URL to redirect the user to for checkout"}},"required":["url"]}}}},"401":{"description":"The seller is not authorised to sell one or more items","content":{"application/json":{"schema":{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]}}}},"404":{"description":"A listing in the basket was not found","content":{"application/json":{"schema":{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]}}}},"409":{"description":"The listings in the response body are no longer available in their requested quantity","content":{"application/json":{"schema":{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]}}}},"500":{"description":"A listing in the basket was not found","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"listingIds":{"type":"array","items":{"type":"string"},"description":"The IDs of the listings that caused the error"}},"required":["listingIds"]},{},{"type":"null"}]}}}}}}}},"webhooks":{}}