Appearance
Guide: calls and SMS
Español: Guía: llamadas y SMS.
Calls and texts leave through one gated path: the same compliance engine whether the request came from a campaign, the dashboard or your API call. There is no raw-send endpoint. The shapes below are the authority of the API Reference; this page is the walk-through.
Calls
| Goal | Endpoint |
|---|---|
| Dial a typed number | POST /v1/dial/manual |
| Preview the next dialable lead without dialing | GET /v1/campaigns/{id}/next-lead |
| Dry-run a campaign's leads through the gates | GET /v1/campaigns/{id}/compliance-preflight |
| Hold, mute, transfer, hang up a live call | POST /v1/calls/{call_id}/hold · …/mute · …/transfer · …/hangup |
Dial a typed number
bash
curl -s -X POST $API/v1/dial/manual \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"number": "+13125551001", "agent_id": "<agent uuid>"}'A live dd_ key must name agent_id (400 when missing). The number is resolved against the phones of your own accounts; the call is placed only when it matches exactly one dialable account, through the gated originator (consent, do-not-call, the destination-local calling window, Reg F frequency, state rules). Outcomes: 200 dialing, 200 blocked with the gate's reason, or fail-closed 422 with invalid_number, no_account, ambiguous_account, no_campaign or number_quarantined.
A refusal by a gate is a successful answer, not an error to retry: it is the evidence that the call was not made. See Errors & compliance.
SMS
bash
curl -s -X POST $API/v1/sms/messages \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"to": "+13125551001", "body": "Your balance is due. Reply STOP to opt out.", "client_ref": "inv-1001"}'client_refis your idempotency key. A retry with the sameclient_refanswers202withduplicate: trueand the provider is not contacted again.- The body is checked before anything else, with zero provider calls and zero ledger rows on a refusal: no opt-out notice →
422 sms_optout_notice_missing; a carrier-prohibited term →422 sms_content_prohibited. Rewording is the only way through. - The sender must be an active number of your account (
422 sms_from_invalid/422 sms_from_not_owned), and a US local (10DLC) sender needs an approved campaign (422 sms_10dlc_campaign_required) — see the numbers guide. - No provider configured →
422 sms_provider_unconfigured. A prepaid account with no sell rate for the region →422 no_rate.
More on providers, templates and replies: SMS messaging.
Trying both without a carrier
With a dd_test_ key the same two requests (POST /v1/dial/manual with number, POST /v1/sms/messages with to and body) answer a simulated result chosen by the destination, and reach no carrier or provider. The four test numbers and what each returns are on limits and test numbers; the records are read at GET /v1/sandbox/records. The end-to-end walk-through is the hosted quickstart.
Reading results
| Need | Where |
|---|---|
| The durable CDR row with its frozen compliance snapshot | GET /v1/call_attempts |
| What the gates refused | GET /v1/stats/blocked |
| A call finished, pushed to you | webhook call.ended — see Outbound webhooks |
| An inbound reply or opt-out | webhooks sms.received / sms.optout |
Any error code | the error index |