{"openapi":"3.1.0","info":{"title":"BuyRecord API","description":"Verified purchase outcomes for products. Reading needs no key.","version":"0.1.0"},"paths":{"/v1/products/search":{"get":{"summary":"Search Products","description":"Products matching a name, GTIN or SKU, each with its outcome summary.","operationId":"search_products","parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":100,"title":"Query"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Category"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/products/compare":{"get":{"summary":"Compare Products","description":"Outcomes for 2 to 5 products, in the order given.","operationId":"compare_products","parameters":[{"name":"ids","in":"query","required":true,"schema":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":2,"maxItems":5,"title":"Ids"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Comparison"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/products/{product_id}/outcomes":{"get":{"summary":"Get Product Outcomes","description":"Score, sample size, outcome breakdown and top return reasons for one product.","operationId":"get_product_outcomes","parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductOutcomes"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/merchants/{shop_domain}":{"get":{"summary":"Get Merchant Profile","description":"Return rate, complaint rate and delivery issue rate across a merchant's products.","operationId":"get_merchant_profile","parameters":[{"name":"shop_domain","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9.-]{1,253}$","title":"Shop Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantProfile"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/outcomes":{"post":{"summary":"Submit Outcome","description":"Record a purchase outcome for a product (product_id or product_url). Requires an API key.\n\nProofs: shopify_order (shop domain, order number, confirmation number) is checked against the\nshop's order record; email_receipt (the merchant's original DKIM-signed confirmation email,\norder number, product name) is checked by its signature. Both count when they match.\npayment_receipt is stored as quarantined.","operationId":"submit_outcome","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutcomeSubmission"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/keys":{"post":{"summary":"Create Api Key","description":"Issue an API key for writing, instantly. Starter limits; a few keys per requester per day.","operationId":"create_api_key","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedKey"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Comparison":{"properties":{"products":{"items":{"$ref":"#/components/schemas/ProductOutcomes"},"type":"array","title":"Products"}},"type":"object","required":["products"],"title":"Comparison"},"EmailReceiptProof":{"properties":{"type":{"type":"string","const":"email_receipt","title":"Type"},"raw_email_base64":{"type":"string","maxLength":2800000,"title":"Raw Email Base64","description":"The merchant's original order confirmation email (.eml, RFC 5322), base64-encoded. Its DKIM signature is verified; the email is processed in memory and never stored."},"order_number":{"type":"string","maxLength":60,"minLength":1,"title":"Order Number","description":"Order number as it appears in the email."},"product_name":{"type":"string","maxLength":200,"minLength":3,"title":"Product Name","description":"Product name exactly as it appears in the email."}},"type":"object","required":["type","raw_email_base64","order_number","product_name"],"title":"EmailReceiptProof"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IssuedKey":{"properties":{"key":{"type":"string","title":"Key","description":"Shown once. Send it as 'Authorization: Bearer <key>'."},"prefix":{"type":"string","title":"Prefix"},"reads_per_minute":{"type":"integer","title":"Reads Per Minute"},"writes_per_minute":{"type":"integer","title":"Writes Per Minute"}},"type":"object","required":["key","prefix","reads_per_minute","writes_per_minute"],"title":"IssuedKey"},"KeyRequest":{"properties":{"label":{"type":"string","maxLength":80,"minLength":3,"pattern":"^[A-Za-z0-9][A-Za-z0-9 ._()-]*$","title":"Label","description":"Name of the agent or project using the key, e.g. 'Acme shopping agent'."}},"type":"object","required":["label"],"title":"KeyRequest"},"MerchantProfile":{"properties":{"shop_domain":{"type":"string","title":"Shop Domain"},"product_count":{"type":"integer","title":"Product Count"},"sample_size":{"type":"integer","title":"Sample Size"},"min_sample":{"type":"integer","title":"Min Sample"},"return_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Return Rate"},"complaint_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Complaint Rate"},"delivery_issue_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delivery Issue Rate","description":"Share of outcomes citing late_delivery or damaged."},"top_reasons":{"items":{"type":"string","enum":["size","quality","not_as_described","late_delivery","damaged","other"]},"type":"array","title":"Top Reasons"},"last_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Synced At"}},"type":"object","required":["shop_domain","product_count","sample_size","min_sample","return_rate","complaint_rate","delivery_issue_rate","top_reasons","last_synced_at"],"title":"MerchantProfile"},"OutcomeSubmission":{"properties":{"product_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Product Id","description":"BuyRecord product id. Either this or product_url."},"product_url":{"anyOf":[{"type":"string","maxLength":500,"pattern":"^https://"},{"type":"null"}],"title":"Product Url","description":"The product page URL at the store. Either this or product_id."},"outcome":{"type":"string","enum":["kept_silent","kept_positive","complained","returned"],"title":"Outcome"},"reasons":{"items":{"type":"string","enum":["size","quality","not_as_described","late_delivery","damaged","other"]},"type":"array","maxItems":6,"title":"Reasons"},"proof":{"oneOf":[{"$ref":"#/components/schemas/PaymentReceiptProof"},{"$ref":"#/components/schemas/ShopifyOrderProof"},{"$ref":"#/components/schemas/EmailReceiptProof"}],"title":"Proof","discriminator":{"propertyName":"type","mapping":{"email_receipt":"#/components/schemas/EmailReceiptProof","payment_receipt":"#/components/schemas/PaymentReceiptProof","shopify_order":"#/components/schemas/ShopifyOrderProof"}}}},"type":"object","required":["outcome","proof"],"title":"OutcomeSubmission"},"OutcomeSummary":{"properties":{"score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Score","description":"0 to 100. Null when sample_size is below min_sample."},"sample_size":{"type":"integer","title":"Sample Size"},"min_sample":{"type":"integer","title":"Min Sample"},"top_reasons":{"items":{"type":"string","enum":["size","quality","not_as_described","late_delivery","damaged","other"]},"type":"array","title":"Top Reasons"}},"type":"object","required":["score","sample_size","min_sample","top_reasons"],"title":"OutcomeSummary"},"PaymentReceiptProof":{"properties":{"type":{"type":"string","const":"payment_receipt","title":"Type"},"reference":{"type":"string","maxLength":200,"minLength":4,"title":"Reference","description":"Receipt or transaction reference. Hashed on arrival, never stored."},"purchased_on":{"type":"string","format":"date","title":"Purchased On"}},"type":"object","required":["type","reference","purchased_on"],"title":"PaymentReceiptProof"},"Product":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"title":{"type":"string","title":"Title","description":"Product name as published by the merchant, cleaned and capped at 200 characters."},"gtin":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gtin"},"url":{"type":"string","title":"Url"},"category":{"type":"string","title":"Category"},"price_band":{"type":"string","enum":["under_30","30_50","50_100","100_150","over_150","unknown"],"title":"Price Band"},"shop_domain":{"type":"string","title":"Shop Domain"},"outcomes":{"$ref":"#/components/schemas/OutcomeSummary"}},"type":"object","required":["id","title","gtin","url","category","price_band","shop_domain","outcomes"],"title":"Product"},"ProductOutcomes":{"properties":{"product_id":{"type":"string","format":"uuid","title":"Product Id"},"title":{"type":"string","title":"Title","description":"Product name as published by the merchant, cleaned and capped at 200 characters."},"url":{"type":"string","title":"Url"},"score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Score","description":"0 to 100. Null when sample_size is below min_sample."},"sample_size":{"type":"integer","title":"Sample Size"},"min_sample":{"type":"integer","title":"Min Sample"},"breakdown":{"additionalProperties":{"type":"integer"},"propertyNames":{"enum":["kept_silent","kept_positive","complained","returned"]},"type":"object","title":"Breakdown"},"top_reasons":{"items":{"type":"string","enum":["size","quality","not_as_described","late_delivery","damaged","other"]},"type":"array","title":"Top Reasons"},"computed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Computed At"}},"type":"object","required":["product_id","title","url","score","sample_size","min_sample","breakdown","top_reasons","computed_at"],"title":"ProductOutcomes"},"SearchResult":{"properties":{"products":{"items":{"$ref":"#/components/schemas/Product"},"type":"array","title":"Products"}},"type":"object","required":["products"],"title":"SearchResult"},"ShopifyOrderProof":{"properties":{"type":{"type":"string","const":"shopify_order","title":"Type"},"shop_domain":{"type":"string","pattern":"^[A-Za-z0-9][A-Za-z0-9.-]{1,253}$","title":"Shop Domain","description":"The store's domain, e.g. brand.com or brand.myshopify.com."},"order_number":{"type":"string","pattern":"^#?[A-Za-z0-9-]{1,40}$","title":"Order Number","description":"Order number as shown to the buyer, e.g. #1001. Never stored."},"confirmation_number":{"type":"string","pattern":"^[A-Za-z0-9]{6,20}$","title":"Confirmation Number","description":"Order confirmation number from the order confirmation, e.g. XPLZ3K9HG. Never stored."}},"type":"object","required":["type","shop_domain","order_number","confirmation_number"],"title":"ShopifyOrderProof"},"SubmissionResult":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","enum":["accepted","quarantined"],"title":"Status"},"status_reason":{"type":"string","enum":["verified","proof_not_verifiable","pending_merchant_verification"],"title":"Status Reason"}},"type":"object","required":["id","status","status_reason"],"title":"SubmissionResult"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","description":"API key (br_live_...). Required for writing.","scheme":"bearer"}}}}