Business hours and auto-replies
Two workspace settings that change how the platform answers on your behalf: when you are open, and what is said automatically when somebody writes. Both are evaluated on the SERVER, in the workspace's own timezone.
What is here
Four routes, and the scopes are not symmetrical — read them before wiring a role. The timezone these are evaluated in belongs to the workspace, not to the caller's browser.
| Endpoint | Scope |
|---|---|
| GET /v1/settings/business-hours | workspace.read |
| PUT /v1/settings/business-hours | workspace.manage |
| GET /v1/settings/auto-replies | automations.manage |
| PUT /v1/settings/auto-replies | automations.manage |
Auto-replies take an automations scope
Reading the auto-replies requires automations.manage, not a read permission, because each toggle materialises a real automation. Business hours split the ordinary way instead: workspace.read to read, workspace.manage to write.
Business hours
| Field | Type | Description |
|---|---|---|
| enabled | boolean | Whether the week is applied at all. |
| timezone | string | The one clock involved. Everything here is evaluated in it. |
| days | object<day, {from,to}[]> | Open days only, each with one or more from/to windows. |
| state | "open" | "closed" | Open or closed right now, decided by the server. |
| suggested.days | object | A starting week the API offers when nothing is configured yet. |
curl -X PUT https://whats.azzamkh.sa/api/v1/settings/business-hours \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"enabled": true,
"timezone": "Asia/Riyadh",
"days": {
"sun": [{ "from": "09:00", "to": "17:00" }],
"mon": [{ "from": "09:00", "to": "17:00" }],
"tue": [{ "from": "09:00", "to": "13:00" },
{ "from": "16:00", "to": "19:00" }]
}
}'
# 200 OK — "state" is the SERVER's answer, in the workspace timezone.
# {
# "enabled": true,
# "timezone": "Asia/Riyadh",
# "days": { "sun": [...], "mon": [...], "tue": [...] },
# "state": "open",
# "suggested": { "days": { ... } }
# }A closed day is an OMITTED day
Sending a day with an empty array is a 422. Send only the days that are open. Turning enabled off KEEPS the week rather than erasing it, and enabled: true with no open day is a 422 as well.
- Never recompute
statein a browser. A browser evaluates the week in ITS timezone, which is the exact mistake this setting exists to prevent — and the away automation reads the same hours server-side, so a locally derived badge would disagree with it. - Windows may repeat within a day, so a split shift is two entries on the same day rather than two settings.
suggested.daysis a convenience, not the current value. Nothing is applied until you PUT it.
Welcome and away replies
These are ordinary automations under the covers: each enabled toggle materialises one, with its own run log and the same loop protection. automation_id is how you find it.
| Field | Type | Description |
|---|---|---|
| welcome, away | object | The two replies. Send either, or both. |
| *.enabled | boolean | Whether this reply is armed. |
| *.message | string | null | The text sent. Null when it has never been set. |
| *.automation_id | string | null | The automation this toggle materialised, or null when it is off. |
| *.last_run_at | string | null | When it last fired. |
| business_hours_configured | boolean | Whether business hours exist. The away reply cannot be turned on without them. |
curl -X PUT https://whats.azzamkh.sa/api/v1/settings/auto-replies \
-H "Authorization: Bearer $WA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"away": { "enabled": true, "message": "We are closed — back at 9am." }
}'
# 200 OK
# {
# "welcome": {
# "enabled": false, "message": null,
# "automation_id": null, "last_run_at": null
# },
# "away": {
# "enabled": true, "message": "We are closed — back at 9am.",
# "automation_id": "atm_...", "last_run_at": null
# },
# "business_hours_configured": true
# }
# Without business hours, turning "away" on is:
# 409 { "error": { "code": "BUSINESS_HOURS_NOT_CONFIGURED", ... } }Errors that matter here
| Code | HTTP | When it happens |
|---|---|---|
| BUSINESS_HOURS_NOT_CONFIGURED | 409 | The away reply was turned on with no business hours configured. Disable the control for turning ON only — a switch frozen in the on position is a trap — and still handle the 409, because another tab can clear the hours between the page loading and the save landing. |
| VALIDATION_ERROR | 422 | An empty open day, enabled with no open day, or a malformed time. |
| FORBIDDEN | 403 | The caller holds neither the read nor the manage scope. |
Every code and its status is on the errors page.