### Worked example: idempotent POST with curl Source: https://www.watchtraderhub.com/docs/api/idempotency Worked example showing three curl calls: the initial creation, a replay with the same key and body (returns 201 with Idempotent-Replay: true), and a buggy retry with a different body (returns 409 key_reused_with_different_body). ```bash # First call, creates the customer. curl -X POST https://www.watchtraderhub.com/api/v1/customers \ -H "Authorization: Bearer wth_YOUR_API_KEY" \ -H "Idempotency-Key: 4fe3c1e5-9c0e-49a8-9d77-2c0a4b6a3d11" \ -H "Content-Type: application/json" \ -d '{"external_id":"cust-001","email":"a@example.com","name":"Alice"}' # 201 Created # Network blip, same call, same key, same body. Replays the original. curl -X POST https://www.watchtraderhub.com/api/v1/customers \ -H "Authorization: Bearer wth_YOUR_API_KEY" \ -H "Idempotency-Key: 4fe3c1e5-9c0e-49a8-9d77-2c0a4b6a3d11" \ -H "Content-Type: application/json" \ -d '{"external_id":"cust-001","email":"a@example.com","name":"Alice"}' # 201 Created Idempotent-Replay: true # Buggy retry, same key, different body. Rejected. curl -X POST https://www.watchtraderhub.com/api/v1/customers \ -H "Authorization: Bearer wth_YOUR_API_KEY" \ -H "Idempotency-Key: 4fe3c1e5-9c0e-49a8-9d77-2c0a4b6a3d11" \ -H "Content-Type: application/json" \ -d '{"external_id":"cust-001","email":"different@example.com","name":"Alice"}' # 409 key_reused_with_different_body ``` -------------------------------- ### GET /v1/parts Source: https://www.watchtraderhub.com/docs/api/pagination Fetches a page of parts using cursor-based pagination. Supports limit, after, and updated_after query parameters. ```APIDOC ## GET /v1/parts ### Description Fetches a page of parts using cursor-based pagination. Supports limit, after, and updated_after query parameters. ### Method GET ### Endpoint https://www.watchtraderhub.com/api/v1/parts ### Parameters #### Query Parameters - **limit** (integer) - Optional - Number of rows to return. Defaults to 50, max 250. - **after** (string) - Optional - Opaque cursor from the previous page's `next_cursor`. Used to fetch the next page. - **updated_after** (string) - Optional - ISO 8601 timestamp. Returns rows where `updated_at > updated_after`. ### Request Example curl -s "https://www.watchtraderhub.com/api/v1/parts?limit=100" \ -H "Authorization: Bearer wth_YOUR_API_KEY" ### Response #### Success Response (200) - **object** (string) - Always "list". - **data** (array) - Array of resource objects (listing/part/order). Up to `limit` rows. - **has_more** (boolean) - True when more rows exist past this page. - **next_cursor** (string) - Opaque string. Pass as `after` on next call. Null when `has_more` is false. #### Response Example { "object": "list", "data": [ /* up to `limit` rows */ ], "has_more": true, "next_cursor": "eyJpZCI6IjI0Zjg…" } ``` -------------------------------- ### Rate limit headers example Source: https://www.watchtraderhub.com/docs/api/authentication Every authenticated response includes these headers. They respond to the limit of current time and the request ID to use in support tickets. ```http X-RateLimit-Limit: 600 X-RateLimit-Remaining: 597 X-RateLimit-Reset: 1778230107 X-Request-Id: req_a4e6109f47be44a3a017ad94965e1a66 X-API-Version: 2026-05-07 ``` -------------------------------- ### Webhook envelope JSON example Source: https://www.watchtraderhub.com/docs/api/webhooks Example of the JSON body sent in a webhook POST request. Use this structure to parse incoming events and access the event data. ```json { "id": "evt_b6d0dfb9dfb64613bed8709ba8a5d079", "object": "event", "type": "listing.published", "api_version": "2026-05-07", "created_at": "2026-05-08T08:41:33.114Z", "livemode": false, "data": { "object": { /* per-event payload, see /docs/api/events */ }, "previous_attributes": { /* present on update events */ } } } ``` -------------------------------- ### part.published Source: https://www.watchtraderhub.com/docs/api/events Fires when the dealer puts a spare part ON the custom channel. Fetch GET /v1/parts/{id} for the part. ```APIDOC ## part.published ### Description Fires when the dealer puts a spare part ON the custom channel. Fetch GET /v1/parts/{id} for the part. ### Event Name part.published ### data.object ``` { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part" } ``` ``` -------------------------------- ### GET /v1/listings Source: https://www.watchtraderhub.com/docs/api/pagination Fetches a page of listings using cursor-based pagination. Supports limit, after, and updated_after query parameters. ```APIDOC ## GET /v1/listings ### Description Fetches a page of listings using cursor-based pagination. Supports limit, after, and updated_after query parameters. ### Method GET ### Endpoint https://www.watchtraderhub.com/api/v1/listings ### Parameters #### Query Parameters - **limit** (integer) - Optional - Number of rows to return. Defaults to 50, max 250. - **after** (string) - Optional - Opaque cursor from the previous page's `next_cursor`. Used to fetch the next page. - **updated_after** (string) - Optional - ISO 8601 timestamp. Returns rows where `updated_at > updated_after`. ### Request Example curl -s "https://www.watchtraderhub.com/api/v1/listings?limit=100" \ -H "Authorization: Bearer wth_YOUR_API_KEY" ### Response #### Success Response (200) - **object** (string) - Always "list". - **data** (array) - Array of resource objects (listing/part/order). Up to `limit` rows. - **has_more** (boolean) - True when more rows exist past this page. - **next_cursor** (string) - Opaque string. Pass as `after` on next call. Null when `has_more` is false. #### Response Example { "object": "list", "data": [ /* up to `limit` rows */ ], "has_more": true, "next_cursor": "eyJpZCI6IjI0Zjg…" } ``` -------------------------------- ### GET /v1/me Source: https://www.watchtraderhub.com/docs/api/quickstart This endpoint checks the validity of your API key and provides the current integration details, including user ID, test rate limits, and API version. ```APIDOC ## GET /v1/me ### Description Confirms your authentication and integration status. Returns the current integration object with user ID, enablement, test mode, API version, and webhook configuration. ### Method GET ### Endpoint https://www.watchtraderhub.com/api/v1/me ### Headers - **Authorization**: Bearer token with your API key (e.g., `wth_YOUR_API_KEY`) ### Request Example ``` curl -i https://www.watchtraderhub.com/api/v1/me \ -H "Authorization: Bearer wth_YOUR_API_KEY" ``` ### Response #### Success Response (200) - **object** (string) - Always "integration" - **user_id** (string) - The dealer's user ID - **is_enabled** (boolean) - Whether the integration is enabled - **is_test_mode** (boolean) - Whether the integration operates in test mode - **api_version** (string) - The API version date (e.g., "2026-05-07") - **subscribed_events** (array of strings) - Subscribed event types, defaults to "*" for all - **webhook** (object) - Webhook configuration - **url** (string) - The webhook receiver URL - **last_success_at** (string/null) - Timestamp of last successful delivery - **last_failure_at** (string/null) - Timestamp of last failed delivery - **consecutive_failures** (integer) - Number of consecutive failures #### Response Example ``` { "object": "integration", "user_id": "…", "is_enabled": true, "is_test_mode": true, "api_version": "2026-05-07", "subscribed_events": ["*"], "webhook": { "url": "https://your-site.com/webhooks/wth", "last_success_at": null, "last_failure_at": null, "consecutive_failures": 0 } } ``` ``` -------------------------------- ### GET /v1/orders Source: https://www.watchtraderhub.com/docs/api/pagination Fetches a page of orders using cursor-based pagination. Supports limit, after, and updated_after query parameters. ```APIDOC ## GET /v1/orders ### Description Fetches a page of orders using cursor-based pagination. Supports limit, after, and updated_after query parameters. ### Method GET ### Endpoint https://www.watchtraderhub.com/api/v1/orders ### Parameters #### Query Parameters - **limit** (integer) - Optional - Number of rows to return. Defaults to 50, max 250. - **after** (string) - Optional - Opaque cursor from the previous page's `next_cursor`. Used to fetch the next page. - **updated_after** (string) - Optional - ISO 8601 timestamp. Returns rows where `updated_at > updated_after`. ### Request Example curl -s "https://www.watchtraderhub.com/api/v1/orders?limit=100" \ -H "Authorization: Bearer wth_YOUR_API_KEY" ### Response #### Success Response (200) - **object** (string) - Always "list". - **data** (array) - Array of resource objects (listing/part/order). Up to `limit` rows. - **has_more** (boolean) - True when more rows exist past this page. - **next_cursor** (string) - Opaque string. Pass as `after` on next call. Null when `has_more` is false. #### Response Example { "object": "list", "data": [ /* up to `limit` rows */ ], "has_more": true, "next_cursor": "eyJpZCI6IjI0Zjg…" } ``` -------------------------------- ### Webhook Envelope Source: https://www.watchtraderhub.com/docs/api/webhooks Every webhook is a POST to your configured URL with a JSON body shaped like the example. The envelope includes event ID, type, API version, creation time, livemode flag, and data object. ```APIDOC ## POST [Configured URL] ### Description Delivers a signed event notification to your configured URL whenever something happens on the dealer side. ### Method POST ### Endpoint Your configured URL (not specified in source) ### Request Body - **id** (string) - Required - Unique event ID. Use it to dedupe at-least-once deliveries. - **object** (string) - Required - Always "event". - **type** (string) - Required - Full event name (e.g., `listing.published`, `order.received`). - **api_version** (string) - Required - The version pinned to the integration that produced the event. - **created_at** (string) - Required - Timestamp of event creation. - **livemode** (boolean) - Required - `false` while the integration was in test mode. - **data** (object) - Required - Contains the event payload. - **object** (object) - Required - The resource the event is about. See Event catalog. - **previous_attributes** (object) - Optional - Present on `*.updated`-style events; map of changed fields with their previous values. ### Request Example ```json { "id": "evt_b6d0dfb9dfb64613bed8709ba8a5d079", "object": "event", "type": "listing.published", "api_version": "2026-05-07", "created_at": "2026-05-08T08:41:33.114Z", "livemode": false, "data": { "object": { /* per-event payload, see /docs/api/events */ }, "previous_attributes": { /* present on update events */ } } } ``` ### Response No response schema documented in source. ``` -------------------------------- ### listing.published data.object Source: https://www.watchtraderhub.com/docs/api/events Payload for the listing.published event. Contains only the listing id and object type. Fetch the full listing via GET /v1/listings/{id}. ```json { "id": "24f0ebb1-73d7-4e99-9901-821078594271", "object": "listing" } ``` -------------------------------- ### part.published data.object Source: https://www.watchtraderhub.com/docs/api/events Payload for the part.published event. Contains only the part id and object type. Fetch the part via GET /v1/parts/{id}. ```json { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part" } ``` -------------------------------- ### Key format regex Source: https://www.watchtraderhub.com/docs/api/authentication The validation regex for the keyed from the API key. It starts with 'wth_' and is followed by 32 base62 characters. The regex is used to check if any remote carrying the token. ```regex /^Bearer\s+(wth_[A-Za-z0-9]{32})$/ ``` -------------------------------- ### Webhook HTTP Request Headers Source: https://www.watchtraderhub.com/docs/api/webhooks Example HTTP request headers for a WatchTraderHub webhook. Includes the signature, event ID, event type, and delivery metadata. The X-WTH-Delivery-Id is unique per dispatch attempt, while X-WTH-Event-Id is unique per event but identical across retries. ```http POST /webhooks/wth HTTP/1.1 Content-Type: application/json X-WTH-Signature: t=1778229903,v1=5a81dbf590e046237fd578e75f5824f210fff7bf4cabd6de7a767169362b5044 X-WTH-Event-Id: evt_b6d0dfb9dfb64613bed8709ba8a5d079 X-WTH-Event-Type: listing.published X-WTH-Delivery-Id: 55fbd03c-5744-4b8e-a057-a29af4729317 X-WTH-Delivery-Attempt: 1 ``` -------------------------------- ### Walk a list with curl using limit and after Source: https://www.watchtraderhub.com/docs/api/pagination Two curl commands. First fetches the first page with `limit=100`, then subsequent pages pass the previous `next_cursor` as the `after` query parameter. Loop until `has_more` is false (or `next_cursor` is null). ```bash # First page curl -s "https://www.watchtraderhub.com/api/v1/listings?limit=100" \ -H "Authorization: Bearer wth_YOUR_API_KEY" # → { "data": [...], "has_more": true, "next_cursor": "eyJ..." } # Subsequent pages, pass the previous next_cursor as `after` curl -s "https://www.watchtraderhub.com/api/v1/listings?limit=100&after=eyJ..." \ -H "Authorization: Bearer wth_YOUR_API_KEY" ``` -------------------------------- ### GET /api/v1/health Source: https://www.watchtraderhub.com/docs Health check endpoint for the WatchTraderHub Custom Integration API. No authentication or rate limiting applies. ```APIDOC ## GET /api/v1/health ### Description Unauthenticated liveness probe for uptime monitors and load-balancer health checks. Returns service status and API version. ### Method GET ### Endpoint /api/v1/health ### Response #### Success Response (200) - **status** (string) - Always "ok" when healthy. - **api_version** (string) - Current API version. #### Response Example { "status": "ok", "api_version": "..." } ``` -------------------------------- ### integration_not_provisioned Source: https://www.watchtraderhub.com/docs/api/errors Documentation for the integration_not_provisioned error, including causes and recovery. ```APIDOC ## Error: integration_not_provisioned ### Description The integration is not linked to an organization. ### Error Code `integration_not_provisioned` ### HTTP Status 403 ### Error Type `permission_error` ### Recovery Contact support so the integration can be linked to your organization. ``` -------------------------------- ### Confirm auth with /v1/me Source: https://www.watchtraderhub.com/docs/api/quickstart Use the /v1/me endpoint to confirm your API key works and to inspect rate-limit and API-version response headers. The expected JSON body shows the integration object with test mode enabled and the webhook configuration. ```bash curl -i https://www.watchtraderhub.com/api/v1/me \ -H "Authorization: Bearer wth_YOUR_API_KEY" ``` ```json { "object": "integration", "user_id": "…", "is_enabled": true, "is_test_mode": true, "api_version": "2026-05-07", "subscribed_events": ["*"], "webhook": { "url": "https://your-site.com/webhooks/wth", "last_success_at": null, "last_failure_at": null, "consecutive_failures": 0 } } ``` -------------------------------- ### Trigger a test webhook with /v1/test/webhook_ping Source: https://www.watchtraderhub.com/docs/api/quickstart Send a signed test event to your webhook URL. The response is 202 Accepted with a delivery_id, and within about 60 seconds a POST with the shown headers should arrive at your webhook URL. ```bash curl -X POST https://www.watchtraderhub.com/api/v1/test/webhook_ping \ -H "Authorization: Bearer wth_YOUR_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` ```http POST /webhooks/wth HTTP/1.1 X-WTH-Signature: t=1778229903,v1=5a81dbf590e046237fd578e75f5824f210fff7bf4cabd6de7a767169362b5044 X-WTH-Event-Id: evt_b6d0dfb9dfb64613bed8709ba8a5d079 X-WTH-Event-Type: integration.test_event X-WTH-Delivery-Id: 55fbd03c-5744-4b8e-a057-a29af4729317 X-WTH-Delivery-Attempt: 1 Content-Type: application/json ``` -------------------------------- ### Pull listings with /v1/listings Source: https://www.watchtraderhub.com/docs/api/quickstart Pull your listings from the custom channel with a cursor-paginated list. The response shows a listing object with watch, price, and pagination fields; see Pagination for walking long lists. ```bash curl -s https://www.watchtraderhub.com/api/v1/listings?limit=10 \ -H "Authorization: Bearer wth_YOUR_API_KEY" ``` ```json { "object": "list", "data": [ { "id": "24f0ebb1-…", "object": "listing", "status": "active", "watch": { "brand": "Rolex", "model": "Submariner Date", "reference": "116610LN", … }, "price": { "amount": 1200000, "currency": "USD", "amount_formatted": "$12,000.00" }, "photos": [], "created_at": "…", "updated_at": "…" } ], "has_more": false, "next_cursor": null } ``` -------------------------------- ### POST /api/v1/* (Idempotency-Key header) Source: https://www.watchtraderhub.com/docs/api/idempotency Every POST to a mutating endpoint under /api/v1/* must include an Idempotency-Key header. Replaying the same key and body returns the original response without re-applying the side effect. ```APIDOC ## [POST] /api/v1/* ### Description Every POST to a mutating endpoint under /api/v1/* must include an Idempotency-Key header. Replaying the same key and body returns the original response without re-applying the side effect. ### Method POST ### Endpoint /api/v1/* ### Parameters #### Headers - **Idempotency-Key** (string) - Required - A unique key (UUIDv4 recommended, any string up to 255 bytes) for the logical operation. Reuse the same key for retries; use a new key for new operations. - **Authorization** (string) - Required - Bearer token for authentication. - **Content-Type** (string) - Required - application/json ### Request Example ``` curl -X POST https://www.watchtraderhub.com/api/v1/customers \ -H "Authorization: Bearer wth_YOUR_API_KEY" \ -H "Idempotency-Key: 4fe3c1e5-9c0e-49a8-9d77-2c0a4b6a3d11" \ -H "Content-Type: application/json" \ -d '{"external_id":"cust-001","email":"a@example.com","name":"Alice"}' ``` ### Response #### Success Response (201 Created) - **Idempotent-Replay** (boolean) - Present on replays, set to true. - **X-Request-Id** (string) - The original request ID on replays. - **Content-Type** (string) - application/json - Response body includes the created resource, e.g., `{ "id": "41296980-…", "object": "customer", … }` #### Response Example ``` HTTP/1.1 201 Created Idempotent-Replay: true X-Request-Id: req_70ab6f8aaa9945958b0564c337d6121e Content-Type: application/json { "id": "41296980-…", "object": "customer", … } ``` ### Error Responses #### 400 missing_idempotency_key Returned when a tracked verb (POST) is missing the Idempotency-Key header. #### 409 key_reused_with_different_body Returned when the same Idempotency-Key is reused with a different request body. The response includes an error object with type `idempotency_error`, code `key_reused_with_different_body`, a message, a doc_url, and a request_id. #### Error Response Example ``` { "error": { "type": "idempotency_error", "code": "key_reused_with_different_body", "message": "Idempotency-Key was previously used with a different request body.", "doc_url": "https://www.watchtraderhub.com/docs/api/errors#key_reused_with_different_body", "request_id": "req_…" } } ``` ### Notes - Idempotency records expire after 24 hours. Reusing a key beyond that window is treated as a fresh operation. - Replay caching applies to any response, including 4xx and 5xx. Use a new key to actually retry. - Do not derive the key from the request body. - Avoid non-deterministic fields (e.g., timestamps) in the body, as they cause body mismatch on retries. ``` -------------------------------- ### Verify Webhook Signature (cURL) Source: https://www.watchtraderhub.com/docs/api/webhooks A one-shot manual sanity check using the shell to recompute the expected signature for a captured webhook body and header. ```APIDOC ## Verify Webhook Signature (cURL) ### Description This snippet shows how to simplify a signature check with cURL locally: it recomputes the expected HMAC signature from the raw body so you can verify it against the `X-WTH-Signature` header. ### Method MANUAL ### Usage Set your own source, then execute the commands to compute the expected `v1` value. ### Parameters - `TIMESTAMP` (string) - Required - The Unix timestamp from the `t=` part of the signature. - `RAW_BODY` (string) - Required - The exact raw request body. - `SECRET` (string) - Required - Your webhook signing secret. ### Example ```bash TIMESTAMP="1778229903" RAW_BODY='{"id":"evt_b6d0dfb9...","object":"event",...}' SECRET="whsec_YOUR_SIGNING_SECRET" EXPECTED=$(printf '%s.%s' "$TIMESTAMP" "$RAW_BODY" \ | openssl dgst -sha256 -hmac "$SECRET" -binary \ | xxd -p -c 256) echo "Expected v1: $EXPECTED" ``` ### Output A lowercase hex signature (the expected to exactly match the `v1` value in the header). ``` -------------------------------- ### Error envelope JSON example Source: https://www.watchtraderhub.com/docs/api/errors Shows the JSON structure of an error response. The 'code' field is stable and should be used for matching, while 'message' may change between API versions. ```json { "error": { "type": "validation_error", "code": "missing_idempotency_key", "message": "Idempotency-Key header is required for this endpoint.", "doc_url": "https://www.watchtraderhub.com/docs/api/errors#missing_idempotency_key", "request_id": "req_…", "param": "Idempotency-Key" } } ``` -------------------------------- ### integration_org_missing Source: https://www.watchtraderhub.com/docs/api/errors Documentation for the integration_org_missing error, including causes and recovery. ```APIDOC ## Error: integration_org_missing ### Description The integration exists but is not attached to an organization. ### Error Code `integration_org_missing` ### HTTP Status 403 ### Error Type `permission_error` ### Recovery Contact support so the integration can be linked to your organization. Regenerating the key does not fix this. ``` -------------------------------- ### listing.published Source: https://www.watchtraderhub.com/docs/api/events Fires when the dealer toggles an inventory item ON for the custom channel. The data.object contains only the listing id and object type. ```APIDOC ## listing.published ### Description Fires when the dealer toggles an inventory item ON for the custom channel. ### Event Name listing.published ### data.object ``` { "id": "24f0ebb1-73d7-4e99-9901-821078594271", "object": "listing" } ``` ``` -------------------------------- ### invalid_api_key Source: https://www.watchtraderhub.com/docs/api/errors Documentation for the invalid_api_key error, including causes and recovery. ```APIDOC ## Error: invalid_api_key ### Description The key is well-formed but does not match any active integration. ### Error Code `invalid_api_key` ### HTTP Status 401 ### Error Type `authentication_error` ### Recovery Regenerate or copy the current key from /channels/custom, Settings → API credentials. ``` -------------------------------- ### Incremental sync with updated_after using curl Source: https://www.watchtraderhub.com/docs/api/pagination Fetches only the newest updates by passing a timestamp to the `updated_after` query parameter. The server returns rows where `updated_at > updated_after` in the same descending `updated_at` order, and `after` still works for paging through the filtered subset. ```bash curl -s "https://www.watchtraderhub.com/api/v1/listings?updated_after=2026-05-08T00:00:00Z" \ -H "Authorization: Bearer wth_YOUR_API_KEY" ``` -------------------------------- ### auth_lookup_failed Source: https://www.watchtraderhub.com/docs/api/errors Documentation for the auth_lookup_failed error, including causes and recovery. ```APIDOC ## Error: auth_lookup_failed ### Description A transient database error occurred while looking up the API key. ### Error Code `auth_lookup_failed` ### HTTP Status 401 ### Error Type `authentication_error` ### Recovery Retry the request after a short backoff. Persistent failures should be reported to support. ``` -------------------------------- ### Replay response with Idempotent-Replay header Source: https://www.watchtraderhub.com/docs/api/idempotency Shows the response returned when a request is replayed with the same Idempotency-Key and body. The Idempotent-Replay header is added and the original request_id is preserved. ```http HTTP/1.1 201 Created Idempotent-Replay: true X-Request-Id: req_70ab6f8aaa9945958b0564c337d6121e Content-Type: application/json { "id": "41296980-…", "object": "customer", … } ``` -------------------------------- ### listing.in_stock Source: https://www.watchtraderhub.com/docs/api/events Fires when a previously-sold listing returns to active stock (e.g. sale voided). The data.object contains only the listing id and object type. ```APIDOC ## listing.in_stock ### Description Fires when a previously-sold listing returns to active stock (e.g. sale voided). ### Event Name listing.in_stock ### data.object ``` { "id": "24f0ebb1-73d7-4e99-9901-821078594271", "object": "listing" } ``` ``` -------------------------------- ### listing.sold Source: https://www.watchtraderhub.com/docs/api/events Fires when a listing transitions to sold (either manually or via order matching). The data.object contains only the listing id and object type. ```APIDOC ## listing.sold ### Description Fires when a listing transitions to sold (either manually or via order matching). ### Event Name listing.sold ### data.object ``` { "id": "24f0ebb1-73d7-4e99-9901-821078594271", "object": "listing" } ``` ``` -------------------------------- ### missing_authorization Source: https://www.watchtraderhub.com/docs/api/errors Documentation for the missing_authorization error, including causes and recovery. ```APIDOC ## Error: missing_authorization ### Description No Authorization header was sent. This error occurs when the client does not include the `Authorization` header or a proxy strips it. ### Error Code `missing_authorization` ### HTTP Status 401 ### Error Type `authentication_error` ### Recovery Send `Authorization: Bearer wth_` on every request. ``` -------------------------------- ### integration_disabled Source: https://www.watchtraderhub.com/docs/api/errors Documentation for the integration_disabled error, including causes and recovery. ```APIDOC ## Error: integration_disabled ### Description The integration was paused by the dealer. ### Error Code `integration_disabled` ### HTTP Status 403 ### Error Type `permission_error` ### Recovery Re-enable the integration at /channels/custom, Settings → Activation & mode. ``` -------------------------------- ### subscription_required Source: https://www.watchtraderhub.com/docs/api/errors Documentation for the subscription_required error, including causes and recovery. ```APIDOC ## Error: subscription_required ### Description The dealer's plan does not include the custom integration. ### Error Code `subscription_required` ### HTTP Status 403 ### Error Type `permission_error` ### Recovery Ask the dealer to subscribe to the Business plan. API access resumes on the next request; no key change is needed. ``` -------------------------------- ### part.sold_out Source: https://www.watchtraderhub.com/docs/api/events Fires when a part reaches zero units, whether it was sold in WatchTraderHub or through a reported order. The part stays readable and its status reads sold_out. ```APIDOC ## part.sold_out ### Description Fires when a part reaches zero units, whether it was sold in WatchTraderHub or through a reported order. The part stays readable and its status reads sold_out. ### Event Name part.sold_out ### data.object ``` { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part", "status": "sold_out" } ``` ``` -------------------------------- ### part.in_stock data.object Source: https://www.watchtraderhub.com/docs/api/events Payload for the part.in_stock event. Contains the part id, object type, and the new quantity. ```json { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part", "quantity": 3 } ``` -------------------------------- ### Rate limit response headers Source: https://www.watchtraderhub.com/docs/api/rate-limits Every authenticated response includes these headers. Limit is the current cap (override or 600), Remaining is tokens left in the rolling window, and Reset is a Unix timestamp for full window reset. Check Remaining before firing the next burst and sleep until Reset minus a safety buffer when low. ```http X-RateLimit-Limit: 600 X-RateLimit-Remaining: 597 X-RateLimit-Reset: 1778230107 ``` -------------------------------- ### listing.updated Source: https://www.watchtraderhub.com/docs/api/events Fires when a published listing's data changes (price, photos, watch attributes, ...). The data.object contains only the listing id and object type. ```APIDOC ## listing.updated ### Description Fires when a published listing's data changes (price, photos, watch attributes, ...). ### Event Name listing.updated ### data.object ``` { "id": "24f0ebb1-73d7-4e99-9901-821078594271", "object": "listing" } ``` ### data.previous_attributes Reserved: currently always an empty object. Fetch the listing to read its current values. ``` -------------------------------- ### part.sold_out data.object Source: https://www.watchtraderhub.com/docs/api/events Payload for the part.sold_out event. Contains the part id, object type, and status sold_out. The part stays readable. ```json { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part", "status": "sold_out" } ``` -------------------------------- ### part.in_stock Source: https://www.watchtraderhub.com/docs/api/events Fires when a live part's stock count changes and it still has units: a restock, a return, a cancelled sale, a fit, or a partial sale. The new count is in quantity. ```APIDOC ## part.in_stock ### Description Fires when a live part's stock count changes and it still has units: a restock, a return, a cancelled sale, a fit, or a partial sale. The new count is in quantity. ### Event Name part.in_stock ### data.object ``` { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part", "quantity": 3 } ``` ``` -------------------------------- ### part.updated Source: https://www.watchtraderhub.com/docs/api/events Fires when a part already on the channel changes (price, quantity, photos, compatibility, ...). The data.object contains only the part id and object type. ```APIDOC ## part.updated ### Description Fires when a part already on the channel changes (price, quantity, photos, compatibility, ...). ### Event Name part.updated ### data.object ``` { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part" } ``` ``` -------------------------------- ### part.unpublished Source: https://www.watchtraderhub.com/docs/api/events Fires when the dealer takes a spare part OFF the custom channel. The part stops being readable once this arrives, so do not fetch it. ```APIDOC ## part.unpublished ### Description Fires when the dealer takes a spare part OFF the custom channel. The part stops being readable once this arrives, so do not fetch it. ### Event Name part.unpublished ### data.object ``` { "id": "9c2f0a71-5d18-4a5e-9b64-0f1c2e3d4a5b", "object": "part" } ``` ```