Skip to content

Send a message or note

POST /hooks/api_v1.php?r=messages uses the same provider, consent, quiet-hour, idempotency, and billing path as Dial Dozer’s UI and automations.

Required scope: messages:write

Terminal window
curl --fail-with-body -X POST \
"https://app.dialdozer.com/hooks/api_v1.php?r=messages" \
-H "X-Api-Key: $DIALDOZER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"lead_id": 48219,
"channel": "sms",
"body": "Hi Maya — your appointment is confirmed for tomorrow.",
"operation_id": "confirm-48219-20260717"
}'
FieldTypeRequiredNotes
lead_idintegeryesMust exist inside the key’s organization.
channelstringyesExactly sms, email, or note.
bodystringyesEmpty content is rejected by the shared send path. Email content is handled as HTML with escaped merge values.
subjectstringemail onlyDefaults to Message from {company} if omitted.
operation_idstringyesIdempotency identity: 1–96 characters using letters, digits, _ . : -. Missing/invalid values return bad_operation_id. Reuse it only for a retry of the same send.

Success commonly returns:

{"ok":true,"message_id":901}

Provider/gate results are intentionally returned rather than hidden. A request can receive HTTP 200 with ok: false, for example {"ok":false,"reason":"empty_body","message_id":null}. Quiet-hour deferral can include a queued message_id and defer_until Unix timestamp.

Billing gate reasons billing_not_configured, billing_unavailable, billing_frozen, subscription_required, and insufficient_credits use HTTP 402. Other delivery/gate failures currently remain HTTP 200; always inspect ok and reason, not only status.

Notes are stored internally and do not call a provider. SMS/email require the relevant contact channel, consent/configuration, and available billing balance.