{"openapi":"3.1.0","info":{"title":"WidersApps API","version":"v1","description":"The WidersApps REST API: one bearer key, JSON in and out, and a single response envelope across contacts, conversations, messages, orders, products, and bookings. For authentication, scopes, pagination, idempotency, and webhook signatures, see the Guide."},"servers":[{"url":"https://console.widers.net"}],"paths":{"/api/v1/me":{"get":{"operationId":"accountApi.me","tags":["AccountApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"company":{"type":"object","properties":{"id":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","name"]},"scopes":{"type":"array","items":{}},"livemode":{"type":"boolean"}},"required":["company","scopes","livemode"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"401":{"description":"An error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview.","examples":[""]}},"required":["message"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-feedback":{"get":{"operationId":"conversations.ai-feedback.index","summary":"The thread's AI-reply feedback rows PAIRED to their outbound messages, in send order (a queue per identical\nbody) — so two byte-identical AI replies bind to their OWN rows and a human reply repeating an AI body can't\nsteal an unconsumed AI row. Exactly the pairing the web render does, keyed by the message's public_id","tags":["AiFeedbackApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"message_id":{"type":"string"},"feedback_id":{"type":"string"},"rating":{"type":"string"}},"required":["message_id","feedback_id","rating"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/ai-feedback/{feedback}/rate":{"post":{"operationId":"ai-feedback.rate","summary":"Rate an AI reply 👍/👎. `rating` must be 1 (up) or -1 (down); sending the currently-active rating again\nclears it (toggle off), mirroring the web. Returns the resulting `{rating: 1|-1|null}`","tags":["AiFeedbackApi"],"parameters":[{"name":"feedback","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"rating":{"type":"string","description":"Reject non-numeric input (e.g. an array `rating[]=1`) BEFORE casting — `(int) [1]` is 1 in PHP, which\n would otherwise sneak a malformed body through as an UP vote and skew the AI-reply quality metric."}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"rating":{"type":["integer","null"]}},"required":["rating"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-insights":{"get":{"operationId":"conversations.ai-insights","tags":["AiInsights"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"sentiment":{"type":["string","null"]},"purchase_likelihood":{"type":"string"},"current_intent":{"type":["object","null"],"properties":{"key":{"type":"string"},"label":{"type":"string"},"at":{"type":"string"}},"required":["key","label","at"]},"ai_ops":{"type":"array","items":{"type":"object","properties":{"text":{"type":"string"},"at":{"type":"string"}},"required":["text","at"]}}},"required":["sentiment","purchase_likelihood","current_intent","ai_ops"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-suggestions/generate":{"post":{"operationId":"conversations.ai-suggestions.generate","summary":"Generate + persist a fresh CONTEXT-AWARE pending set (reply/tag/tip). Returns `{available, created}`:\n`available:false` when the AI was unavailable (no key / budget spent / malformed — existing set kept);\notherwise `created` is how many were persisted (0 = «AI ran, nothing warranted» — a valid outcome)","tags":["AiSuggestionApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"object","properties":{"available":{"type":"boolean"},"created":{"type":"string"}},"required":["available","created"]},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"available":{"type":"boolean"},"created":{"type":"integer"}},"required":["available","created"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-suggestions":{"get":{"operationId":"conversations.ai-suggestions.index","summary":"The open thread's PENDING suggestions for the pane (a tag → its name + colour), newest first — the exact\nshape the web `aiSuggestions()` builds","tags":["AiSuggestionApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{"anyOf":[{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string","const":"tag"},"text":{"type":"string"},"color":{"type":"string"}},"required":["id","kind","text","color"]},{"type":"object","properties":{"id":{"type":"string"},"kind":{"type":"string"},"text":{"type":"string"},"color":{"type":"string"}},"required":["id","kind","text","color"]}]}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"array","items":{"type":"string"},"minItems":0,"maxItems":0},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-suggestions/history":{"get":{"operationId":"conversations.ai-suggestions.history","summary":"The thread's recent AI-suggestion HISTORY (all statuses) for the «AI activity» list — what the assistant\nproposed and what became of it. Newest first, fail-soft on a missing table. Mirrors web `aiSuggestionLog()`","tags":["AiSuggestionApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"label":{"type":"string"},"status":{"type":"string"},"at":{"type":"string"}},"required":["label","status","at"]}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"array","items":{"type":"string"},"minItems":0,"maxItems":0},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-suggestions/{suggestion}/approve":{"post":{"operationId":"conversations.ai-suggestions.approve","summary":"Approve a pending suggestion — human-in-the-loop, each acts by kind: a REPLY returns its text for the app to\npaste (never auto-sent), a TAG is attached to the thread server-side, a TIP is just acknowledged. Flips the\nrow to APPROVED with acted_by/at. Returns `{kind, text?}`; a foreign/consumed/other-thread id → 404","tags":["AiSuggestionApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}},{"name":"suggestion","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"kind":{"type":"string"},"text":{"type":"string"}},"required":["kind","text"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-suggestions/{suggestion}/dismiss":{"post":{"operationId":"conversations.ai-suggestions.dismiss","summary":"Dismiss a pending suggestion (no side effect) — tenant-scoped + thread-scoped + pending-only","tags":["AiSuggestionApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}},{"name":"suggestion","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"kind":{"type":"string"}},"required":["kind"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/bookings":{"get":{"operationId":"bookings.index","tags":["Bookings"],"parameters":[{"name":"from","in":"query","schema":{"type":"string"}},{"name":"to","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Array of `BookingResource`","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BookingResource"}}},"required":["data"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"List bookings"},"post":{"operationId":"bookings.store","tags":["Bookings"],"responses":{"201":{"description":"`BookingResource`","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BookingResource"}},"required":["data"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Create a booking"}},"/api/v1/availability":{"get":{"operationId":"bookings.availability","tags":["Bookings"],"parameters":[{"name":"agent_email","in":"query","schema":{"type":"string"}},{"name":"from","in":"query","schema":{"type":"string"}},{"name":"to","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"busy":{"type":"array","items":{"type":"object","properties":{"starts_at":{"type":"string"},"ends_at":{"type":"string"}},"required":["starts_at","ends_at"]}}},"required":["busy"]},{"type":"object","properties":{"busy":{"type":"array","items":{"type":"string"},"minItems":0,"maxItems":0}},"required":["busy"]}]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Check availability"}},"/api/v1/bookings/{booking}":{"get":{"operationId":"bookings.show","tags":["Bookings"],"parameters":[{"name":"booking","in":"path","required":true,"description":"The booking public id","schema":{"type":"string"}}],"responses":{"200":{"description":"`BookingResource`","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BookingResource"}},"required":["data"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Retrieve a booking"},"patch":{"operationId":"bookings.update","tags":["Bookings"],"parameters":[{"name":"booking","in":"path","required":true,"description":"The booking public id","schema":{"type":"string"}}],"responses":{"200":{"description":"`BookingResource`","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/BookingResource"}},"required":["data"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Update a booking"},"delete":{"operationId":"bookings.destroy","tags":["Bookings"],"parameters":[{"name":"booking","in":"path","required":true,"description":"The booking public id","schema":{"type":"string"}}],"responses":{"204":{"description":"No content"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Delete a booking"}},"/api/v1/broadcasting/auth":{"post":{"operationId":"broadcasting.auth","summary":"Authenticate the request for channel access","tags":["Broadcast"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object"}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/campaigns":{"get":{"operationId":"campaignApi.index","tags":["CampaignApi"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["draft","scheduled","queued","sending","paused","cancelling","cancelled","completed","failed"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"]}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/campaigns/{campaign}":{"get":{"operationId":"campaignApi.show","tags":["CampaignApi"],"parameters":[{"name":"campaign","in":"path","required":true,"description":"The campaign public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/campaigns/{campaign}/pause":{"post":{"operationId":"campaignApi.pause","tags":["CampaignApi"],"parameters":[{"name":"campaign","in":"path","required":true,"description":"The campaign public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/campaigns/{campaign}/resume":{"post":{"operationId":"campaignApi.resume","tags":["CampaignApi"],"parameters":[{"name":"campaign","in":"path","required":true,"description":"The campaign public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/campaigns/{campaign}/cancel":{"post":{"operationId":"campaignApi.cancel","tags":["CampaignApi"],"parameters":[{"name":"campaign","in":"path","required":true,"description":"The campaign public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/contacts":{"get":{"operationId":"contacts.index","tags":["Contacts"],"parameters":[{"name":"q","in":"query","schema":{"type":"string","maxLength":191}},{"name":"phone","in":"query","schema":{"type":"string","maxLength":32}},{"name":"country","in":"query","schema":{"type":"string","minLength":2,"maxLength":2}},{"name":"blocked","in":"query","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"subscribed","in":"query","schema":{"type":"string","enum":["1","0","true","false"]}},{"name":"sort","in":"query","schema":{"type":"string","enum":["created_at","name"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"]}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"List contacts"},"post":{"operationId":"contacts.store","tags":["Contacts"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":["string","null"],"maxLength":191},"phone":{"type":["string","null"],"maxLength":32},"email":{"type":["string","null"],"format":"email","maxLength":191},"country":{"type":["string","null"],"minLength":2,"maxLength":2},"subscribed":{"type":"boolean"},"source":{"type":["string","null"],"maxLength":20}}}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{},"phone":{"type":["string","null"]},"email":{"description":"sandbox mirrors the live E.164 output"},"country":{},"subscribed":{"type":"boolean"},"blocked":{"type":"boolean"},"source":{},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","name","phone","email","country","subscribed","blocked","source","created_at","updated_at"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Create a contact"}},"/api/v1/contacts/bulk-tag":{"post":{"operationId":"contacts.bulk_tag","summary":"Attach or detach ONE tag across several contacts in a single call — the native app's multi-select\n«إسناد وسم لعدة جهات اتصال». Tenant-scoped end to end (CLAUDE.md rule 1): the tag and every contact resolve\nTHROUGH the bound tenant, so a foreign/unknown public_id simply matches nothing (never leaks, never throws);\nthe attach/detach rides the history-aware, idempotent AttachesTags service; sandbox reports the summary\nwithout a write. Returns a summary — requested vs affected — never the (potentially large) contact list","tags":["Contacts"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_ids":{"type":"array","items":{"type":"string","maxLength":26},"minItems":1,"maxItems":500},"tag":{"type":"string","maxLength":26},"action":{"type":"string","enum":["add","remove"]}},"required":["contact_ids","tag"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"action":{"type":"string"},"tag":{"type":"string"},"requested":{"type":"integer"},"affected":{"type":"integer","minimum":0}},"required":["action","tag","requested","affected"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/contacts/{contact}":{"get":{"operationId":"contacts.show","tags":["Contacts"],"parameters":[{"name":"contact","in":"path","required":true,"description":"The contact public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Retrieve a contact"},"patch":{"operationId":"contacts.update","tags":["Contacts"],"parameters":[{"name":"contact","in":"path","required":true,"description":"The contact public id","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":["string","null"],"maxLength":191},"phone":{"type":["string","null"],"maxLength":32},"email":{"type":["string","null"],"format":"email","maxLength":191},"country":{"type":["string","null"],"minLength":2,"maxLength":2},"subscribed":{"type":"boolean"},"blocked":{"type":"boolean"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Update a contact"},"delete":{"operationId":"contacts.destroy","tags":["Contacts"],"parameters":[{"name":"contact","in":"path","required":true,"description":"The contact public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Delete a contact"}},"/api/v1/contacts/{contact}/notes":{"get":{"operationId":"contacts.notes","summary":"A contact's internal-note log — every ConversationEvent(InternalNote) recorded on the contact's threads,\nnewest-first (the SAME shared log the inbox note tab, the contact-detail «notes» tab, and a flow's add_note\naction write). Read-only, gated on contacts.view, tenant-scoped by the bound token. The shape is\n{ author, text, at }: `author` the agent's display name (or a system label), `at` an ISO-8601 timestamp.\nThe internal event id is never exposed (CLAUDE.md — the bigint stays private; the note list needs no key)","tags":["Contacts"],"parameters":[{"name":"contact","in":"path","required":true,"description":"The contact public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string"},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations":{"get":{"operationId":"conversations.index","tags":["Conversations"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["open","closed"]}},{"name":"assignee","in":"query","schema":{"type":"string","maxLength":191}},{"name":"channel","in":"query","description":"an agent email, or \"me\"","schema":{"type":"string","maxLength":30}},{"name":"tag","in":"query","schema":{"type":"string","maxLength":26}},{"name":"contact","in":"query","schema":{"type":"string","maxLength":26}},{"name":"q","in":"query","schema":{"type":"string","maxLength":191}},{"name":"archived","in":"query","description":"free-text: contact name/phone + message body","schema":{"type":"string","enum":["0","1","true","false"]}},{"name":"unassigned","in":"query","description":"absent = ALL (unchanged contract); false = active inbox; true = archived only","schema":{"type":"string","enum":["0","1","true","false"]}},{"name":"read","in":"query","description":"true = no assigned agent (the «غير مسندة» filter)","schema":{"type":"string","enum":["0","1","true","false"]}},{"name":"muted","in":"query","description":"true = read (unread_count=0); false = has unread","schema":{"type":"string","enum":["0","1","true","false"]}},{"name":"period","in":"query","description":"true = currently muted; false = not muted","schema":{"type":"string","enum":["today","week","month"]}},{"name":"rating","in":"query","description":"by last activity (last_message_at), mirrors the web","schema":{"type":"integer","minimum":1,"maximum":5}},{"name":"limit","in":"query","description":"exact CSAT rating (customer-set)","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"},"total_unread":{"type":"integer","minimum":0}},"required":["next_cursor","has_more","total_unread"]}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"List conversations"}},"/api/v1/conversations/bulk":{"post":{"operationId":"conversations.bulk","description":"The `conversation_ids` are resolved in ONE tenant-scoped query, so a foreign / unknown public_id simply\nnever matches (fail-closed — never leaks, never 404s the whole batch). Capped at 200 ids per call so a\nrunaway client can't fan out unbounded work. Returns a summary (requested / affected / unknown), not N\nfull conversation payloads — the client re-fetches the list to reconcile order + state.","summary":"Apply ONE action to MANY conversations at once (the app's / inbox's «select + bulk-act» surface): mark\nread/unread, close/open, assign/unassign, mute/unmute. Same `inbox.access` gate and same sandbox\nshort-circuit as the single-thread mutations, delegating each to the idempotent ConversationActions","tags":["Conversations"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"conversation_ids":{"type":"array","items":{"type":"string","maxLength":26},"minItems":1,"maxItems":200},"action":{"type":"string","enum":["read","unread","close","open","assign","unassign","mute","unmute","tag","untag"]},"assignee":{"type":"string","maxLength":191},"tag":{"type":"string","description":"\"me\" or an agent email","maxLength":26},"until":{"type":["string","null"],"format":"date-time","description":"the tag public_id to attach/detach"}},"required":["conversation_ids","action"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"action":{"type":"string"},"requested":{"type":"integer"},"affected":{"type":"string"},"unknown":{}},"required":["action","requested","affected","unknown"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}":{"get":{"operationId":"conversations.show","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Retrieve a conversation"}},"/api/v1/conversations/{conversation}/timeline":{"get":{"operationId":"conversations.timeline","summary":"The merged conversation timeline the native agent app renders — messages + private notes + lifecycle\nevents in one ordered stream (richer than a plain message list: failure reason, quoted-reply snippet and\nthe authoring agent). Paginates OLDER via a single `before` timestamp; the client dedupes by entry id","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"before","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string"},"meta":{"type":"array","items":{}}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/flush-held":{"post":{"operationId":"conversations.flush-held","summary":"Flush this thread's HELD reply batch NOW — send the accumulated «الردود» batch (فيتشر ١). The native composer\ncalls this when the agent stops typing (idle) or leaves the thread, mirroring the web composer's idle/leave\nflush; the per-conversation backstop job is the crash-safe fallback. `inbox.access`, visibility-gated,\nsandbox-safe; idempotent — a repeat flush finds nothing, and it can never double-send with the backstop","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"flushed":{"type":"boolean"}},"required":["flushed"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/assign":{"post":{"operationId":"conversations.assign","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"assignee":{"type":"string","maxLength":191}},"required":["assignee"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Assign a conversation"}},"/api/v1/conversations/{conversation}/unassign":{"post":{"operationId":"conversations.unassign","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Unassign a conversation"}},"/api/v1/conversations/{conversation}/close":{"post":{"operationId":"conversations.close","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Close a conversation"}},"/api/v1/conversations/{conversation}/reopen":{"post":{"operationId":"conversations.reopen","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Reopen a conversation"}},"/api/v1/conversations/{conversation}/read":{"post":{"operationId":"conversations.read","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Mark a conversation read"}},"/api/v1/conversations/{conversation}/unread":{"post":{"operationId":"conversations.unread","summary":"Flag the thread «to handle later» — re-surfaces it in the unread filter (mirror of read())","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/mute":{"post":{"operationId":"conversations.mute","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"until":{"type":["string","null"],"format":"date-time"}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Mute a conversation"}},"/api/v1/conversations/{conversation}/unmute":{"post":{"operationId":"conversations.unmute","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Unmute a conversation"}},"/api/v1/conversations/{conversation}/archive":{"post":{"operationId":"conversations.archive","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Archive a conversation"}},"/api/v1/conversations/{conversation}/unarchive":{"post":{"operationId":"conversations.unarchive","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Unarchive a conversation"}},"/api/v1/conversations/{conversation}/pin":{"post":{"operationId":"conversations.pin","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/unpin":{"post":{"operationId":"conversations.unpin","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/follow":{"post":{"operationId":"conversations.follow","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Follow a conversation"}},"/api/v1/conversations/{conversation}/unfollow":{"post":{"operationId":"conversations.unfollow","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Unfollow a conversation"}},"/api/v1/conversations/{conversation}/notes":{"post":{"operationId":"conversations.notes","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","maxLength":2000},"mentions":{"type":["array","null"],"description":"agent EMAILS to @mention (the app's «@» picker). `nullable` so absent / null / [] all mean «no\nmentions» — an explicit JSON null must not 422 the whole note (some clients encode empty as null).","items":{"type":"string","format":"email","maxLength":191},"maxItems":50}},"required":["body"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Add an internal note"}},"/api/v1/conversations/{conversation}/tags":{"post":{"operationId":"conversations.tags.attach","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tag":{"type":"string","maxLength":26}},"required":["tag"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Attach a tag"}},"/api/v1/conversations/{conversation}/tags/{tag}":{"delete":{"operationId":"conversations.tags.detach","tags":["Conversations"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}},{"name":"tag","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Detach a tag"}},"/api/v1/conversations/{conversation}/presence":{"get":{"operationId":"conversations.presence.show","tags":["ConversationPresenceApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"conversation":{"type":"string"},"locked":{"type":"boolean"},"locked_by_other":{"type":"string"},"editing_by":{"type":["string","null"]},"is_me":{"type":"string"}},"required":["conversation","locked","locked_by_other","editing_by","is_me"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"conversations.presence.update","tags":["ConversationPresenceApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["claim","release"]},"typing":{"type":"boolean","description":"The composer heartbeat sets typing=true while the agent is actively composing — drives the customer's\n«agent is typing…» dots (owner #٣, recommended OFF): our-own-channel dots via the AGENT flag, and a\nthrottled provider-side indicator to the customer's phone on WhatsApp. Same behaviour as the web composer."}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"conversation":{"type":"string"},"locked":{"type":"boolean"},"locked_by_other":{"type":"string"},"editing_by":{"type":["string","null"]},"is_me":{"type":"string"}},"required":["conversation","locked","locked_by_other","editing_by","is_me"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/dealchat/reply-templates":{"get":{"operationId":"dealchat.reply-templates.index","tags":["DealChatReplyTemplate"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"}},"required":["id","title","body"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/messages/{message}/email-body":{"get":{"operationId":"messages.email_body","tags":["EmailBodyApi"],"parameters":[{"name":"message","in":"path","required":true,"description":"The message public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"subject":{"type":["string","null"]},"has_html":{"type":"string"},"html":{"type":"string","description":"The full <!doctype html> document (sanitized body + inline styles + strict CSP meta) — the app\nhands this straight to a WKWebView; nothing further to assemble on the client."}},"required":["id","subject","has_html","html"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/events":{"get":{"operationId":"eventApi.index","summary":"The subscribable event topics for this token — name, localized label, group, and governing scope","tags":["EventApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"401":{"description":"An error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview.","examples":[""]}},"required":["message"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/events/{topic}/samples":{"get":{"operationId":"eventApi.samples","summary":"Recent delivery envelopes for one topic — sample/poll data. 404 for an unknown or non-public topic,\n403 when the token lacks the topic's scope; otherwise the latest few envelopes exactly as delivered","tags":["EventApi"],"parameters":[{"name":"topic","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":{}}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"401":{"description":"An error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview.","examples":[""]}},"required":["message"]}}}},"403":{"description":"An error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview.","examples":[""]}},"required":["message"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-suggest":{"post":{"operationId":"conversations.ai-suggest","tags":["InboxAiSuggest"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"object","properties":{"available":{"type":"boolean"},"reply":{"type":"string"},"tip":{"type":"string"}},"required":["available","reply","tip"]},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"available":{"type":"boolean"},"reply":{"type":"null"},"tip":{"type":"null"}},"required":["available","reply","tip"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/ai-summary":{"post":{"operationId":"conversations.ai-summary","tags":["InboxAiSummary"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"object","properties":{"available":{"type":"boolean"},"summary":{"type":"string"}},"required":["available","summary"]},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"available":{"type":"boolean"},"summary":{"type":"null"}},"required":["available","summary"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/flows":{"get":{"operationId":"flows.index","summary":"GET /flows — the tenant's LIVE flows (published + an active version), for the run-flow picker. Reads\nTHROUGH the tenant scope (BelongsToTenant), so a token only ever sees its own company's flows","tags":["InboxFlow"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}},"required":["id","name"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/run-flow":{"post":{"operationId":"conversations.run-flow","summary":"POST /conversations/{conversation}/run-flow {flow: <public_id>} — start the live flow on this thread.\nReturns an HONEST outcome, none of which is a client error (the app shows a plain notice):\n  running   — the engine started the flow (now waiting on the customer / completed a send leg)\n  completed — the flow ran to its end\n  error     — the flow stopped on a node error\n  blocked   — a flow already owns this conversation (parked/paused) — start() refused to clobber it\n  busy      — another worker holds the per-conversation lock right now\nA non-live / foreign flow id is a 422 (the only real client error)","tags":["InboxFlow"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"flow":{"type":"string","maxLength":26}},"required":["flow"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","enum":["running","completed","error"]},"started":{"type":"boolean"}},"required":["status","started"]},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","const":"blocked"},"started":{"type":"boolean"}},"required":["status","started"]},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","const":"busy"},"started":{"type":"boolean"}},"required":["status","started"]},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"status":{"type":"string","const":"running"},"started":{"type":"boolean"}},"required":["status","started"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/media":{"get":{"operationId":"media.index","summary":"The tenant's media library — the previously-uploaded assets the native app's «مكتبة الوسائط» browses to\nre-send without re-uploading. Reads THROUGH the tenant scope (BelongsToTenant), newest first, keyset-paged\non created_at, optionally narrowed to one `kind` (image/video/audio/document). Each row's `url` is the same\ncapability URL POST /media returns, usable directly as `media_url` on POST /messages","tags":["MediaApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"mime":{"type":"string"},"kind":{"type":"string"},"size":{"type":"integer"},"name":{"type":"string"}},"required":["id","url","mime","kind","size","name"]}},"meta":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"]}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"media.store","tags":["MediaApi"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","contentMediaType":"application/octet-stream","description":"Extension-aware format gate ({@see MetaMediaFormats::uploadAllowed}): a real Office document that\ncontent-sniffs as a bare container (.xls → x-ole-storage, .xlsx → zip) is accepted by its extension,\nwhile a renamed binary (unknown extension + non-allowed sniff) is still rejected."}},"required":["file"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"mime":{"type":"string"},"kind":{"type":"string"},"size":{"type":"string"}},"required":["id","url","mime","kind","size"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/messages":{"get":{"operationId":"messages.index","tags":["Messages"],"parameters":[{"name":"conversation","in":"query","schema":{"type":"string","maxLength":26}},{"name":"contact","in":"query","schema":{"type":"string","maxLength":26}},{"name":"occurred_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"occurred_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"direction","in":"query","schema":{"type":"string","enum":["inbound","outbound"]}},{"name":"q","in":"query","schema":{"type":"string","maxLength":191}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"]}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"List messages"},"post":{"operationId":"messages.store","tags":["Messages"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","maxLength":30},"contact_id":{"type":"string","maxLength":26},"type":{"type":"string","enum":[""]},"text":{"type":["string","null"],"maxLength":4096},"template_name":{"type":["string","null"],"maxLength":191},"template_language":{"type":["string","null"],"maxLength":20},"template_values":{"type":"array","items":{"type":"string"}},"media_url":{"type":["string","null"],"description":"body[]/header/buttons/card_headers/… (TemplateValues::fromArray)","maxLength":2048},"media_mime":{"type":["string","null"],"maxLength":127},"media_name":{"type":["string","null"],"maxLength":255},"reply_to":{"type":["string","null"],"description":"DOCUMENT display name (WhatsApp document.filename)","maxLength":26},"batch":{"type":"boolean","description":"public_id of a message in this thread to quote"},"subject":{"type":["string","null"],"description":"فيتشر ١ «الردود»: HOLD+MERGE this WhatsApp text reply into the open batch","maxLength":255},"attachments":{"type":"array","description":"EMAIL only: the reply's subject line","items":{"type":"string","description":"EMAIL only: MediaAsset public_ids (POST /media)","maxLength":26},"maxItems":10}},"required":["channel","contact_id"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"conversation_id":{"type":"null"},"contact_id":{"type":["string","null"]},"channel":{"type":["string","null"]},"direction":{"type":"string"},"type":{"anyOf":[{"type":"string"},{"type":"string","enum":["text"]}]},"status":{"type":"string"},"body":{"type":["string","null"]},"media_mime":{"type":["string","null"]},"media_url":{"type":["string","null"]},"occurred_at":{"type":"string"}},"required":["id","conversation_id","contact_id","channel","direction","type","status","body","media_mime","media_url","occurred_at"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Create a message"}},"/api/v1/messages/{message}":{"get":{"operationId":"messages.show","tags":["Messages"],"parameters":[{"name":"message","in":"path","required":true,"description":"The message public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Retrieve a message"}},"/api/v1/messages/{message}/react":{"post":{"operationId":"messages.react","summary":"React to a message with a curated emoji — the agent puts a reaction ON the {message}, delivered the WhatsApp\nway (a `reaction`, not a bubble). Re-sending the SAME emoji the agent already put here REMOVES it (a toggle,\nan empty emoji to Meta). Mirrors the web inbox's react() gate-for-gate: reactions-enabled, WhatsApp-only, the\n24h window OPEN, ONLY the curated set (a forged emoji is refused), and a resolvable target wamid. A reaction\nis a real outbound send (gated `inbox.access`, visibility-scoped, sandbox-safe) but never lifts the thread and\nnever pauses a running flow (it annotates a past message; it is not a reply the AI should hold back for)","tags":["Messages"],"parameters":[{"name":"message","in":"path","required":true,"description":"The message public id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emoji":{"type":"string","enum":["👍","❤️","😂","😮","😢","🙏"]}},"required":["emoji"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"conversation_id":{"type":"string"},"contact_id":{"type":"string"},"channel":{"type":"string"},"direction":{"type":"string"},"type":{"type":"string","const":"reaction"},"status":{"type":"string"},"body":{"type":"string"},"media_mime":{"type":"null"},"media_url":{"type":"null"},"occurred_at":{"type":"string"}},"required":["id","conversation_id","contact_id","channel","direction","type","status","body","media_mime","media_url","occurred_at"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/orders":{"get":{"operationId":"orders.index","tags":["Orders"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["pending","awaiting_payment","partially_paid","paid","processing","in_progress","shipped","ready_for_pickup","fulfilled","delivered","cancelled","refunded"]}},{"name":"created_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"created_before","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"contact","in":"query","schema":{"type":"string","maxLength":26}},{"name":"fulfilment_method","in":"query","schema":{"type":"string","enum":["delivery","pickup"]}},{"name":"sort","in":"query","schema":{"type":"string","enum":["created_at","number"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"]}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"List orders"},"post":{"operationId":"orders.store","tags":["Orders"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":["string","null"],"maxLength":26},"items":{"type":"array","items":{"type":"object","properties":{"product_id":{"type":"string","maxLength":26},"quantity":{"type":"integer","minimum":1},"variant_id":{"type":["string","null"],"maxLength":26}},"required":["product_id","quantity"]},"minItems":1},"currency":{"type":"string","minLength":3,"maxLength":3},"source":{"type":"string","maxLength":32},"notes":{"type":["string","null"],"maxLength":2000},"customer_name":{"type":["string","null"],"maxLength":191},"customer_phone":{"type":["string","null"],"maxLength":32},"customer_email":{"type":["string","null"],"format":"email","maxLength":191},"coupon_code":{"type":["string","null"],"maxLength":64},"shipping_minor":{"type":"integer","minimum":0},"fulfilment_method":{"type":"string","enum":["delivery","pickup"]}},"required":["items"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"number":{"type":"integer"},"status":{"type":"string"},"currency":{"type":"string"},"subtotal_minor":{"type":"number"},"discount_minor":{"type":"integer"},"shipping_minor":{"type":"integer"},"tax_minor":{"type":"integer"},"cod_fee_minor":{"type":"integer"},"gift_wrap_minor":{"type":"integer"},"wallet_minor":{"type":"integer"},"total_minor":{"type":"number"},"fulfilment_method":{"type":"string"},"shipping_carrier":{"type":"null"},"contact_id":{"type":"null"},"customer_name":{},"customer_phone":{"type":["string","null"]},"customer_email":{"description":"sandbox mirrors live E.164"},"source":{},"payment_method":{"type":"null"},"paid_at":{"type":"null"},"placed_at":{"type":"string"},"created_at":{"type":"string"},"items":{"type":"array","items":{}}},"required":["id","number","status","currency","subtotal_minor","discount_minor","shipping_minor","tax_minor","cod_fee_minor","gift_wrap_minor","wallet_minor","total_minor","fulfilment_method","shipping_carrier","contact_id","customer_name","customer_phone","customer_email","source","payment_method","paid_at","placed_at","created_at","items"]},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Create a order"}},"/api/v1/orders/{order}":{"get":{"operationId":"orders.show","tags":["Orders"],"parameters":[{"name":"order","in":"path","required":true,"description":"The order public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Retrieve a order"}},"/api/v1/orders/{order}/status":{"patch":{"operationId":"orders.status","tags":["Orders"],"parameters":[{"name":"order","in":"path","required":true,"description":"The order public id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","awaiting_payment","partially_paid","paid","processing","in_progress","shipped","ready_for_pickup","fulfilled","delivered","cancelled","refunded"]},"note":{"type":["string","null"],"maxLength":1000}},"required":["status"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Update order status"}},"/api/v1/products":{"get":{"operationId":"products.index","tags":["Products"],"parameters":[{"name":"status","in":"query","schema":{"type":"string","enum":["draft","active","archived"]}},{"name":"type","in":"query","schema":{"type":"string","enum":["physical","digital","donation","subscription","gift_card","bundle","bookable"]}},{"name":"category","in":"query","schema":{"type":"string","maxLength":26}},{"name":"sort","in":"query","schema":{"type":"string","enum":["created_at","name"]}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"cursor","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"]}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"List products"},"post":{"operationId":"products.store","tags":["Products"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"description":{"type":["string","null"],"maxLength":5000},"type":{"type":"string","enum":["physical","digital","donation","subscription","gift_card","bundle","bookable"]},"status":{"type":"string","enum":["draft","active","archived"]},"price_minor":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"track_stock":{"type":"boolean"},"stock":{"type":"integer","minimum":0}},"required":["name","type","price_minor"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"200":{"description":"","content":{"application/json":{"schema":{"type":"string"}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Create a product"}},"/api/v1/products/{product}":{"get":{"operationId":"products.show","tags":["Products"],"parameters":[{"name":"product","in":"path","required":true,"description":"The product public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Retrieve a product"},"patch":{"operationId":"products.update","tags":["Products"],"parameters":[{"name":"product","in":"path","required":true,"description":"The product public id","schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"description":{"type":["string","null"],"maxLength":5000},"status":{"type":"string","enum":["draft","active","archived"]},"price_minor":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"track_stock":{"type":"boolean"},"stock":{"type":"integer","minimum":0}}}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"string"},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}},"summary":"Update a product"}},"/api/v1/quick-replies":{"get":{"operationId":"quick-replies.index","tags":["QuickReplyApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"}},"required":["id","title","body"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"quick-replies.store","summary":"Create a quick reply from the native app (the owner's «create quick reply from the app» ask). Gated on\n`quick-replies.manage` — the same permission the web manager enforces — so an agent-only token is refused,\none privilege system. `company_id` is stamped by BelongsToTenant from the bound tenant (never client-set)","tags":["QuickReplyApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","maxLength":120},"body":{"type":"string","maxLength":5000}},"required":["title","body"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"}},"required":["id","title","body"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/stickers":{"get":{"operationId":"stickers.index","tags":["StickerApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"mime":{"type":"string"}},"required":["id","url","mime"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"stickers.store","description":"The source is then re-encoded to a WhatsApp-compliant STATIC sticker (512×512 webp, ≤100 KB) so the tray\nonly ever holds SENDABLE stickers — a tray send can't fail on Meta's size cap. Idempotent on the normalized\nbytes: re-saving the same sticker (a double-tap) returns the existing tray row and stores no second asset.","summary":"Save a sticker into the tray. The app first uploads the source bytes through the audited POST /media funnel\n(quota + finfo allowlist) and passes the resulting asset's public_id here — we DON'T fetch an arbitrary\nURL server-side (no SSRF surface). The asset is resolved THROUGH the tenant scope, so a foreign/unknown id\nis refused","tags":["StickerApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"media_id":{"type":"string","maxLength":26}},"required":["media_id"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"url":{"type":"string"},"mime":{"type":"string"}},"required":["id","url","mime"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/stickers/{sticker}":{"delete":{"operationId":"stickers.destroy","summary":"Remove a sticker from the tray (the shared webp asset is left in the library). Tenant-scoped by public_id","tags":["StickerApi"],"parameters":[{"name":"sticker","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":["deleted"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/tags":{"get":{"operationId":"tags.index","tags":["TagApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"},"is_system":{"type":"boolean"}},"required":["id","name","color","is_system"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"tags.store","summary":"Create a tag from the native app (the owner's «create tags from the app» ask). Gated on `tags.manage` —\nthe same permission the web manager enforces — so an agent-only token is refused. `is_system` is never\nfillable (a tenant can't forge a smart tag), and `company_id` is stamped by BelongsToTenant. English-name\nuniqueness is enforced within the bound company, matching the web","tags":["TagApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name_en":{"type":"string","maxLength":60},"name_ar":{"type":["string","null"],"maxLength":60},"color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},"description":{"type":["string","null"],"maxLength":255}},"required":["name_en","color"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"},"is_system":{"type":"boolean","description":"A freshly-created tag is never a system tag; coerce (the DB default isn't reflected on the\nin-memory model until a refresh)."}},"required":["id","name","color","is_system"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/tags/{tag}":{"patch":{"operationId":"tags.update","summary":"Rename / recolour a company tag from the app's tag manager. Gated on `tags.manage`; the {tag} binding is\ntenant-scoped (a foreign public_id 404s). A SYSTEM tag is never editable here — its fields are fixed —\nmatching the web manager's 403. English-name uniqueness is re-checked excluding this row","tags":["TagApi"],"parameters":[{"name":"tag","in":"path","required":true,"description":"The tag public id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name_en":{"type":"string","maxLength":60},"name_ar":{"type":["string","null"],"maxLength":60},"color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$"},"description":{"type":["string","null"],"maxLength":255}},"required":["name_en","color"]}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"color":{"type":"string"},"is_system":{"type":"boolean"}},"required":["id","name","color","is_system"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}},"delete":{"operationId":"tags.destroy","summary":"Delete a company tag (detaching it from any thread). Gated on `tags.manage`; the {tag} binding is\ntenant-scoped. A SYSTEM tag can never be deleted — the model's `deleting` hook also refuses it (fail-closed\nat both layers), so a forged attempt is a clean 422, never a 500","tags":["TagApi"],"parameters":[{"name":"tag","in":"path","required":true,"description":"The tag public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"deleted":{"type":"boolean"}},"required":["deleted"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/templates":{"get":{"operationId":"templates.index","tags":["TemplateApi"],"parameters":[{"name":"channel","in":"query","required":true,"schema":{"type":"string","maxLength":30}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]},{"type":"object","properties":{"data":{"type":"array","items":{"type":"string"},"minItems":0,"maxItems":0},"meta":{"type":"string"}},"required":["data","meta"]}]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/conversations/{conversation}/variables":{"get":{"operationId":"conversations.variables","tags":["VariableApi"],"parameters":[{"name":"conversation","in":"path","required":true,"description":"The conversation public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"value":{"type":"string"},"is_system":{"type":"boolean"}},"required":["key","label","value","is_system"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/webhooks":{"get":{"operationId":"webhookApi.index","summary":"The integrator's active + inactive subscriptions for this tenant (never the secret)","tags":["WebhookApi"],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"active":{"type":"boolean"},"last_delivered_at":{"type":["string","null"]}},"required":["id","name","url","events","active","last_delivered_at"]}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}},"post":{"operationId":"webhookApi.store","summary":"Subscribe a public https endpoint to one or more event topics (Zapier's REST-Hook \"subscribe\"). Refused\nunless the token holds every subscribed topic's governing scope. Returns the subscription plus the\nplaintext signing secret — the only moment it is ever visible","tags":["WebhookApi"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048},"events":{"type":"array","items":{"type":"string","enum":["contact.created","order.created","contact.updated","order.paid","contact.blocked","order.shipped","contact.unblocked","order.ready_for_pickup","contact.tagged","order.delivered","contact.untagged","order.cancelled","contact.deleted","order.refunded","cart.abandoned","product.created","product.updated","booking.created","booking.updated","booking.cancelled","booking.confirmed","campaign.completed","message.received","campaign.failed","message.sent","conversation.created","conversation.assigned","conversation.transferred","conversation.closed","conversation.reopened","conversation.muted","conversation.unmuted","conversation.archived","conversation.unarchived","conversation.tagged","conversation.untagged","message.delivered","message.read","message.failed","conversation.unassigned"]},"minItems":1},"name":{"type":["string","null"],"maxLength":120}},"required":["url","events"]}}}},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{}},"meta":{"type":"string"}},"required":["data","meta"]}}}},"401":{"description":"An error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview.","examples":[""]}},"required":["message"]}}}},"403":{"description":"An error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview.","examples":[""]}},"required":["message"]}}}},"422":{"$ref":"#/components/responses/ValidationException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}},"/api/v1/webhooks/{webhook}":{"delete":{"operationId":"webhookApi.destroy","summary":"Unsubscribe (Zapier's REST-Hook \"unsubscribe\"). Tenant-scoped by public_id — a foreign id already 404'd","tags":["WebhookApi"],"parameters":[{"name":"webhook","in":"path","required":true,"description":"The webhook public id","schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean"}},"required":["id","deleted"]},"meta":{"type":"string"}},"required":["data","meta"]}}}},"404":{"$ref":"#/components/responses/ModelNotFoundException"},"default":{"$ref":"#/components/responses/Error"},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"409":{"$ref":"#/components/responses/Error"},"422":{"$ref":"#/components/responses/Error"},"429":{"$ref":"#/components/responses/Error"},"500":{"$ref":"#/components/responses/Error"}}}}},"components":{"schemas":{"BookingResource":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"starts_at":{"type":"string"},"ends_at":{"type":"string"},"status":{"type":"string"},"location":{"type":["string","null"]},"notes":{"type":["string","null"]},"contact_id":{"type":["string","null"]},"agent_email":{"type":["string","null"]},"source":{"type":"string"},"created_at":{"type":["string","null"]}},"required":["id","title","starts_at","ends_at","status","location","notes","contact_id","agent_email","source","created_at"],"title":"BookingResource"},"ApiError":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["type","code","message","request_id"],"properties":{"type":{"type":"string","enum":["invalid_request_error","authentication_error","authorization_error","idempotency_error","rate_limit_error","api_error"],"description":"Coarse error family."},"code":{"type":"string","enum":["bad_request","validation_failed","unauthenticated","forbidden","not_found","method_not_allowed","not_acceptable","conflict","idempotency_conflict","payload_too_large","rate_limited","server_error"],"description":"Stable machine-readable error code."},"message":{"type":"string","description":"Human-readable, localised message."},"param":{"type":"string","nullable":true,"description":"Offending input field, when relevant."},"request_id":{"type":"string","description":"Correlation id, also on the X-Request-Id header."}}}}}},"responses":{"ValidationException":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Errors overview."},"errors":{"type":"object","description":"A detailed description of each field that failed validation.","additionalProperties":{"type":"array","items":{"type":"string"}}}},"required":["message","errors"]}}}},"ModelNotFoundException":{"description":"Not found","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error overview."}},"required":["message"]}}}},"Error":{"description":"Uniform error envelope. `code` is a stable machine-readable contract; `request_id` echoes the X-Request-Id header for support.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key issued in Settings → Developers. Send it as `Authorization: Bearer wa_live_<id>|<token>` (or `wa_test_…` for the sandbox)."}}},"tags":[{"name":"Contacts","description":"Create, read, update, and delete the people you talk to."},{"name":"Conversations","description":"Read threads and manage their lifecycle — assign, close, tag, and more."},{"name":"Messages","description":"List, read, and send messages across your connected channels."},{"name":"Orders","description":"List and read orders, create them, and advance their status."},{"name":"Products","description":"Read your catalog to reference products by id."},{"name":"Bookings","description":"Manage calendar bookings (uses the legacy authentication)."}],"security":[{"bearerAuth":[]}]}