Appearance
Hosted quickstart — sign up to first webhook
Español: Inicio rápido alojado.
This guide takes you from no account to your first simulated call and your first signed webhook, against the hosted API, using a test key. A test key never reaches a carrier, a phone, an SMS provider or a mailbox, and nothing it does is metered or charged. The local-stack walkthrough that places real compliance-gated attempts is the Quickstart.
https://api.usa.dialerdigital.com # hosted API (USA cell)You will: register → set your password → sign in → mint a dd_test_ key → simulate a call → receive the call.ended webhook → read the test record.
Copy-paste friendly
Every step is a runnable curl; jq captures values into shell variables. Branch on error.code, never on message — see the error index.
Step 1 — Register
Registration is public and anonymous. First read what the form needs — the terms version in force and the public anti-bot site key:
bash
API=https://api.usa.dialerdigital.com
curl -s $API/v1/signups/config
# -> {"available":true,"terms_version":"...","captcha":{"provider":"turnstile","site_key":"..."}}available: false means sign-up is closed in this cell. Otherwise, solve the Cloudflare Turnstile widget (with that site_key) in a browser to obtain a captcha_token, then register:
bash
curl -s -X POST $API/v1/signups \
-H "Content-Type: application/json" \
-d '{
"email": "dev@example.com",
"name": "Ada Developer",
"terms_version": "<terms_version from the config>",
"captcha_token": "<token from the widget>",
"locale": "en"
}'
# -> {"status":"accepted"}The answer is 202 accepted whether the address is new, pending or already registered — it never tells you which, so nobody can probe for accounts. A new or pending address gets a mail with a single-use link (a new link kills the previous one); an address that already belongs to a person gets a "you already have an account" notice with no link. Until you redeem it there is no key, no person and no session, and the account's plan is draft: anything that spends or places a real call answers 402 plan_inactive.
Refusals you can hit: 422 terms_version_mismatch, 403 captcha_failed, 429 signup_rate_limited (wait Retry-After), 503 signup_unavailable / 503 captcha_unavailable (nothing was created).
Step 2 — Set your password
The link in the mail carries a token (ddr_…). Redeem it with the password you choose (12 to 128 characters):
bash
curl -s -X POST $API/v1/auth/password-reset/confirm \
-H "Content-Type: application/json" \
-d '{"token": "<token from the link>", "new_password": "<your password>"}'
# -> {"status":"ok"}Redeeming the link verifies the address and creates your person in the same step. A bad, expired or already-used token is one indistinguishable 401.
Step 3 — Sign in
bash
SESSION=$(curl -s -X POST $API/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "dev@example.com", "password": "<your password>"}' | jq -r .token)This mints a ddu_ dashboard session. If the account has a second factor active, the answer is mfa_required: true plus a challenge to redeem at POST /v1/auth/mfa/verify first. See Authentication.
Step 4 — Mint a test key
Public sign-up starts as member
A person who registers through the public sign-up enters as a member. Minting a key takes an account_admin, and today only a platform operator grants that role (there is no API route for it). Until then POST /v1/api_keys answers 403 role_forbidden.
With an account_admin login, ask for environment: "test":
bash
TOKEN=$(curl -s -X POST $API/v1/api_keys \
-H "Authorization: Bearer $SESSION" \
-H "Content-Type: application/json" \
-d '{"label": "quickstart", "environment": "test"}' | jq -r .token)
echo $TOKEN # dd_test_… — shown ONCEThe token is shown once; store it. The environment is fixed at creation. A test key authenticates and reads like a live one, but every route that dials for real, buys or provisions answers 403 test_environment.
Step 5 — Register a webhook endpoint
Subscribe an HTTPS endpoint (port 443, public host) to the call events. The secret is shown once:
bash
curl -s -X POST $API/v1/webhooks \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/hooks/dialerdigital", "events": ["call.answered", "call.ended"]}'
# -> {"webhook":{"id":"...","enabled":true,...},"secret":"whsec_..."}Verify signatures as described in Outbound webhooks. To check your receiver before any call, POST /v1/webhooks/{id}/test sends one signed webhook.test event now and answers with what your endpoint replied.
Step 6 — Simulate a call
With a test key, POST /v1/dial/manual answers a deterministic simulated result chosen by the destination — see limits and test numbers:
bash
curl -s -X POST $API/v1/dial/manual \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"number": "+13125550100"}'
# -> {"status":"dialing","call_id":"..."}Your endpoint receives call.answered and call.ended, signed with X-DD-Signature like a real delivery, with livemode: false and environment: "test" in the envelope.
Step 7 — Read the test record
Simulated calls and SMS live apart from your real CDR (/v1/reports/cdr never includes them):
bash
curl -s "$API/v1/sandbox/records?kind=call&limit=5" -H "Authorization: Bearer $TOKEN"
# -> {"environment":"test","records":[{"kind":"call","to_number":"+13125550100","outcome":"answered","status":"completed",...}]}Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
422 unknown_test_number | The destination is not one of the four test numbers. |
403 test_environment | The route reaches a carrier, provider or credential; a test key cannot use it. |
403 role_forbidden on minting | Your login is a member (every public sign-up starts as one); only a platform operator can grant account_admin. |
402 plan_inactive | A real call or send on an account whose plan is not active; test keys do not hit this path. |
429 rate_limited | Per-key quota — see rate limits. |