Skip to content

Message quota events

Events related to the per-number message quota, measured against the organization’s current billing cycle (cycle_start/cycle_end). Limits per plan: Free 300, Lone Wolf 1,800, Business 50,000 and Custom 500,000 per number, per cycle.

The message quota is per number, like the contact quota: each linked number (main or an extra alias) has its own allowance, and an account with N numbers has N times the plan’s allowance. These events identify the affected number by the number_alias of the envelope (not in data). Only messages sent through Turbo Notify (origin: "tn") consume the quota.

To configure the webhook URL, validate the signature and understand the envelope, see Webhook: setup and envelope.

Events

EventWhen
message.quota.warningCrossed the 80, 90 or 95% threshold of the number’s message quota
message.quota.exceededAttempt rejected because the quota is exhausted (HTTP 429)

number_alias in the envelope

Both events carry, right below organization_id, the number_alias field: the identifier of the Turbo Notify number whose message quota was reached ("main" for the main number or the alias of an extra number). The event data carries the quota fields threshold_percent (only in warning), used, quota, cycle_start, cycle_end, resets_at, tier, channel, origin. number_alias sits in the envelope, never inside data.

used/quota are measured against the organization’s evaluated billing cycle (cycle_start/cycle_end, ISO 8601 UTC); resets_at equals cycle_end.

threshold_percent is the percentage of the quota reached, as an integer: 80, 90 or 95 (80 means 80%). An exhausted quota does not arrive as threshold_percent: 100: it arrives as the message.quota.exceeded event, which has no such field.

Among the account events, number_alias is omitted in storage.* and in media.unavailable. The whole *.quota.* family (contacts and messages) carries this field.

Example: message.quota.warning

{
"id": "evt_...",
"type": "message.quota.warning",
"organization_id": "org_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"number_alias": "main",
"number_id": "num_0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"created_at": "2026-06-20T12:00:00Z",
"data": {
"threshold_percent": 80,
"used": 240,
"quota": 300,
"cycle_start": "2026-06-01T00:00:00Z",
"cycle_end": "2026-07-01T00:00:00Z",
"resets_at": "2026-07-01T00:00:00Z",
"tier": "FREE",
"channel": "whatsapp",
"origin": "tn"
}
}

Example: message.quota.exceeded

{
"id": "evt_...",
"type": "message.quota.exceeded",
"organization_id": "org_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"number_alias": "main",
"number_id": "num_0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"created_at": "2026-06-20T12:00:00Z",
"data": {
"quota": 300,
"used": 300,
"cycle_start": "2026-06-01T00:00:00Z",
"cycle_end": "2026-07-01T00:00:00Z",
"resets_at": "2026-07-01T00:00:00Z",
"tier": "FREE",
"channel": "whatsapp",
"origin": "tn"
}
}

Timestamps and correlation

  • These events are generated by Turbo Notify itself (they do not reflect an action on WhatsApp): they do not carry at in data, only the envelope created_at (moment Turbo Notify emitted the event).
  • cycle_start/cycle_end are the evaluated billing cycle against which used/quota were measured. resets_at is the moment the quota count starts over: equal to cycle_end at emission, it is not the moment something happened.
  • There is no phone in the content of these events. To correlate with the request that triggered the overflow, use GET /v1/events?request_id=req_....
  • Move to a larger plan (see the plan table in Quota and usage).
  • Follow, in the dashboard under Usage, the consumption of each number in the current cycle.