Warming
Switch warming on or off for a channel, and read its progress.
Warming is free and included with every channel. Your channels chat with each other so they look like ordinary, active WhatsApp accounts. These routes switch it on or off for one channel, read its progress, and choose whether your webhook receivers also get its traffic.
All three routes use the channel token. While warming is not available for a channel, each answers 404 not_found.
GET/v1/sessions/<CHANNEL_ID>/warming
Read this channel's warming state.
PUT/v1/sessions/<CHANNEL_ID>/warming
Switch warming on or off.
PUT/v1/sessions/<CHANNEL_ID>/warming/webhooks
Choose whether this channel's webhook receivers also get its warming traffic.
Read the state
curl "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/warming" \
-H "Authorization: Bearer <CHANNEL_TOKEN>"{
"enabled": true,
"since": "2026-10-11T03:00:00Z",
"state": "warming",
"reason_code": "warming",
"restart_after": null,
"stage": 2,
"stage_count": 5,
"clean_days_at_stage": 1,
"clean_days_needed": 3,
"conversations_today": 4,
"target_today": 9,
"partners": 2,
"voice": "Example persona",
"last_activity_at": "2026-10-11T04:12:00Z",
"next_window": { "from": "2026-10-11T07:00:00Z", "to": "2026-10-11T09:30:00Z" },
"stale": false,
"webhook_include_warming": false
}Fields:
| Field | Meaning |
|---|---|
enabled | whether warming is switched on for this channel. |
since | when it was switched on, or null. |
state | one of off, stopped, paused, waiting, warming. |
reason_code | why it is in that state. See the list below. |
restart_after | after a safety stop, the earliest time you can switch it back on. Null otherwise. |
stage, stage_count, clean_days_at_stage, clean_days_needed | progress through the warming stages. stage, clean_days_at_stage and clean_days_needed can be null before progress is known. |
conversations_today, target_today | today's activity against today's target, or null. |
partners | how many of your channels this one warms with. |
voice | the display name of the persona in use, or null. |
last_activity_at, next_window | the last activity, and the next time window when activity is due. Either can be null. |
stale | true when the progress figures could not be read fresh, so they are the last known values. |
webhook_include_warming | whether your receivers get warming traffic. See the last section. |
The reason_code values:
| Code | Meaning |
|---|---|
off | Warming is switched off. |
warming | Warming is running. |
waiting_for_partner | Waiting for another of your channels to be ready. |
waiting_for_voice | Waiting for a free persona. |
waiting_for_capacity | Waiting for capacity. |
paused_by_you | Warming is paused for the account. |
paused_disconnected | Paused because the channel is not connected. |
paused_allowance | Paused because the channel's daily allowance is used. |
stopped_safety | Stopped for safety. See the cooldown below. |
pool_halted | Warming is halted for all your channels. |
stopped_operator | Stopped by WAgate. |
Switch warming on or off
PUT sessions/<CHANNEL_ID>/warming takes enabled (required, boolean), restart_ack (boolean) and acknowledge (an object with text_version). Any other field answers 400 field_not_allowed. The answer is the channel object, and its warming field holds the same object GET returns.
Switching off always works, including while your account is suspended.
curl -X PUT "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/warming" \
-H "Authorization: Bearer <CHANNEL_TOKEN>" -H "Content-Type: application/json" \
-d '{"enabled": false}'Before the first switch-on
The account owner acknowledges the warming terms once before any channel on the account can warm. In the console that is a checkbox. On the API you send it with the first switch-on, as the acknowledge field. Sending it records the acknowledgment for the account.
curl -X PUT "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/warming" \
-H "Authorization: Bearer <CHANNEL_TOKEN>" -H "Content-Type: application/json" \
-d '{"enabled": true, "acknowledge": {"text_version": "2026-10-13"}}'text_version must be the current version of the warming terms, shown in the console where you switch warming on. It is checked only while the account has not yet acknowledged the current version. Once it has, you can send {"enabled": true} alone, and a text_version you send is ignored. If the terms change, the version changes, and the account is asked again at its next switch-on.
What the account owner agrees to
The account acknowledges the following text once before any of its channels can warm. In the console it is a checkbox, with the heading "Turn on warming". The last item is the checkbox label.
- Warming sends short, pre-written chat messages between your own channels, automatically, from your numbers. You do not write these messages. WAgate does, and sends them on your behalf. They are ordinary WhatsApp messages from your numbers: you will see the chats on your phones, and they count toward your sandbox allowances.
- WhatsApp decides what it allows. Warming is meant to lower the risk of a restriction, but WhatsApp can still restrict or ban any number, including one that is warming, for reasons we cannot see and cannot reverse. A restriction or ban alone does not entitle you to a refund or compensation. Refund rights required by law and the liability exceptions in Terms section 13 still apply.
- You can turn warming off for any number at any time. It stops before the next message.
- I understand that WAgate will send pre-written messages from my numbers on my behalf, and that WhatsApp may still restrict or ban a number that is warming. I own these numbers or am authorized to operate them, and I accept that risk.
After a safety stop
If WAgate stops a number for safety, state is stopped and reason_code is stopped_safety. The number cools down first. Until restart_after, a switch-on answers 409 warming_cooldown. After that, switching it back on needs restart_ack:
curl -X PUT "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/warming" \
-H "Authorization: Bearer <CHANNEL_TOKEN>" -H "Content-Type: application/json" \
-d '{"enabled": true, "restart_ack": true}'If restart_after is null, no end time was recorded and only WAgate can clear the stop. Contact support at [email protected].
Refusals
| Status | Code | Meaning |
|---|---|---|
| 409 | warming_ack_required | The account has not acknowledged the current terms. Send acknowledge. |
| 400 | warming_ack_version_unknown | The text_version is not the current one. |
| 409 | warming_cooldown | Stopped for safety. restart_after says when it can be switched on again, or is null. |
| 409 | warming_restart_ack_required | The cooldown is over. Send restart_ack: true. |
| 503 | warming_state_unreadable | The warming record could not be read, so the switch-on was refused. Retry later. |
| 403 | warming_peer_refused | Warming refused an operation between channels. It should not reach you. Contact support. |
| 403 | account_suspended | The account is on hold. You can still switch warming off. |
| 400 | field_not_allowed | The body has a field this route does not accept. |
| 404 | not_found | Warming is not available for this channel. |
When several apply, they are checked in this order: suspended account, cooldown, acknowledgment, restart acknowledgment. See Errors for the full code list.
Warming traffic on your webhooks
By default your webhook receivers get nothing from warming. To receive it, switch it on for the channel:
curl -X PUT "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/warming/webhooks" \
-H "Authorization: Bearer <CHANNEL_TOKEN>" -H "Content-Type: application/json" \
-d '{"include_warming": true}'The body is exactly {"include_warming": true} or {"include_warming": false}. Any other body answers 400. The answer is the warming object shown above.
With it on, your receivers also get the message and message.status events that warming traffic produces, and each of those events carries "warming": true at the top level, next to type. Filter on that field if you do not want to process them. See Webhook events for the envelope.