Skip to main contentSkip to Content
Messages

Messages

Messages represent dispatched communications to contacts across all channels.

List Messages

GET /api/workspaces/{workspaceId}/messages

Paginated list of messages with filtering.

Auth: Session required

Query Parameters:

ParamTypeDefaultDescription
pagenumber1Page number
limitnumber50Items per page
channelstring—EMAIL, PUSH, TELEGRAM, SMS, WHATSAPP, ONSITE, WEBHOOK
statusstring—QUEUED, SENDING, SENT, DELIVERED, OPENED, CLICKED, BOUNCED, FAILED, UNSUBSCRIBED
contactIdstring—Filter by contact
campaignIdstring—Filter by campaign

Response:

{ "data": [ { "id": "msg_abc123", "channel": "EMAIL", "status": "DELIVERED", "subject": "Welcome to Acme!", "sentAt": "2026-01-15T10:00:00.000Z", "openedAt": "2026-01-15T10:05:00.000Z", "contactId": "ct_1", "campaignId": "cmp_1" } ], "pagination": { "page": 1, "limit": 50, "total": 5000, "totalPages": 100 } }

Send Message

POST /api/workspaces/{workspaceId}/messages

Sends a message to a contact through the specified channel.

Auth: Session required

Request Body:

{ "contactId": "ct_abc123", "channel": "EMAIL", "subject": "Your weekly digest", "body": "<h1>Hello {{contact.firstName}}</h1><p>Here is your update...</p>", "templateId": "tpl_abc123", "campaignId": "cmp_abc123", "metadata": { "category": "digest" } }
FieldTypeRequiredDescription
contactIdstringYesTarget contact ID
channelstringYesEMAIL, PUSH, TELEGRAM, SMS, WHATSAPP, ONSITE, WEBHOOK
subjectstringNoMessage subject (email)
bodystringNoMessage body content
templateIdstringNoTemplate to render
campaignIdstringNoAssociated campaign
metadataobjectNoAdditional metadata

Response (200): Dispatch result. Returns 422 if dispatch fails.

Get Message

GET /api/workspaces/{workspaceId}/messages/{messageId}

Returns message details with contact, template, and campaign information.

Message Status Flow

QUEUED → SENDING → SENT → DELIVERED → OPENED → CLICKED ↘ BOUNCED ↘ FAILED ↘ UNSUBSCRIBED

Each status transition is tracked with timestamps and events.

Open tracking and image prefetch

Opens are counted when the tracking image in an email is loaded. Mail providers and security scanners load that image before a human sees the message, so CampaignOS ignores a load that both comes from a known proxy or scanner (Gmail’s image proxy, Yahoo, Outlook preview, Proofpoint, Mimecast and similar) and happens within 30 seconds of the send, and any load in the first 15 seconds whatever the agent.

Those loads are recorded on the message as machine opens and mark it delivered. The message detail shows how many there were. They do not set the open date, do not count in open rates, and do not trigger “opened the email” automations.

Gmail caches the image after fetching it, so a later human open may never reach the server. Clicks are the reliable engagement signal there, and a click also marks the message as opened.

Last updated on