Groupilot Docs

Sends

Schedule a one-off message on an occurrence, edit, cancel or retry a planned send, with the send scope.

Everything on this page needs the send scope. A send goes out on your customer's WhatsApp number, so keep this scope for tools you trust. Reference: Messages.

Read the planned sends

GET /v1/events/{id}/jobs lists every planned send of an event (one per occurrence and sequence message, plus one-off messages), with filters status, occurrence_id, community_id, content_type, from, to, order, and cursor pagination. GET /v1/jobs/{id} reads one. GET /v1/jobs/{id}/deliveries lists the result per community.

A send has a status (scheduled, billing_paused, overdue, sent, partial, failed, canceled), flags editable, cancelable, retryable, retrying, a retry object (count, max, next_at), delivery counts (sent, failed, certain_failed, uncertain, total) and its content (source is template while it still follows the sequence message, snapshot once frozen). error_message, on sends and deliveries, is always a neutral one-line text you can show to a user.

Schedule a one-off message

POST /v1/events/{event_id}/messages
Idempotency-Key: <uuid>

{
  "occurrence_id": "…",
  "send_at": "2026-11-20T20:25:00+01:00",
  "type": "text",
  "text": "We start in 5 minutes, here is the link: https://…",
  "label": "Late start"
}
  • send_at is at least 60 seconds in the future. The occurrence must be upcoming, not live or finished.
  • type: text, image, video, voice or poll. Media types need a media_url: any URL the WhatsApp provider can fetch is accepted. Uploading first through Media is recommended: format and size are checked there, whereas a bad external file only surfaces at send time. Polls take poll: { question, options, select_count }.
  • label (60 characters) is shown in the app next to the message.
  • The content is frozen at creation. Date variables work.
  • 30 per day per account. The response is the created Job (201).

Edit a pending send

PATCH /v1/jobs/{job_id}
{ "text": "Updated text", "media_url": null }

Only while editable is true: not attempted yet, subscription active, and not a poll. Only text and media_url can change, not the time. The override wins over the sequence message until it is sent, and a later resync keeps it.

Cancel a pending send

POST /v1/jobs/{job_id}/cancel

Only while cancelable is true (pending, time not reached). The send stays in the list with status: canceled. 409 otherwise.

Retry a failed send

POST /v1/jobs/{job_id}/retry
{ "mode": "failed" }
modeWhen
failedThe send failed everywhere
partialSome communities got it, others did not
overdueIts time passed without an attempt (number disconnected, billing)
force_nowGroupilot is waiting before an automatic retry and you want it now

Groupilot only re-queues the communities where the send certainly failed before leaving. A send WhatsApp did not confirm is never repeated: check the group yourself. The response is { "job": { … }, "deliveries_reset": 2 }. 409 when nothing certain is left to retry.

Automatic retries

Groupilot retries on its own up to 5 times, after about 1, 3, 10, 25 and 60 minutes, on temporary errors. retry.next_at tells you when. Permanent errors (refused media, missing community) are final.

On this page