{"openapi":"3.1.0","info":{"title":"URSY Wine Marketplace API","version":"1.0.0","description":"The storefront and API share canonical records. Monetary *_minor values are integer GBP pence. Demo stock cannot be purchased. Public reads permit anonymous access; a supplied Bearer key is always scope checked. BrowserNonce requires a signed-in URSY.ID cookie session plus X-WP-Nonce. Keys cannot administer Stripe, fulfil/refund, submit reviews or manage other keys. Checkout requires human age confirmation and Idempotency-Key. See /developers/ for request examples."},"servers":[{"url":"https://ursy.wine/wp-json/ursy/v1"}],"components":{"securitySchemes":{"BearerKey":{"type":"http","scheme":"bearer","description":"Revocable URSY Wine key with explicit scopes."},"BrowserNonce":{"type":"apiKey","in":"header","name":"X-WP-Nonce","description":"Also requires the authenticated WordPress session cookie established by URSY.ID."},"StripeSignature":{"type":"apiKey","in":"header","name":"Stripe-Signature","description":"Stripe timestamped HMAC over the unchanged raw request body."}}},"paths":{"/search":{"get":{"summary":"Search canonical wine products with merchant, style, price and postcode filters.","operationId":"_search","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"merchant","in":"query","schema":{"type":"string"}},{"name":"style","in":"query","schema":{"type":"string"}},{"name":"country","in":"query","schema":{"type":"string"}},{"name":"grape","in":"query","schema":{"type":"string"}},{"name":"postcode","in":"query","schema":{"type":"string"}},{"name":"radius_km","in":"query","schema":{"type":"string"}},{"name":"fulfilment","in":"query","schema":{"type":"string"}},{"name":"sort","in":"query","schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"string"}},{"name":"min_price","in":"query","schema":{"type":"string"}},{"name":"max_price","in":"query","schema":{"type":"string"}}],"x-required-scope":"catalog:read"}},"/products/{id}":{"get":{"summary":"Get one canonical wine identity.","operationId":"_products_id","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-scope":"catalog:read"}},"/products/{id}/offers":{"get":{"summary":"Compare independently owned merchant offers.","operationId":"_products_id_offers","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-scope":"offers:read"}},"/merchants":{"get":{"summary":"Find wine shops.","operationId":"_merchants","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"x-required-scope":"merchant:read"}},"/merchants/{id}":{"get":{"summary":"Read a public merchant profile.","operationId":"_merchants_id","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-scope":"merchant:read"}},"/merchants/{id}/offers":{"get":{"summary":"Read this merchant’s offers.","operationId":"_merchants_id_offers","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-scope":"offers:read"}},"/gtin/{gtin}":{"get":{"summary":"Fetch authoritative source details from URSY.food.","operationId":"_gtin_gtin","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"gtin","in":"path","required":true,"schema":{"type":"string"}}],"x-required-scope":"catalog:read"}},"/health":{"get":{"summary":"Read marketplace counts and readiness.","operationId":"_health","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"x-required-scope":"catalog:read"}},"/account/orders":{"get":{"summary":"Read only your own orders.","operationId":"_account_orders","responses":{"200":{"description":"Successful JSON response"},"400":{"description":"Invalid parameters"},"404":{"description":"Entity not found"},"429":{"description":"Rate limit exceeded"}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"orders:read"}},"/quotes":{"post":{"summary":"Calculate one merchant order including delivery. Demo quotes cannot be paid.","operationId":"_quotes","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":40,"items":{"type":"object","required":["offer_id","quantity"],"properties":{"offer_id":{"type":"string"},"quantity":{"type":"integer","minimum":1,"maximum":120}}}},"postcode":{"type":"string"},"fulfilment":{"enum":["delivery","local","collection"]}}}}}},"responses":{"200":{"description":"Successful response"},"401":{"description":"Authentication required"},"409":{"description":"Demo inventory, age action, stale quote, stock change or merchant not ready"},"503":{"description":"Provider or launch configuration unavailable"}},"x-required-scope":"quotes:create"}},"/checkout-sessions":{"post":{"summary":"Create direct merchant Stripe checkout after authentication, age declaration and readiness checks.","operationId":"_checkout_sessions","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["quote_id","age_confirmed"],"properties":{"quote_id":{"type":"string"},"age_confirmed":{"const":true}}}}}},"responses":{"200":{"description":"Successful response"},"401":{"description":"Authentication required"},"409":{"description":"Demo inventory, age action, stale quote, stock change or merchant not ready"},"503":{"description":"Provider or launch configuration unavailable"}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"checkout:create","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":16,"maxLength":100,"pattern":"^[A-Za-z0-9_-]+$"}}]}},"/merchant/stripe/connect":{"post":{"summary":"Manage your own merchant Stripe Connect account.","operationId":"_merchant_stripe_connect","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Successful response"},"401":{"description":"Authentication required"},"409":{"description":"Demo inventory, age action, stale quote, stock change or merchant not ready"},"503":{"description":"Provider or launch configuration unavailable"}},"security":[{"BrowserNonce":[]}]}},"/merchant/stripe/status":{"post":{"summary":"Manage your own merchant Stripe Connect account.","operationId":"_merchant_stripe_status","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Successful response"},"401":{"description":"Authentication required"},"409":{"description":"Demo inventory, age action, stale quote, stock change or merchant not ready"},"503":{"description":"Provider or launch configuration unavailable"}},"security":[{"BrowserNonce":[]}]}},"/orders/{id}":{"get":{"summary":"Read an order owned by the buyer or merchant.","operationId":"get__orders_id","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"orders:read"}},"/merchant/apply":{"post":{"summary":"Submit the signed-in account’s merchant application for review.","operationId":"post__merchant_apply","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BrowserNonce":[]}]}},"/merchant/me":{"get":{"summary":"Read your merchant profile.","operationId":"get__merchant_me","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"merchant:read"},"post":{"summary":"Update your merchant profile.","operationId":"post__merchant_me","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BrowserNonce":[]}]}},"/merchant/offers":{"get":{"summary":"Read your inventory.","operationId":"get__merchant_offers","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"inventory:read"},"post":{"summary":"Create or update an offer using GTIN identity.","operationId":"post__merchant_offers","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"inventory:write"}},"/merchant/offers/{id}":{"patch":{"summary":"Update your own merchant offer.","operationId":"patch__merchant_offers_id","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"inventory:write"},"delete":{"summary":"Pause your own offer.","operationId":"delete__merchant_offers_id","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"inventory:write"}},"/merchant/import":{"post":{"summary":"Import your CSV inventory; GTIN matches retain canonical identity.","operationId":"post__merchant_import","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"inventory:write"}},"/merchant/orders":{"get":{"summary":"Read your merchant orders and item identifiers.","operationId":"get__merchant_orders","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"orders:read"}},"/merchant/statements":{"get":{"summary":"Read your append-only commission ledger.","operationId":"get__merchant_statements","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"security":[{"BearerKey":[]},{"BrowserNonce":[]}],"x-required-scope":"orders:read"}},"/merchant/orders/{id}/fulfil":{"post":{"summary":"Update a verified paid order using age-checked fulfilment.","operationId":"post__merchant_orders_id_fulfil","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BrowserNonce":[]}]}},"/merchant/orders/{id}/refund":{"post":{"summary":"Request a full or item-allocated partial refund.","operationId":"post__merchant_orders_id_refund","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":16,"maxLength":100,"pattern":"^[A-Za-z0-9_-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BrowserNonce":[]}]}},"/account/api-keys":{"get":{"summary":"List your key metadata from a browser session.","operationId":"get__account_api_keys","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"security":[{"BrowserNonce":[]}]},"post":{"summary":"Issue an explicitly scoped key; the credential is shown once.","operationId":"post__account_api_keys","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BrowserNonce":[]}]}},"/account/api-keys/{id}":{"delete":{"summary":"Revoke your key from a browser session.","operationId":"delete__account_api_keys_id","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"security":[{"BrowserNonce":[]}]}},"/support":{"post":{"summary":"Save a private support request.","operationId":"post__support","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BrowserNonce":[]}]}},"/merchants/{id}/reviews":{"get":{"summary":"Read public feedback, with demo feedback labelled.","operationId":"get__merchants_id_reviews","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"x-required-scope":"merchant:read"},"post":{"summary":"Submit feedback for your completed purchase.","operationId":"post__merchants_id_reviews","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"BrowserNonce":[]}]}},"/mcp":{"post":{"summary":"Read-only JSON-RPC catalogue tools. Does not authorise purchases.","operationId":"post__mcp","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/stripe/webhook":{"post":{"summary":"Stripe connected-account webhook; signed payload required.","operationId":"post__stripe_webhook","responses":{"200":{"description":"Successful operation"},"400":{"description":"Invalid request"},"401":{"description":"Missing or invalid authentication"},"403":{"description":"Insufficient ownership, scope or browser nonce"},"409":{"description":"State conflict or launch gate"},"429":{"description":"Rate limit exceeded"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"security":[{"StripeSignature":[]}]}}}}