{"openapi":"3.1.0","info":{"title":"PriceHub API","version":"1.0.0","description":"Reference prices of brands, delivered to connected sites with each site's own pricing rules.\n\nAuthenticate with `Authorization: Bearer phk_<prefix>_<secret>`. Scopes: `read` (catalog and prices), `site` (endpoints under /v1/sites/me, key must belong to a site), `brand:write` (brand price lists).\n\nSync model for plugins: 1) PUT /v1/sites/me/mappings; 2) full snapshot with GET /v1/sites/me/final-prices (no since_seq) page by page, remembering snapshot_seq from the FIRST page; 3) then poll GET /v1/sites/me/final-prices?since_seq=<last seq> until has_more is false (a page can be empty while has_more is true); on 410 resync_required go back to step 2; 4) POST /v1/sites/me/sync-report. When rules_version changes, take a full snapshot again.\n\nPrices are in Toman (IRT) unless `currency` says otherwise. Responses over 1 KB are gzipped when the client accepts it."},"servers":[{"url":"/"}],"security":[{"apiKey":[]}],"paths":{"/v1/health":{"get":{"summary":"Service health","security":[],"responses":{"200":{"description":"OK"}}}},"/v1/openapi.json":{"get":{"summary":"This document","security":[],"responses":{"200":{"description":"OK"}}}},"/v1/brands":{"get":{"summary":"Active brands and the price types visible to you","parameters":[{"name":"cursor","in":"query","required":false,"description":"From next_cursor","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"1–500, default 100","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Brand"}},"next_cursor":{"type":["integer","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/products":{"get":{"summary":"Catalog with variants and media","parameters":[{"name":"brand","in":"query","required":false,"description":"Brand slug","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Category slug","schema":{"type":"string"}},{"name":"updated_since","in":"query","required":false,"description":"ISO date-time","schema":{"type":"string","format":"date-time"}},{"name":"cursor","in":"query","required":false,"description":"From next_cursor","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"1–1000, default 100","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}},"next_cursor":{"type":["integer","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/products/{id}":{"get":{"summary":"One product","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Product"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/prices":{"get":{"summary":"Current prices of one brand","parameters":[{"name":"brand","in":"query","required":true,"description":"Brand slug","schema":{"type":"string"}},{"name":"type","in":"query","required":false,"description":"Price type code, e.g. retail","schema":{"type":"string"}},{"name":"cursor","in":"query","required":false,"description":"From next_cursor, e.g. \"120.3\"","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–5000, default 1000","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Price"}},"next_cursor":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/prices/changes":{"get":{"summary":"Change feed: every price change after since_seq, in order","description":"Site keys only see brands the site follows. Each request scans a bounded window of the feed, so data can be empty while has_more is true: keep calling with next_seq until has_more is false. 410 resync_required means since_seq is older than the kept history.","parameters":[{"name":"since_seq","in":"query","required":false,"description":"Last seq you processed (0 for everything)","schema":{"type":"integer"}},{"name":"brand","in":"query","required":false,"description":"Limit to one brand","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–10000, default 1000","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Change"}},"next_seq":{"type":"integer"},"has_more":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"410":{"$ref":"#/components/responses/Gone"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/sites/me":{"get":{"summary":"Your site: followed brands, mapped products, last synced seq","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Site"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/sites/me/brands":{"put":{"summary":"Replace the brands your site follows","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["brands"],"properties":{"brands":{"type":"array","items":{"type":"string"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}},"description":"Mapping a product follows its brand automatically. Unfollowing a brand that still has mapped products returns 409 brand_has_mappings."}},"/v1/sites/me/mappings":{"get":{"summary":"Your product mappings","parameters":[{"name":"cursor","in":"query","required":false,"description":"From next_cursor","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"1–5000","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Mapping"}},"next_cursor":{"type":["integer","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}},"put":{"summary":"Map your products to ours (bulk, up to 50,000)","description":"Matching order: variant_id, then barcode, then sku (add brand when a code exists in several brands). An external product maps to one variant and vice versa; the last item wins and the others are reported.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/MappingIn"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"matched":{"type":"integer"},"unmatched":{"type":"array","items":{"type":"object","properties":{"external_id":{"type":"string"},"reason":{"type":"string"}}}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/sites/me/rules":{"get":{"summary":"Your pricing rules","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Rule"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}},"put":{"summary":"Replace all pricing rules (validated; nothing is saved if one is invalid)","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["rules"],"properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/Rule"}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/sites/me/rules/preview":{"post":{"summary":"What rules would do, without saving","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rules":{"type":"array","items":{"$ref":"#/components/schemas/Rule"},"description":"Omit to preview the stored rules"},"current_prices":{"type":"object","additionalProperties":{"type":"number"},"description":"Your current prices by external_id, for direction counts and the max-change guard"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"summary":{"type":"object"},"sample":{"type":"array","items":{"$ref":"#/components/schemas/FinalPrice"}}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/sites/me/final-prices":{"get":{"summary":"Final prices for your mapped products","parameters":[{"name":"since_seq","in":"query","required":false,"description":"Incremental mode: changes after this seq. Omit for a full snapshot.","schema":{"type":"integer"}},{"name":"cursor","in":"query","required":false,"description":"Full snapshot paging, from next_cursor","schema":{"type":"integer"}},{"name":"limit","in":"query","required":false,"description":"1–5000, default 1000","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FinalPrice"}},"snapshot_seq":{"type":"integer","description":"Full mode: continue incrementally from this seq (take it from the first page)"},"next_cursor":{"type":["integer","null"]},"next_seq":{"type":"integer"},"has_more":{"type":"boolean"},"rules_version":{"type":["string","null"]}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"410":{"$ref":"#/components/responses/Gone"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}},"description":"Incremental mode returns only your mapped products whose reference price changed. data can be empty while has_more is true; keep calling with next_seq. 410 resync_required: take a full snapshot."}},"/v1/sites/me/sync-report":{"post":{"summary":"Report what you applied; advances your last_seq","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["to_seq"],"properties":{"from_seq":{"type":"integer"},"to_seq":{"type":"integer"},"applied":{"type":"integer"},"failed":{"type":"array","items":{"type":"object","properties":{"external_id":{"type":"string"},"error":{"type":"string"}}}}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/brand/price-lists":{"get":{"summary":"Your price list versions","parameters":[{"name":"brand","in":"query","required":true,"description":"Brand slug","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1–500","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}},"post":{"summary":"Send a price list (brand systems)","description":"Up to 100,000 items per request. Larger lists: create a draft with the first 100,000 (publish omitted), add the rest with POST /v1/brand/price-lists/{version}/items, check GET .../{version}/diff, then POST .../{version}/publish. The comparison with published prices runs in the database. Suspicious changes (over anomaly_percent, or a likely missing/extra zero) block publishing with 409 unless accept_anomalies=true. Codes not in the catalog are skipped and reported.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["brand","items"],"properties":{"brand":{"type":"string"},"items":{"type":"array","items":{"$ref":"#/components/schemas/PriceListItem"},"maxItems":100000},"publish":{"type":"boolean"},"missing":{"enum":["keep","out_of_stock"]},"accept_anomalies":{"type":"boolean"},"anomaly_percent":{"type":"number","default":40}}}}}},"responses":{"201":{"description":"Saved (and published when asked)"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/brand/price-lists/{version}/publish":{"post":{"summary":"Publish a saved draft","parameters":[{"name":"version","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["brand"],"properties":{"brand":{"type":"string"},"missing":{"enum":["keep","out_of_stock"]},"accept_anomalies":{"type":"boolean"},"anomaly_percent":{"type":"number","default":40}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/sites/me/mappings/delete":{"post":{"summary":"Remove product mappings by external_id or for a whole brand","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"external_ids":{"type":"array","items":{"type":"string"},"maxItems":50000},"brand":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"deleted":{"type":"integer"}}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/brand/price-lists/{version}/items":{"post":{"summary":"Add items to a draft list (up to 100,000 per request; a repeated sku replaces the earlier one)","parameters":[{"name":"version","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["brand","items"],"properties":{"brand":{"type":"string"},"items":{"type":"array","maxItems":100000,"items":{"$ref":"#/components/schemas/PriceListItem"}}}}}}},"responses":{"200":{"description":"Staged"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/brand/price-lists/{version}/diff":{"get":{"summary":"Compare a list with what is published (summary and the most suspicious changes)","parameters":[{"name":"version","in":"path","required":true,"schema":{"type":"integer"}},{"name":"brand","in":"query","required":true,"schema":{"type":"string"}},{"name":"anomaly_percent","in":"query","schema":{"type":"number","default":40}}],"responses":{"200":{"description":"OK"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"503":{"$ref":"#/components/responses/ModuleDisabled"}}}},"/v1/price-index":{"get":{"summary":"Daily price index (100 = first day), for the market or one brand","tags":["analytics"],"responses":{"200":{"description":"OK"}},"description":"?brand=slug, ?days=90. value moves by the mean log change of every priced product (default public price), so a few big moves shift it a little; changed/up/down count the products that moved."}},"/v1/orgs/{org}/brands/{brand}/stats":{"get":{"summary":"A brand’s own numbers: views, downloads, publishes, connected sites","tags":["analytics"],"responses":{"200":{"description":"OK"}},"description":"?days=30","security":[{"session":[]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}},{"name":"brand","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/plans":{"get":{"summary":"Plans for sites and brands, with limits and prices (Toman)","tags":["billing"],"responses":{"200":{"description":"OK"}},"description":"?audience=site|brand","security":[]}},"/v1/account/plan":{"get":{"summary":"The plan and limits of the API key owner","tags":["billing"],"responses":{"200":{"description":"OK"}},"description":"Limits the API enforces with 402 plan_limit: brands, products, webhooks (sites); products, api_upload (brands)."}},"/v1/orgs/{org}/billing":{"get":{"summary":"Plan, subscription and invoices of an organization","tags":["billing"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/billing/quote":{"post":{"summary":"Price for a plan and period, with VAT and discount","tags":["billing"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"},"period":{"type":"string"},"discount_code":{"type":"string"}},"required":["plan"]}}}},"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/billing/checkout":{"post":{"summary":"Create the invoice to pay","tags":["billing"],"responses":{"200":{"description":"OK"}},"description":"Then pay it with POST /v1/payments/start.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"},"period":{"type":"string"},"discount_code":{"type":"string"}},"required":["plan"]}}}},"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/billing/trial":{"post":{"summary":"Start the free trial of a plan (once)","tags":["billing"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"}},"required":["plan"]}}}},"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/billing/cancel":{"post":{"summary":"Do not renew (or undo)","tags":["billing"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"undo":{"type":"boolean"}}}}}},"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/dealer-access":{"get":{"summary":"Dealer price requests your organization sent","tags":["dealer-access"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}}]},"post":{"summary":"Ask a brand to see its dealer prices","tags":["dealer-access"],"responses":{"200":{"description":"OK"}},"description":"Needs a plan with dealer_prices. Once approved, the dealer price types of that brand appear for every API key of the organization.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"brand":{"type":"string"},"message":{"type":"string"}},"required":["brand"]}}}},"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/brands/{brand}/dealer-requests":{"get":{"summary":"Requests your brand received","tags":["dealer-access"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}},{"name":"brand","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/brands/{brand}/dealer-requests/{dealer}/decide":{"post":{"summary":"Approve or reject","tags":["dealer-access"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"approve":{"type":"boolean"},"note":{"type":"string"}},"required":["approve"]}}}},"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}},{"name":"brand","in":"path","required":true,"schema":{"type":"string"}},{"name":"dealer","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/orgs/{org}/brands/{brand}/dealer-requests/{dealer}/revoke":{"post":{"summary":"Take an approval back","tags":["dealer-access"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"org","in":"path","required":true,"schema":{"type":"string"}},{"name":"brand","in":"path","required":true,"schema":{"type":"string"}},{"name":"dealer","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/brand/extract":{"post":{"summary":"Read a price list from text, a PDF or an image (preview, nothing stored)","tags":["extraction"],"responses":{"200":{"description":"OK"}},"description":"Returns rows (code, name, prices, stock, confidence), lines that were skipped, warnings and a CSV to upload with the regular import, where it is diffed, checked for anomalies and published as usual. Images and scanned PDFs need an OCR service configured on the platform.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"content_base64":{"type":"string"},"mime":{"type":"string"},"price_names":{"type":"array","items":{"type":"string"}}}}}}}}},"/v1/fx":{"get":{"summary":"Latest exchange rates (Toman per unit)","tags":["fx"],"responses":{"200":{"description":"OK"}},"description":"Prices set in a foreign currency are converted with these. When a rate changes, sites with currency-based rules see rules_version change and should take a full snapshot."}},"/v1/fx/{currency}":{"get":{"summary":"Rate history","tags":["fx"],"responses":{"200":{"description":"OK"}},"description":"?days=30 (up to 365)","parameters":[{"name":"currency","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/auth/otp":{"post":{"summary":"Send a sign-in code by SMS or email","tags":["auth"],"responses":{"200":{"description":"OK"}},"description":"to: mobile (09..., +98...) or email. One code a minute and five an hour per number, twenty an hour per IP; 429 carries Retry-After. The answer is the same whether or not an account exists.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string"}},"required":["to"]}}}}}},"/v1/auth/otp/verify":{"post":{"summary":"Sign in with the code (creates the account on first use)","tags":["auth"],"responses":{"200":{"description":"OK"}},"description":"Answers a session token, or two_factor_required with a challenge for /v1/auth/2fa.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string"},"code":{"type":"string"}},"required":["to","code"]}}}}}},"/v1/auth/password":{"post":{"summary":"Sign in with a password","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"to":{"type":"string"},"password":{"type":"string"}},"required":["to","password"]}}}}}},"/v1/auth/2fa":{"post":{"summary":"Second step: authenticator or recovery code","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"challenge":{"type":"string"},"code":{"type":"string"}},"required":["challenge","code"]}}}}}},"/v1/auth/me":{"get":{"summary":"The signed-in user and their organizations","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]},"post":{"summary":"Update profile","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"full_name":{"type":"string"}}}}}}}},"/v1/auth/sessions":{"get":{"summary":"Signed-in devices","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]}},"/v1/auth/logout":{"post":{"summary":"Sign out this session","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]}},"/v1/auth/logout-all":{"post":{"summary":"Sign out every other session","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]}},"/v1/auth/password/set":{"post":{"summary":"Set or change the password (ends other sessions)","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string"},"current_password":{"type":"string"}},"required":["password"]}}}}}},"/v1/auth/2fa/setup":{"post":{"summary":"Start two-factor setup: a secret and otpauth:// link to scan","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]}},"/v1/auth/2fa/enable":{"post":{"summary":"Confirm with a first code; returns ten recovery codes once","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"}},"required":["code"]}}}}}},"/v1/auth/2fa/disable":{"post":{"summary":"Switch two-factor off with a code or recovery code","tags":["auth"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"}},"required":["code"]}}}}}},"/v1/me/notifications":{"get":{"summary":"Your notifications, newest first","tags":["notifications"],"responses":{"200":{"description":"OK"}},"description":"?unread=1, ?before_id= for the next page, ?limit= up to 100.","security":[{"session":[]}]}},"/v1/me/notifications/count":{"get":{"summary":"Unread count","tags":["notifications"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]}},"/v1/me/notifications/{id}/read":{"post":{"summary":"Mark one read","tags":["notifications"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/me/notifications/read-all":{"post":{"summary":"Mark all read","tags":["notifications"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]}},"/v1/me/notification-prefs":{"get":{"summary":"Channels per kind, quiet hours, linked bot chats","tags":["notifications"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]},"put":{"summary":"Choose channels per kind and quiet hours (Tehran time)","tags":["notifications"],"responses":{"200":{"description":"OK"}},"description":"kinds: {\"price_alert\": [\"inapp\",\"sms\"]}; channels: inapp, sms, email, telegram, bale (inapp is always on). quiet: {\"from\": 23, \"to\": 7}; SMS and bot messages wait until it ends, email does not.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kinds":{"type":"object"},"quiet":{"type":"object"}}}}}}}},"/v1/me/notification-channels/link":{"post":{"summary":"A one-time code to link a Telegram or Bale chat","tags":["notifications"],"responses":{"200":{"description":"OK"}},"description":"Send /start <code> to the bot within 15 minutes.","security":[{"session":[]}]}},"/v1/me/notification-channels/{channel}/unlink":{"post":{"summary":"Unlink a bot chat","tags":["notifications"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"channel","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/bots/{channel}/{secret}":{"post":{"summary":"Bot API webhook (Telegram, Bale)","tags":["notifications"],"responses":{"200":{"description":"OK"}},"security":[],"parameters":[{"name":"channel","in":"path","required":true,"schema":{"type":"string"}},{"name":"secret","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/payments/start":{"post":{"summary":"Pay an invoice: returns the bank page to send the payer to","tags":["payments"],"responses":{"200":{"description":"OK"}},"description":"The amount comes from the invoice. After paying, the bank returns the payer to /v1/payments/callback/<gateway>, which verifies the payment with the bank and activates the plan, then redirects to PUBLIC_URL/account/billing.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invoice_id":{"type":"integer"}},"required":["invoice_id"]}}}}}},"/v1/payments/callback/{gateway}":{"get":{"summary":"Return from the bank (verifies and activates)","tags":["payments"],"responses":{"200":{"description":"OK"}},"security":[],"parameters":[{"name":"gateway","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/payments/fake/{authority}":{"get":{"summary":"Development bank page (only with PAYMENT_GATEWAY=fake)","tags":["payments"],"responses":{"200":{"description":"OK"}},"security":[],"parameters":[{"name":"authority","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/search":{"get":{"summary":"Search products by name, model, code or barcode","tags":["search"],"responses":{"200":{"description":"OK"}},"description":"q (typos tolerated; Persian/Arabic letters and digits are unified), brand, category, in_stock=1, min_price, max_price, sort=relevance|price_asc|price_desc, limit, offset. min_price is the lowest public price."}},"/v1/search/suggest":{"get":{"summary":"Name suggestions while typing","tags":["search"],"responses":{"200":{"description":"OK"}},"description":"?q="}},"/v1/me/tickets":{"get":{"summary":"Your tickets","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]},"post":{"summary":"Open a ticket","tags":["support"],"responses":{"200":{"description":"OK"}},"description":"category: technical, billing, content, other. priority: low, normal, high.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"subject":{"type":"string"},"body":{"type":"string"},"category":{"type":"string"},"priority":{"type":"string"},"organization_id":{"type":"integer"},"attachments":{"type":"array","items":{"type":"string"}}},"required":["subject","body"]}}}}}},"/v1/me/tickets/{id}":{"get":{"summary":"A ticket and its messages","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/me/tickets/{id}/reply":{"post":{"summary":"Reply (reopens a closed ticket)","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string"},"attachments":{"type":"array","items":{"type":"string"}}},"required":["body"]}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/me/tickets/{id}/close":{"post":{"summary":"Close","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/staff/tickets":{"get":{"summary":"Support queue (staff)","tags":["support"],"responses":{"200":{"description":"OK"}},"description":"?status=open|waiting_customer|waiting_support|closed","security":[{"session":[]}]}},"/v1/staff/tickets/{id}":{"get":{"summary":"A ticket with internal notes (staff)","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/staff/tickets/{id}/reply":{"post":{"summary":"Reply or add an internal note (staff)","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string"},"internal":{"type":"boolean"}},"required":["body"]}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/staff/tickets/{id}/triage":{"post":{"summary":"Priority, category, assignee (staff)","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"priority":{"type":"string"},"category":{"type":"string"},"assignee_id":{"type":"integer"}}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/staff/tickets/{id}/close":{"post":{"summary":"Close (staff)","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/help":{"get":{"summary":"Help center articles","tags":["support"],"responses":{"200":{"description":"OK"}},"description":"?category=, ?audience=brand|site|developer, ?q= search","security":[]}},"/v1/help/{slug}":{"get":{"summary":"One article (Markdown body)","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[],"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/staff/help/{slug}":{"put":{"summary":"Create or edit an article (staff)","tags":["support"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"category":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"audience":{"type":"string"},"summary":{"type":"string"},"video_url":{"type":"string"},"sort":{"type":"integer"},"published":{"type":"boolean"}},"required":["category","title","body"]}}}},"parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/me/watchlist":{"get":{"summary":"Followed products (with current public prices) and brands","tags":["watchlist"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]},"post":{"summary":"Follow a product (variant_id) or a whole brand (brand slug)","tags":["watchlist"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"variant_id":{"type":"integer"},"brand":{"type":"string"}}}}}}}},"/v1/me/watchlist/remove":{"post":{"summary":"Stop following","tags":["watchlist"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"variant_id":{"type":"integer"},"brand":{"type":"string"}}}}}}}},"/v1/me/alerts":{"get":{"summary":"Your price alerts","tags":["watchlist"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}]},"post":{"summary":"Create a price alert","tags":["watchlist"],"responses":{"200":{"description":"OK"}},"description":"condition: any_change, below, above (with threshold in Toman), back_in_stock. below/above fire when the price crosses the threshold, not again while it stays past it. price_type: a public price type code of the brand; its default when omitted.","security":[{"session":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"variant_id":{"type":"integer"},"condition":{"type":"string"},"price_type":{"type":"string"},"threshold":{"type":"number"}},"required":["variant_id","condition"]}}}}}},"/v1/me/alerts/{id}/delete":{"post":{"summary":"Delete an alert","tags":["watchlist"],"responses":{"200":{"description":"OK"}},"security":[{"session":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}]}},"/v1/sites/me/webhooks":{"get":{"summary":"Your webhooks","tags":["webhooks"],"responses":{"200":{"description":"OK"}}},"post":{"summary":"Add a webhook (the signing secret is returned once)","tags":["webhooks"],"description":"Types: prices.changed (a followed brand published prices; pull them with final-prices), mapping.needs_review. Every delivery carries X-PriceHub-Signature: t=<unix>,v1=<hex HMAC-SHA256 of \"<t>.<body>\" with the secret>. Reject timestamps older than 5 minutes. The id in the body is stable across retries: use it to ignore duplicates. Answer 2xx within 10 s; failures are retried with backoff for about a day, and a webhook failing 50 times in a row is switched off. URLs must be https and resolve to public addresses.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"enum":["prices.changed","mapping.needs_review"]}}}}}}},"responses":{"201":{"description":"Created; includes secret"},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/v1/sites/me/webhooks/{id}/delete":{"post":{"summary":"Remove a webhook","tags":["webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"}}}},"/v1/sites/me/webhooks/{id}/enable":{"post":{"summary":"Switch a webhook back on after fixing the endpoint","tags":["webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"}}}},"/v1/sites/me/webhooks/{id}/test":{"post":{"summary":"Queue a test delivery (type ping)","tags":["webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Queued"}}}},"/v1/sites/me/webhooks/{id}/deliveries":{"get":{"summary":"Recent deliveries with status and errors","tags":["webhooks"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"OK"}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"phk_<prefix>_<secret>"}},"responses":{"BadRequest":{"description":"Invalid input; details lists every problem","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing, malformed, unknown or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Key lacks the scope or the resource is not yours","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Too many requests; see Retry-After","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ModuleDisabled":{"description":"The module behind this endpoint is switched off","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Suspicious changes or wrong list state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Gone":{"description":"since_seq is older than the kept change feed; take a full snapshot","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}}}},"Brand":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name_fa":{"type":"string"},"name_en":{"type":["string","null"]},"is_official":{"type":"boolean"},"last_published_at":{"type":["string","null"],"format":"date-time"},"price_types":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name_fa":{"type":"string"},"visibility":{"enum":["public","dealer","private"]}}}}}},"Product":{"type":"object","properties":{"id":{"type":"integer"},"brand":{"type":"string"},"category":{"type":["string","null"]},"model":{"type":["string","null"]},"name_fa":{"type":"string"},"slug":{"type":"string"},"specs":{"type":"object"},"status":{"type":"string"},"variants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"sku":{"type":"string"},"barcode":{"type":["string","null"]},"attributes":{"type":"object"}}}},"media":{"type":"array","items":{"type":"object"}}}},"Price":{"type":"object","properties":{"variant_id":{"type":"integer"},"sku":{"type":"string"},"price_type":{"type":"string"},"amount":{"type":["number","null"],"description":"null = no price given (call for price)"},"currency":{"type":"string"},"fx_amount":{"type":["number","null"]},"fx_currency":{"type":["string","null"]},"in_stock":{"type":"boolean"},"seq":{"type":"integer"},"updated_at":{"type":"string","format":"date-time"}}},"Change":{"type":"object","properties":{"seq":{"type":"integer"},"brand":{"type":"string"},"variant_id":{"type":"integer"},"sku":{"type":"string"},"price_type":{"type":"string"},"change_kind":{"enum":["new","price","stock","removed"]},"old_amount":{"type":["number","null"]},"amount":{"type":["number","null"],"description":"current value"},"in_stock":{"type":"boolean"}}},"Site":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string"},"platform":{"type":"string"},"brands":{"type":"array","items":{"type":"string"}},"mapped_products":{"type":"integer"},"rules":{"type":"integer"},"last_seq":{"type":"integer"},"latest_seq":{"type":"integer"}}},"MappingIn":{"type":"object","required":["external_id"],"properties":{"external_id":{"type":"string","description":"Product or variation id in your store"},"external_sku":{"type":"string"},"variant_id":{"type":"integer"},"barcode":{"type":"string"},"sku":{"type":"string"},"brand":{"type":"string"},"locked":{"type":"boolean","description":"Never change this product's price"}}},"Mapping":{"type":"object","properties":{"variant_id":{"type":"integer"},"sku":{"type":"string"},"brand":{"type":"string"},"external_id":{"type":"string"},"method":{"enum":["barcode","sku","model","fuzzy","manual"]},"locked":{"type":"boolean"}}},"Rule":{"type":"object","required":["name","priority","scope"],"description":"First enabled rule (lowest priority) whose scope matches a product wins.","properties":{"name":{"type":"string"},"priority":{"type":"integer"},"enabled":{"type":"boolean"},"action":{"enum":["price","skip"]},"scope":{"type":"object","properties":{"all":{"type":"boolean"},"brands":{"type":"array","items":{"type":["string","integer"]},"description":"slugs or ids"},"categories":{"type":"array","items":{"type":"integer"}},"variants":{"type":"array","items":{"type":"integer"}},"skus":{"type":"array","items":{"type":"string"}},"excludeVariants":{"type":"array","items":{"type":"integer"}},"priceRange":{"type":"object","properties":{"min":{"type":"number"},"max":{"type":"number"},"priceType":{"type":"string"}}},"inStockOnly":{"type":"boolean"}}},"base":{"oneOf":[{"type":"object","properties":{"priceType":{"type":"string"}}},{"type":"object","properties":{"fx":{"type":"object","properties":{"priceType":{"type":"string"}}}}}]},"adjust":{"type":"array","items":{"type":"object","properties":{"type":{"enum":["percent","fixed","multiply","set"]},"value":{"type":"number"}}}},"sale":{"type":"object","properties":{"type":{"enum":["percent","fixed"]},"value":{"type":"number"},"startsAt":{"type":"string","format":"date-time"},"endsAt":{"type":"string","format":"date-time"}}},"rounding":{"type":"object","properties":{"step":{"type":"number"},"mode":{"enum":["nearest","up","down"]},"endWith":{"type":"number"}}},"guards":{"type":"object","properties":{"minPrice":{"type":"number"},"maxPrice":{"type":"number"},"maxChangePercent":{"type":"number"}}},"syncStock":{"type":"boolean","default":true}}},"FinalPrice":{"type":"object","properties":{"external_id":{"type":"string"},"variant_id":{"type":"integer"},"sku":{"type":"string"},"status":{"enum":["ok","needs_approval","skipped","no_rule","no_base_price"],"description":"Apply only \"ok\"; hold \"needs_approval\" for a person"},"regular_price":{"type":["number","null"]},"sale_price":{"type":["number","null"]},"sale_starts_at":{"type":"string"},"sale_ends_at":{"type":"string"},"in_stock":{"type":"boolean","description":"absent = do not change stock"},"rule_id":{"type":["integer","string","null"]},"notes":{"type":"array","items":{"type":"string"}}}},"PriceListItem":{"type":"object","required":["sku"],"properties":{"sku":{"type":"string"},"prices":{"type":"object","additionalProperties":{"type":["number","null"]},"description":"by price type code"},"fx_prices":{"type":"object","additionalProperties":{"type":["object","null"],"properties":{"amount":{"type":"number"},"currency":{"type":"string"}}}},"in_stock":{"type":"boolean"}}}}}}