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

bash
curl "https://api-wagate.socialground.co/v1/sessions/<CHANNEL_ID>/warming" \
  -H "Authorization: Bearer <CHANNEL_TOKEN>"
json
{
  "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:

FieldMeaning
enabledwhether warming is switched on for this channel.
sincewhen it was switched on, or null.
stateone of off, stopped, paused, waiting, warming.
reason_codewhy it is in that state. See the list below.
restart_afterafter a safety stop, the earliest time you can switch it back on. Null otherwise.
stage, stage_count, clean_days_at_stage, clean_days_neededprogress through the warming stages. stage, clean_days_at_stage and clean_days_needed can be null before progress is known.
conversations_today, target_todaytoday's activity against today's target, or null.
partnershow many of your channels this one warms with.
voicethe display name of the persona in use, or null.
last_activity_at, next_windowthe last activity, and the next time window when activity is due. Either can be null.
staletrue when the progress figures could not be read fresh, so they are the last known values.
webhook_include_warmingwhether your receivers get warming traffic. See the last section.

The reason_code values:

CodeMeaning
offWarming is switched off.
warmingWarming is running.
waiting_for_partnerWaiting for another of your channels to be ready.
waiting_for_voiceWaiting for a free persona.
waiting_for_capacityWaiting for capacity.
paused_by_youWarming is paused for the account.
paused_disconnectedPaused because the channel is not connected.
paused_allowancePaused because the channel's daily allowance is used.
stopped_safetyStopped for safety. See the cooldown below.
pool_haltedWarming is halted for all your channels.
stopped_operatorStopped 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.

bash
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.

bash
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:

bash
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

StatusCodeMeaning
409warming_ack_requiredThe account has not acknowledged the current terms. Send acknowledge.
400warming_ack_version_unknownThe text_version is not the current one.
409warming_cooldownStopped for safety. restart_after says when it can be switched on again, or is null.
409warming_restart_ack_requiredThe cooldown is over. Send restart_ack: true.
503warming_state_unreadableThe warming record could not be read, so the switch-on was refused. Retry later.
403warming_peer_refusedWarming refused an operation between channels. It should not reach you. Contact support.
403account_suspendedThe account is on hold. You can still switch warming off.
400field_not_allowedThe body has a field this route does not accept.
404not_foundWarming 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:

bash
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.

Warming · WAgate docs