{"openapi":"3.1.0","info":{"title":"SitesPlaced Developer API","version":"v1","summary":"Catalogue, checkout, orders, tracking and webhooks for one SitesPlaced store.","description":"Two uses. **Headless:** a custom website with no backend of its own uses SitesPlaced for its catalogue, checkout and orders.\n**Connected:** a seller who already runs WooCommerce or Shopify keeps that shop, and a plugin copies every order into SitesPlaced. The other platform stays in charge of payment, stock and cancellation; SitesPlaced sends back only the shipping status and the tracking details.\n\n**Keys.** Send the key in a header: `Authorization: Bearer <key>` (`X-Api-Key: <key>` is also accepted). A key in the URL is refused. A secret key (`sp_live_sk_…`) is for servers only; sent from a web browser it is refused with 403. A publishable key (`sp_live_pk_…`) may sit in browser code: it can hold only `products:read`, `checkout:write` and `tracking:read`, and works only from the websites on its allowed list. A connection key is the secret key a plugin receives when a shop connects; routes marked \"connection key\" accept only such a key.\n\n**Conventions.** JSON in, JSON out, UTF-8, bodies up to 1 MB. Dates are ISO 8601 in UTC. Money is a plain number in the order's currency (`1499.5`). Lists are paged with a cursor and come newest first. Every response carries `X-Request-Id`, the `X-RateLimit-*` headers and `Cache-Control: no-store`.\n\n**Rate limits.** 60 requests a minute per secret key on the free plan, 300 on a paid store plan. Publishable keys: 600 / 3000 a minute per key and 30 / 60 per visitor IP. Over the limit: 429 with `Retry-After` (seconds).\n\nHuman-readable reference: https://sitesplaced.com/developers/api","contact":{"name":"SitesPlaced","url":"https://sitesplaced.com/contact"}},"servers":[{"url":"https://sitesplaced.com/api/v1","description":"Always the apex host, never www."}],"externalDocs":{"description":"API reference","url":"https://sitesplaced.com/developers/api"},"security":[{"bearerAuth":[]},{"apiKeyHeader":[]}],"tags":[{"name":"Account","description":"Which store a key belongs to."},{"name":"Orders","description":"Read, send in, update and archive orders."},{"name":"Products","description":"The store's own catalogue, for headless sites. The store must be published."},{"name":"Checkout","description":"Prepare a cart on the store's SitesPlaced checkout."},{"name":"Tracking","description":"Order status for a shopper. Never returns a name, phone, email or address."},{"name":"Webhooks","description":"Endpoints that receive order events."},{"name":"Connection","description":"For plugins that connect another platform's shop. Connection key only, except the code exchange."},{"name":"Meta","description":"This file."}],"paths":{"/me":{"get":{"operationId":"getMe","tags":["Account"],"summary":"Which store this key belongs to","description":"Accepts any valid key. Make this the first call of any integration.","responses":{"200":{"description":"The store, the key and its rate limit.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/orders":{"get":{"operationId":"listOrders","tags":["Orders"],"summary":"List orders","description":"Secret key. Permission `orders:read`. Newest first.","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/OrderStatus"}},{"name":"source","in":"query","schema":{"$ref":"#/components/schemas/OrderSource"}},{"name":"external_id","in":"query","description":"The order's id on the other platform.","schema":{"type":"string"}},{"name":"updated_since","in":"query","schema":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."}},{"name":"created_since","in":"query","schema":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."}},{"name":"include_archived","in":"query","description":"Send `true` to also return archived orders.","schema":{"type":"string","enum":["true"]}}],"responses":{"200":{"description":"A page of orders.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}},"post":{"operationId":"upsertOrder","tags":["Orders"],"summary":"Send an order in (create or update)","description":"Secret key. Permission `orders:write`. Creates the order, or updates it if `external_id` was sent before. Safe to retry. The order source is decided by the key, never by the body: a WooCommerce connection key gives `woocommerce`, a Shopify connection gives `shopify`, any other secret key gives `api`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderInput"}}}},"responses":{"200":{"description":"The order was updated, was unchanged, or was skipped.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUpsertResult"}}}},"201":{"description":"The order was created.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUpsertResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/orders/batch":{"post":{"operationId":"upsertOrdersBatch","tags":["Orders"],"summary":"Send up to 50 orders in","description":"Secret key. Permission `orders:write`. One bad order never fails the batch. `backfill: true` means \"this is history\": no mobile push, no WhatsApp and no webhooks.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderBatchRequest"}}}},"responses":{"200":{"description":"One result per order.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderBatchResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/orders/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"The SitesPlaced order id (a uuid), not the order number.","schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getOrder","tags":["Orders"],"summary":"Get one order","description":"Secret key. Permission `orders:read`.","responses":{"200":{"description":"The order.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderEnvelope"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}},"patch":{"operationId":"updateOrder","tags":["Orders"],"summary":"Change status and tracking","description":"Secret key. Permission `orders:write`. Send any of `status`, `tracking` and `comment`. Cancelling an order copied in from another platform with a key that is not that order's own connection key gives 409: cancel it on the other platform.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderPatch"}}}},"responses":{"200":{"description":"The updated order.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderEnvelope"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}},"delete":{"operationId":"archiveOrder","tags":["Orders"],"summary":"Archive an order","description":"Secret key. Permission `orders:write`. Archives; an order is never hard-deleted.","responses":{"200":{"description":"The order is archived.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderArchived"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/external-products/batch":{"post":{"operationId":"upsertExternalProducts","tags":["Connection"],"summary":"Send up to 100 of a connected shop's products","description":"Connection key only. Permission `products:write`. These products are kept apart from the store's own products and can never be sold on a SitesPlaced storefront.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalProductBatchRequest"}}}},"responses":{"200":{"description":"One result per product.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalProductBatchResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/external-products/{external_id}":{"parameters":[{"name":"external_id","in":"path","required":true,"description":"The product's id on the other platform.","schema":{"type":"string"}}],"delete":{"operationId":"deleteExternalProduct","tags":["Connection"],"summary":"Remove one copied product","description":"Connection key only. Permission `products:write`.","responses":{"200":{"description":"Removed.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExternalProductDeleted"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/products":{"get":{"operationId":"listProducts","tags":["Products"],"summary":"List products","description":"Secret or publishable key. Permission `products:read`. The store must be published. Prices are the ones the storefront shows.","parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Cursor"},{"name":"category","in":"query","description":"A category name from `GET /categories`.","schema":{"type":"string"}}],"responses":{"200":{"description":"A page of products.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductList"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/products/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"operationId":"getProduct","tags":["Products"],"summary":"Get one product","description":"Secret or publishable key. Permission `products:read`.","responses":{"200":{"description":"The product.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductEnvelope"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/categories":{"get":{"operationId":"listCategories","tags":["Products"],"summary":"List category names","description":"Secret or publishable key. Permission `products:read`.","responses":{"200":{"description":"The store's category names.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/checkout/sessions":{"post":{"operationId":"createCheckoutSession","tags":["Checkout"],"summary":"Prepare a cart and get a link to it","description":"Secret or publishable key. Permission `checkout:write`. Send the shopper to `url`: the cart opens with those lines; prices, stock, payment methods and every checkout guard are SitesPlaced's own. Up to 50 lines. Unknown or archived products give 422. With a publishable key, `return_url` must be on the key's allowed websites. The link works for 24 hours.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSessionRequest"}}}},"responses":{"201":{"description":"The prepared cart.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutSession"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/tracking":{"get":{"operationId":"getTracking","tags":["Tracking"],"summary":"Look up an order's status for a shopper","description":"Secret or publishable key. Permission `tracking:read`. Never returns a name, phone, email or address. An order copied in from another platform needs `contact`, because those order numbers are sequential and easy to guess. Missing `contact` gives 422 with `param: \"contact\"`; a wrong one gives 422; five wrong tries give 429 for 15 minutes.","parameters":[{"name":"order","in":"query","required":true,"description":"The order number.","schema":{"type":"string"}},{"name":"contact","in":"query","description":"The last 4 digits of the phone number on the order, or the email. Needed for orders copied in from another platform.","schema":{"type":"string"}}],"responses":{"200":{"description":"The order's status.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackingResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/webhooks":{"get":{"operationId":"listWebhooks","tags":["Webhooks"],"summary":"List webhook endpoints","description":"Secret key. Permission `webhooks:write`. The signing secret is never listed.","responses":{"200":{"description":"The store's endpoints.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}},"post":{"operationId":"createWebhook","tags":["Webhooks"],"summary":"Register a webhook endpoint","description":"Secret key. Permission `webhooks:write`. `url` must be public https. The `secret` in the response is shown once. Deliveries are attempted once, with an 8 second timeout, and redirects are not followed: poll `GET /orders?updated_since=` as a backstop.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}}},"responses":{"201":{"description":"The endpoint, with its signing secret.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreated"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/webhooks/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"delete":{"operationId":"deleteWebhook","tags":["Webhooks"],"summary":"Remove a webhook endpoint","description":"Secret key. Permission `webhooks:write`.","responses":{"200":{"description":"Removed.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeleted"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/connect/exchange":{"post":{"operationId":"exchangeConnectCode","tags":["Connection"],"summary":"Swap a one-time code for the plugin's key","description":"No key: the plugin does not have one yet. The code works once, for 10 minutes, and only when the host of `site_url` matches the shop that was approved. Any failure gives 400.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectExchangeRequest"}}}},"responses":{"200":{"description":"The plugin's key and signing secret.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectExchangeResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/connect/disconnect":{"post":{"operationId":"disconnect","tags":["Connection"],"summary":"Close the connection","description":"Connection key only. Permission `connection:manage`. The key stops working immediately afterwards.","responses":{"200":{"description":"Disconnected.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Ok"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/connection":{"get":{"operationId":"getConnection","tags":["Connection"],"summary":"The connection's status","description":"Connection key only. Permission `connection:manage`.","responses":{"200":{"description":"The connection and its store.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionStatus"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}},"put":{"operationId":"putConnection","tags":["Connection"],"summary":"Report the plugin's version and push address","description":"Connection key only. Permission `connection:manage`. A `site_url` whose host differs from the connected one gives 409 and the plugin must pause: this is how a staging copy of a site is stopped from sending orders to the live store.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionHeartbeat"}}}},"responses":{"200":{"description":"The connection and its store.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectionStatus"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"$ref":"#/components/responses/Conflict"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/connection/updates":{"get":{"operationId":"listConnectionUpdates","tags":["Connection"],"summary":"Updates waiting to go back to the shop","description":"Connection key only. Permission `connection:manage`. The pull fallback a plugin runs every 15 minutes.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"default":50}}],"responses":{"200":{"description":"Waiting updates.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateList"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/connection/updates/ack":{"post":{"operationId":"acknowledgeConnectionUpdates","tags":["Connection"],"summary":"Report which updates were applied","description":"Connection key only. Permission `connection:manage`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAck"}}}},"responses":{"200":{"description":"How many were acknowledged.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAckResult"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"},"503":{"$ref":"#/components/responses/Unavailable"}}}},"/openapi.json":{"get":{"operationId":"getOpenApi","tags":["Meta"],"summary":"This file","security":[],"responses":{"200":{"description":"The OpenAPI 3.1 description of this API.","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"webhooks":{"orderEvent":{"post":{"operationId":"onOrderEvent","tags":["Webhooks"],"summary":"An order event, delivered to your endpoint","description":"One attempt, 8 second timeout, redirects not followed. Check `X-SitesPlaced-Signature` before trusting the body: it is `sha256=` followed by the hex HMAC-SHA256 of the raw body, made with the `whsec_…` secret shown once when the endpoint was created. Compare in constant time.","security":[],"parameters":[{"name":"X-SitesPlaced-Event","in":"header","required":true,"schema":{"type":"string","enum":["order.created","order.paid","order.confirmed","order.fulfilled","order.shipped","order.out_for_delivery","order.completed","order.cancelled","order.updated"]}},{"name":"X-SitesPlaced-Delivery","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-SitesPlaced-Signature","in":"header","required":true,"description":"`sha256=<hex HMAC-SHA256 of the raw body>`","schema":{"type":"string","pattern":"^sha256=[0-9a-f]{64}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Answer with any 2xx status within 8 seconds."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer sp_live_sk_…` (or `sp_live_pk_…` on routes that accept a publishable key). A key in the URL is refused."},"apiKeyHeader":{"type":"apiKey","in":"header","name":"X-Api-Key","description":"The same key, in `X-Api-Key`. Also accepted."}},"headers":{"X-Request-Id":{"description":"Identifies this call. Quote it when asking for help.","schema":{"type":"string","examples":["req_…"]}},"X-RateLimit-Limit":{"description":"Requests allowed per minute for this key.","schema":{"type":"integer"}},"X-RateLimit-Remaining":{"description":"Requests left in the current minute.","schema":{"type":"integer"}},"X-RateLimit-Reset":{"description":"When the limit resets, in unix seconds.","schema":{"type":"integer"}},"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}},"parameters":{"Limit":{"name":"limit","in":"query","description":"Page size, 1 to 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},"Cursor":{"name":"cursor","in":"query","description":"The `next_cursor` from the page before.","schema":{"type":"string"}}},"responses":{"BadRequest":{"description":"`invalid_request`. The request is malformed or a field has a bad value; `param` names the field.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"invalid_request","message":"Plain words.","request_id":"req_…"}}}}},"Unauthorized":{"description":"`unauthorized`. The key is missing, wrong or revoked.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unauthorized","message":"Plain words.","request_id":"req_…"}}}}},"Forbidden":{"description":"`forbidden`. The key may not do this: a secret key sent from a browser, a publishable key from a website not on its list, the wrong kind of key, or a missing permission.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"forbidden","message":"Plain words.","request_id":"req_…"}}}}},"NotFound":{"description":"`not_found`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"not_found","message":"Plain words.","request_id":"req_…"}}}}},"Conflict":{"description":"`conflict`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"conflict","message":"Plain words.","request_id":"req_…"}}}}},"PayloadTooLarge":{"description":"`payload_too_large`. Bodies can be up to 1 MB.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"payload_too_large","message":"Plain words.","request_id":"req_…"}}}}},"Unprocessable":{"description":"`unprocessable`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unprocessable","message":"Plain words.","request_id":"req_…"}}}}},"RateLimited":{"description":"`rate_limited`. Wait for `Retry-After` seconds.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"rate_limited","message":"Plain words.","request_id":"req_…"}}}}},"InternalError":{"description":"`internal_error`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"internal_error","message":"Plain words.","request_id":"req_…"}}}}},"Unavailable":{"description":"`unavailable`.","headers":{"X-Request-Id":{"$ref":"#/components/headers/X-Request-Id"},"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":{"code":"unavailable","message":"Plain words.","request_id":"req_…"}}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","enum":["invalid_request","unauthorized","forbidden","not_found","conflict","payload_too_large","unprocessable","rate_limited","internal_error","unavailable"]},"message":{"type":"string","description":"Plain words, for a person."},"param":{"type":"string","description":"The field at fault, when there is one.","examples":["totals.total"]},"request_id":{"type":"string","examples":["req_…"]}}}}},"Ok":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}},"Scope":{"type":"string","enum":["orders:read","orders:write","products:read","products:write","checkout:write","tracking:read","webhooks:write","connection:manage"]},"OrderStatus":{"type":"string","enum":["pending","confirmed","shipped","out_for_delivery","completed","cancelled"],"description":"`completed` means delivered."},"OrderSource":{"type":"string","enum":["native","woocommerce","shopify","api"],"description":"`native` is the SitesPlaced checkout."},"PaymentStatus":{"type":"string","enum":["unpaid","pending","paid","failed","refunded"]},"Me":{"type":"object","required":["api_version","store","key","limits"],"properties":{"api_version":{"type":"string","const":"v1"},"store":{"type":"object","required":["id","name","slug","url","tracking_url","currency","mode"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"url":{"type":"string","format":"uri"},"tracking_url":{"type":"string","format":"uri"},"currency":{"type":"string","examples":["INR"]},"mode":{"type":"string","enum":["full","tracking_only"]}}},"key":{"type":"object","required":["kind","scopes","connection_id"],"properties":{"kind":{"type":"string","enum":["secret","publishable"]},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"connection_id":{"type":["string","null"],"format":"uuid","description":"Set when the key is a plugin's connection key."}}},"limits":{"type":"object","required":["requests_per_minute"],"properties":{"requests_per_minute":{"type":"integer"}}}}},"OrderItem":{"type":"object","required":["name","quantity","unit_price"],"properties":{"name":{"type":"string"},"variant":{"type":["string","null"]},"quantity":{"type":"number"},"unit_price":{"type":"number"},"sku":{"type":["string","null"]},"product_id":{"type":["string","null"],"description":"The SitesPlaced product id. Null on an order copied in from another platform."},"external_product_id":{"type":["string","null"]},"image_url":{"type":["string","null"]}}},"OrderTracking":{"type":"object","required":["page_url"],"properties":{"number":{"type":["string","null"]},"courier":{"type":["string","null"]},"url":{"type":["string","null"]},"status_text":{"type":["string","null"]},"page_url":{"type":"string","format":"uri","description":"The public tracking page for this order."}}},"OrderRisk":{"type":["object","null"],"description":"Cash-on-delivery orders only.","properties":{"level":{"type":"string","enum":["medium","high"]},"flags":{"type":"array","items":{"type":"object","required":["code","label"],"properties":{"code":{"type":"string","examples":["bad_phone"]},"label":{"type":"string"}}}}}},"Order":{"type":"object","required":["id","object","source","status","payment","totals","currency","customer","items","tracking","archived","created_at","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","const":"order"},"order_number":{"type":["string","null"]},"source":{"$ref":"#/components/schemas/OrderSource"},"external_id":{"type":["string","null"]},"external_number":{"type":["string","null"]},"external_status":{"type":["string","null"],"description":"The raw status on the other platform.","examples":["processing"]},"external_url":{"type":["string","null"],"description":"The order's admin address on the other platform."},"status":{"$ref":"#/components/schemas/OrderStatus"},"payment":{"type":"object","required":["method","status"],"properties":{"method":{"type":"string","description":"For orders copied in from another platform this is only `cod` or `manual`; the real method is in `external_method`."},"status":{"$ref":"#/components/schemas/PaymentStatus"},"external_method":{"type":["string","null"]},"external_method_title":{"type":["string","null"]}}},"totals":{"type":"object","required":["total","discount","shipping","cod_fee"],"properties":{"total":{"type":"number"},"discount":{"type":"number"},"shipping":{"type":"number"},"cod_fee":{"type":"number"}}},"currency":{"type":"string","examples":["INR"]},"customer":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"email":{"type":["string","null"]},"phone":{"type":["string","null"]},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"state":{"type":["string","null"]},"postcode":{"type":["string","null"]},"country":{"type":["string","null"]}}},"items":{"type":"array","items":{"$ref":"#/components/schemas/OrderItem"}},"tracking":{"$ref":"#/components/schemas/OrderTracking"},"note":{"type":["string","null"]},"risk":{"$ref":"#/components/schemas/OrderRisk"},"archived":{"type":"boolean"},"created_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."}}},"OrderEnvelope":{"type":"object","required":["order"],"properties":{"order":{"$ref":"#/components/schemas/Order"}}},"OrderArchived":{"type":"object","required":["id","archived"],"properties":{"id":{"type":"string","format":"uuid"},"archived":{"type":"boolean","const":true}}},"OrderList":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}},"OrderInput":{"type":"object","required":["external_id","totals"],"properties":{"external_id":{"type":"string","description":"The order's id on the other system. Sending the same one again updates the order."},"number":{"type":"string","description":"The order number a shopper sees."},"status":{"type":"string","description":"Read according to `status_kind`."},"status_kind":{"type":"string","enum":["woocommerce","shopify","sitesplaced"],"description":"`woocommerce`: WooCommerce status slugs, with or without `wc-`. `shopify`: `open`, `partial`, `fulfilled` or `cancelled`. `sitesplaced`: the six order statuses, plus the aliases `delivered`, `fulfilled`, `processing`, `paid` and `canceled`. A connection key defaults to its platform; any other key defaults to `sitesplaced`."},"payment":{"type":"object","properties":{"status":{"type":"string","enum":["unpaid","pending","paid","failed","refunded","partially_refunded"],"description":"Send it. If it is missing the server guesses from the status."},"method":{"type":"string","examples":["razorpay"]},"method_title":{"type":"string","examples":["Credit Card/UPI"]},"is_cod":{"type":"boolean","description":"True for cash on delivery. This is what turns on the COD risk flags."},"transaction_id":{"type":"string"},"refunded_amount":{"type":"number"}}},"currency":{"type":"string","examples":["INR"]},"totals":{"type":"object","required":["total"],"properties":{"total":{"type":"number","minimum":0},"discount":{"type":"number"},"shipping":{"type":"number"},"cod_fee":{"type":"number"},"tax":{"type":"number"}}},"customer":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"address_line1":{"type":"string"},"address_line2":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"postcode":{"type":"string"},"country":{"type":"string","examples":["IN"]}}},"items":{"type":"array","description":"Up to 200 line items are kept.","items":{"type":"object","properties":{"external_product_id":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string"},"variant":{"type":"string","examples":["Size: Small"]},"quantity":{"type":"number"},"unit_price":{"type":"number"},"image_url":{"type":"string"}}}},"note":{"type":"string"},"tracking":{"type":"object","properties":{"number":{"type":["string","null"]},"courier":{"type":["string","null"]},"url":{"type":["string","null"]}}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."},"updated_at":{"type":"string","format":"date-time","description":"Older than the copy SitesPlaced holds → ignored (`action: \"unchanged\"`)."},"admin_url":{"type":"string","description":"The order's admin address on the other system."},"deleted":{"type":"boolean","description":"True archives the copy. It is never hard-deleted."},"test":{"type":"boolean","description":"True → skipped."},"delivered":{"type":"boolean"}}},"OrderUpsertResult":{"type":"object","required":["order","action"],"properties":{"order":{"oneOf":[{"$ref":"#/components/schemas/Order"},{"type":"null"}],"description":"Null when `action` is `skipped`."},"action":{"type":"string","enum":["created","updated","unchanged","skipped"]},"reason":{"type":"string","description":"Set when `action` is `skipped`."}}},"OrderBatchRequest":{"type":"object","required":["orders"],"properties":{"orders":{"type":"array","minItems":1,"maxItems":50,"items":{"$ref":"#/components/schemas/OrderInput"}},"backfill":{"type":"boolean","description":"True means \"this is history\": no mobile push, no WhatsApp, no webhooks."}}},"OrderBatchResult":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"type":"object","required":["external_id","ok"],"properties":{"external_id":{"type":["string","null"]},"ok":{"type":"boolean"},"action":{"type":"string","enum":["created","updated","unchanged","skipped"]},"id":{"type":"string","format":"uuid"},"error":{"type":"string"}}}}}},"OrderPatch":{"type":"object","description":"Any of the three.","properties":{"status":{"$ref":"#/components/schemas/OrderStatus"},"tracking":{"type":"object","properties":{"number":{"type":"string"},"courier":{"type":"string"},"url":{"type":"string","format":"uri"}}},"comment":{"type":"string"}}},"ProductVariant":{"type":"object","properties":{"options":{"type":"object","additionalProperties":{"type":"string"},"examples":[{"Size":"M"}]},"price":{"type":"number"},"stock":{"type":["number","null"]},"sku":{"type":["string","null"]}}},"Product":{"type":"object","required":["id","object","name","price","currency","in_stock","url"],"properties":{"id":{"type":"string","format":"uuid"},"object":{"type":"string","const":"product"},"name":{"type":"string"},"description":{"type":"string"},"price":{"type":"number","description":"The price the storefront shows."},"compare_at_price":{"type":["number","null"]},"delivery_fee":{"type":["number","null"],"description":"The product's own delivery fee. null = sent at the store's standard fee; 0 = ships free. An order is charged one delivery fee, the highest among its products."},"currency":{"type":"string","examples":["INR"]},"image_url":{"type":["string","null"]},"images":{"type":"array","items":{"type":"string","format":"uri"}},"category":{"type":["string","null"]},"categories":{"type":"array","items":{"type":"string"}},"type":{"type":"string","examples":["physical"]},"in_stock":{"type":"boolean"},"stock":{"type":["number","null"]},"variants":{"type":"array","items":{"$ref":"#/components/schemas/ProductVariant"}},"url":{"type":"string","format":"uri","description":"The product's page on the SitesPlaced storefront."}}},"ProductEnvelope":{"type":"object","required":["product"],"properties":{"product":{"$ref":"#/components/schemas/Product"}}},"ProductList":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Product"}},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}},"CategoryList":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"string"},"examples":[["Earrings","Necklaces"]]}}},"CheckoutSessionRequest":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":50,"items":{"type":"object","required":["product_id"],"properties":{"product_id":{"type":"string","format":"uuid"},"quantity":{"type":"integer","minimum":1},"variant":{"type":"object","additionalProperties":{"type":"string"},"examples":[{"Size":"M"}]}}}},"return_url":{"type":"string","format":"uri","description":"With a publishable key, this must be on the key's allowed websites."}}},"CheckoutSession":{"type":"object","required":["url","token","expires_at"],"properties":{"url":{"type":"string","format":"uri","description":"Send the shopper here.","examples":["https://asha-jewels.sitesplaced.site/cart?restore=cl_…"]},"token":{"type":"string","examples":["cl_…"]},"expires_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."}}},"TrackingOrder":{"type":"object","description":"Never contains a name, phone, email or address.","properties":{"order_number":{"type":"string"},"status":{"$ref":"#/components/schemas/OrderStatus"},"items":{"type":"array","items":{"type":"object"}},"total_amount":{"type":"number"},"shipping_fee":{"type":["number","null"]},"cod_fee":{"type":["number","null"]},"currency":{"type":"string"},"tracking_link":{"type":["string","null"]},"status_comment":{"type":["string","null"]},"shipping_awb":{"type":["string","null"]},"shipping_courier":{"type":["string","null"]},"shipping_status_text":{"type":["string","null"]},"status_history":{"type":"array","items":{"type":"object"}},"created_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."}}},"TrackingResult":{"type":"object","required":["order","store"],"properties":{"order":{"$ref":"#/components/schemas/TrackingOrder"},"store":{"type":"object","required":["name"],"properties":{"name":{"type":"string"}}}}},"WebhookEvent":{"type":"string","enum":["order.created","order.paid","order.confirmed","order.fulfilled","order.shipped","order.out_for_delivery","order.completed","order.cancelled","order.updated","*"]},"Webhook":{"type":"object","required":["id","url","events"],"properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEvent"}}}},"WebhookCreate":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","description":"Must be public https."},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEvent"},"examples":[["order.created"]]}}},"WebhookCreated":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","required":["secret"],"properties":{"secret":{"type":"string","description":"Shown once.","examples":["whsec_…"]}}}]},"WebhookList":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}},"WebhookDeleted":{"type":"object","required":["id","deleted"],"properties":{"id":{"type":"string","format":"uuid"},"deleted":{"type":"boolean","const":true}}},"ConnectedStore":{"type":"object","required":["id","name","slug","tracking_url","dashboard_url"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"},"tracking_url":{"type":"string","format":"uri"},"dashboard_url":{"type":"string","format":"uri"}}},"ConnectExchangeRequest":{"type":"object","required":["code","site_url"],"properties":{"code":{"type":"string","examples":["spc_…"]},"site_url":{"type":"string","format":"uri","examples":["https://shop.example.com"]}}},"ConnectExchangeResult":{"type":"object","required":["api_key","webhook_secret","connection_id","store"],"properties":{"api_key":{"type":"string","examples":["sp_live_sk_…"]},"webhook_secret":{"type":"string","description":"Signs the updates pushed back to the shop.","examples":["whsec_…"]},"connection_id":{"type":"string","format":"uuid"},"store":{"$ref":"#/components/schemas/ConnectedStore"}}},"Connection":{"type":"object","required":["id","platform","status"],"properties":{"id":{"type":"string","format":"uuid"},"platform":{"type":"string","examples":["woocommerce"]},"status":{"type":"string"},"status_detail":{"type":["string","null"]},"shop_url":{"type":["string","null"]},"orders_synced":{"type":"integer"},"last_order_at":{"type":["string","null"],"format":"date-time"}}},"ConnectionStatus":{"type":"object","required":["connection","store"],"properties":{"connection":{"$ref":"#/components/schemas/Connection"},"store":{"$ref":"#/components/schemas/ConnectedStore"}}},"ConnectionHeartbeat":{"type":"object","properties":{"plugin_version":{"type":"string","examples":["1.0.0"]},"platform_version":{"type":"string"},"site_url":{"type":"string","format":"uri","description":"A host that differs from the connected one gives 409."},"push_url":{"type":["string","null"],"description":"Where SitesPlaced pushes updates. Null when the shop's REST API cannot be reached.","examples":["https://shop.example.com/wp-json/sitesplaced/v1/updates"]},"shop_name":{"type":"string"},"currency":{"type":"string","examples":["INR"]}}},"Update":{"type":"object","description":"\"This order shipped / is out for delivery / was delivered, and here is the tracking.\"","required":["id","order_id","external_id"],"properties":{"id":{"type":"string","format":"uuid"},"order_id":{"type":"string","format":"uuid"},"external_id":{"type":"string"},"number":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["shipped","out_for_delivery","completed",null],"description":"Null means tracking only."},"tracking":{"type":"object","properties":{"number":{"type":["string","null"]},"courier":{"type":["string","null"]},"url":{"type":["string","null"]}}},"tracking_page_url":{"type":"string","format":"uri"},"comment":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."}}},"UpdateList":{"type":"object","required":["updates"],"properties":{"updates":{"type":"array","items":{"$ref":"#/components/schemas/Update"}}}},"UpdateAck":{"type":"object","properties":{"applied":{"type":"array","items":{"type":"string"}},"failed":{"type":"array","items":{"type":"object","required":["id"],"properties":{"id":{"type":"string"},"error":{"type":"string"}}}}}},"UpdateAckResult":{"type":"object","required":["acknowledged"],"properties":{"acknowledged":{"type":"integer"}}},"ExternalProductInput":{"type":"object","required":["external_id","name"],"properties":{"external_id":{"type":"string"},"name":{"type":"string"},"sku":{"type":"string"},"price":{"type":"number"},"currency":{"type":"string"},"image_url":{"type":"string","format":"uri"},"images":{"type":"array","items":{"type":"string","format":"uri"}},"url":{"type":"string","format":"uri"},"category":{"type":"string"},"description":{"type":"string"},"stock":{"type":"number"},"status":{"type":"string"},"updated_at":{"type":"string","format":"date-time","description":"ISO 8601, in UTC."}}},"ExternalProductBatchRequest":{"type":"object","required":["products"],"properties":{"products":{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/ExternalProductInput"}}}},"ExternalProductBatchResult":{"type":"object","required":["results"],"properties":{"results":{"type":"array","items":{"type":"object","required":["external_id","ok"],"properties":{"external_id":{"type":["string","null"]},"ok":{"type":"boolean"},"error":{"type":"string"}}}}}},"ExternalProductDeleted":{"type":"object","required":["external_id","deleted"],"properties":{"external_id":{"type":"string"},"deleted":{"type":"boolean"}}}}}}