Quick replies
A quick reply is a saved snippet an agent inserts into the composer. It is not a template: nothing is submitted for approval, nothing is sent by this section, and the text is ordinary free text.
The quick reply
One entry carries BOTH language bodies and at least one of them must be present. That is deliberate: the server never picks a language, because the composer knows the contact's locale and the API does not. Approved message templates are a different thing entirely — see templates.
| Field | Type | Description |
|---|---|---|
| shortcut | string | What an agent types after the slash. Unique in the workspace. |
| title | string | The human label in the library. |
| body_en, body_ar | string | null | The English and Arabic bodies. Either may be null, but not both. |
| sort_order | number | The operator's arrangement. The server owns the value; do not compute one. |
| use_count, last_used_at | number, string | null | How often it has been inserted, and when it last was. |
Pick the language on the client
Read the contact's locale, take that body, and fall back to the OTHER language rather than to nothing — a reply in the wrong language is more useful than an empty composer. Note that the conversation's embedded contact carries no locale, so resolving it needs a contact read.
Authentication and scopes
No permission was minted for quick replies; they reuse three existing ones. An agent can therefore read and use them and cannot manage them.
| Scope | Used for |
|---|---|
| messages.read | List and read. |
| templates.manage | Create, update, delete and reorder. |
| messages.send | Record a use. |
Endpoints
curl -X POST https://whats.azzamkh.sa/api/v1/quick-replies \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"shortcut": "hours",
"title": "Opening hours",
"body_en": "We reply Sunday to Thursday, 9am to 5pm.",
"body_ar": "نرد من الأحد إلى الخميس، 9 صباحًا حتى 5 مساءً."
}'
# 201 Created
# {
# "id": "qr_...",
# "shortcut": "hours",
# "title": "Opening hours",
# "body_en": "...",
# "body_ar": "...",
# "sort_order": 30,
# "use_count": 0,
# "last_used_at": null,
# ...
# }
# Search is a PREFIX match on the shortcut, not a search over titles:
curl "https://whats.azzamkh.sa/api/v1/quick-replies?q=hou" \
-H "Authorization: Bearer $WA_API_KEY"
# Clearing ONE language is an explicit null. Omitting the field leaves it.
curl -X PATCH https://whats.azzamkh.sa/api/v1/quick-replies/qr_... \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "body_en": null }'Behaviour worth knowing
?q=is a PREFIX match on the shortcut, not a fuzzy search over titles. Prefix is what makes typing deterministic.- The list comes back in the operator's order, paged on
(sort_order, public_id). Render it as received; do not sort in the client.PATCH /v1/quick-replies/ordertakes ORDERED IDS rather than positions, precisely so no client computes its own. - On
PATCH,nullclears one language and an absent field leaves it alone. The empty string is not a legal body, so emptying a field must be sent asnullor the edit is silently dropped. POST …/useis bookkeeping only — it sends nothing. Send the message through the conversation as usual, then record the use.- Creating and using are rate limited per workspace: 120 creates a minute, 600 uses a minute, 60 reorders a minute.
Errors that matter here
| Code | HTTP | When it happens |
|---|---|---|
| QUICK_REPLY_NOT_FOUND | 404 | No quick reply with that id in this workspace. |
| QUICK_REPLY_SHORTCUT_TAKEN | 409 | Another quick reply already uses that shortcut. |
| VALIDATION_ERROR | 422 | Both bodies were empty, or a field is the wrong shape. |
| RATE_LIMITED | 429 | Too many creates, uses or reorders in the window. |
Every code and its status is on the errors page.