Skip to content
API PlatformDevelopers
POST/v1/conversations/{conversation_id}/system-messagesbeta

Add a system message

Needs
Manage conversations: notes, assign, close, tags, reminders (inbox:write)
Plan
Any plan with API access
Limits
60 a minute per key
Dry run
Yes — a full preview with ?dry_run=true
Undo
A system line cannot be removed.

Adds a line to a conversation's thread that your team sees and the customer never gets: an event from your own systems, such as an order shipped, a payment received or a record synced. No reply window applies, and it does not count against the send limits.

  • text: the line (plain text, up to 4096 characters).
  • system_type: what kind of event it records, e.g. ORDER_UPDATE, PAYMENT_RECEIVED or SHIPPING_UPDATE (letters, digits and _, up to 100, upper-cased; default NOTIFICATION). The platform's own types (MENTION, REMINDER, REMINDER_SET, REMINDER_ACKNOWLEDGED, REMINDER_DELETED, REMINDER_UPDATED, SLA_BREACH, CALL_EVENT, CLIENT_ACTION) are refused: to mention colleagues, add a note instead.
  • meta: a JSON object kept with the line for integrations that read the thread later (at most 4 KB as JSON, nested at most 3 levels, 50 keys per object; keys are kept exactly as sent). The keys mentionStaffs, acknowledged, reminder_id, created_by_staff_id and idempotency_key are refused (send your key as the Idempotency-Key header).
  • priority: true moves the conversation up and notifies its assignee, a manager and the team leads; meta.source then appears in that notification, so it must be text (up to 200 characters) or a number.

Text and meta are shown as plain text, never as HTML. Try it with ?dry_run=true: the conversation and the fields are checked and nothing is added.

Try it

Path

The conversation id.

Body

The line your team sees (plain text, 1–4096 characters).

The kind of event, e.g. `ORDER_UPDATE` (letters, digits and `_`, up to 100; upper-cased; default `NOTIFICATION`). The platform's own types are refused.

A JSON object kept with the line (at most 4 KB, 3 levels, 50 keys per object). Reserved keys are refused.

`true` moves the conversation up and notifies its assignee, a manager and the team leads.

Protects against doing it twice if you retry: a retry with the same key gets the first answer back instead of running again.

Test mode (dry run): nothing will change
Turns test mode off for this page only. It switches back when you leave the page.

Code and response

curl -X POST 'https://mcp.wa-api.cloud/v1/conversations/77410/system-messages?dry_run=true' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "text": "Order #4411 shipped with FedEx (tracking FX123456789).",
  "system_type": "ORDER_UPDATE",
  "meta": {
    "order_id": "4411",
    "carrier": "FedEx",
    "tracking_number": "FX123456789",
    "source": "shop"
  }
}'

The code reads your key from $API_KEY.

Parameters

Parameters
FieldTypeWhat it is
conversation_idrequiredstring · pathThe conversation id.pattern ^\d{1,19}$Signed in? Pick one from your data with “My data”.

Body

Body fields
FieldTypeWhat it is
textrequiredstringThe line your team sees (plain text, 1–4096 characters).1–4096 characters
system_typestringThe kind of event, e.g. ORDER_UPDATE (letters, digits and _, up to 100; upper-cased; default NOTIFICATION). The platform's own types are refused.pattern ^[A-Za-z][A-Za-z0-9_]*$ · 0–100 characters
metaobjectA JSON object kept with the line (at most 4 KB, 3 levels, 50 keys per object). Reserved keys are refused.
prioritybooleantrue moves the conversation up and notifies its assignee, a manager and the team leads.

Headers

Headers
FieldTypeWhat it is
AuthorizationrequiredheaderBearer $API_KEY — your API key.
Api-VersionheaderThe API version to use, e.g. 2026-10-01. Default: the version your key is pinned to.one of: 2026-10-01 · pattern ^\d{4}-\d{2}-\d{2}$
Idempotency-KeyrequiredheaderRequired here. Any unique string (8–128 characters), e.g. your order id plus the step. Kept 24 hours. Not needed with dry_run=true.pattern ^[A-Za-z0-9._:-]+$ · 8–128 characters

Response 201

The line was added (or the dry-run check). It shows in the conversation's message list as a `SYSTEM` message.

Response fields
FieldTypeWhat it is
message_idrequiredstring or null
statusrequiredstringcreated, or dry_run.
conversation_idrequiredstring
channelrequiredobject
idrequiredstring
namerequiredstring or null
typerequiredstring
system_typerequiredstring
visible_to_customerrequiredboolean
dry_runbooleantrue when this was a dry run: every check ran and nothing changed.

Errors

Errors are application/problem+json. Branch on code.

StatusCodeWhen
400invalid_input

A field is missing or has the wrong format. errors[] points at each field. text is empty or too long, system_type is reserved for the platform or has other characters, or meta breaks a rule (a reserved key, too large or too deep, or a source that is not text up to 200 characters or a number). Also returned when the Idempotency-Key header is missing, or was used before with a different body.

401unauthenticated

The Authorization header is missing, the key is unknown, expired or revoked.

403entitlement_required

The workspace's plan does not include API access (api_access).

403insufficient_scope

The key does not have the permission this operation needs.

404not_found

No conversation with this id, or your key cannot see it.

409conflict

Also returned while a request with the same Idempotency-Key is still running.

429rate_limited

The key or workspace went over its rate limit. Wait for Retry-After seconds.

503upstream_unavailable

A service behind the API is briefly unavailable. Safe to retry with backoff.

504timeout

The change did not finish in time. Retry with the same Idempotency-Key: it never runs twice.

Examples

Record an order update for your team

Request body

{
  "text": "Order #4411 shipped with FedEx (tracking FX123456789).",
  "system_type": "ORDER_UPDATE",
  "meta": {
    "order_id": "4411",
    "carrier": "FedEx",
    "tracking_number": "FX123456789",
    "source": "shop"
  }
}

Response 201

{
  "message_id": "5501238",
  "status": "created",
  "conversation_id": "77410",
  "channel": {
    "id": "301",
    "name": "Main WhatsApp",
    "type": "whatsapp"
  },
  "system_type": "ORDER_UPDATE",
  "visible_to_customer": false
}

Operation path

The same operation is also at POST /v1/ops/inbox_add_system_message, with every field in the JSON body.