"Likely Answer", "Likely Voicemail") once processing finishes. Use it when your tooling enriches one row at a time and the bulk Uploads API doesn’t fit.
This endpoint is Enterprise-only. To enable access for your organization, email support@optimaldial.com. Until access is granted, every call returns
403 with error: "feature_not_enabled".Lifecycle
POST /api/v1/contacts— submit one phone number. We charge 1 credit and return immediately with acontact_idinqueuedstate.- Processing happens asynchronously. Typical turnaround is within 24-48 hours.
- When processing finishes, the contact transitions to
completed(withoptimaldial_statusset) orfailed(witherror_message). - You learn the result via either:
- The
callback_urlyou provided on creation (a signed POST per contact — recommended for integrations that can listen for webhooks), or - Your registered org-level webhook endpoints (
contact.completed/contact.failed), or - Polling
GET /api/v1/contacts/{contact_id}.
- The
The Contact object
| Field | Type | Notes |
|---|---|---|
id | string (UUID) | Stable identifier. |
organization_id | string (UUID) | Org the contact belongs to. |
phone | string | E.164-normalized phone (US/CA only). |
properties | object | Whatever extra fields you sent on creation, echoed back in result payloads. |
status | enum | One of: queued, processing, completed, failed, discarded. |
optimaldial_status | string | null | The classification — e.g. "Likely Answer". Populated when status == "completed". |
error_message | string | null | Populated when status == "failed". |
message | string | null | Human-readable note about the current state. Populated while the contact is still queued/processing (e.g. “Contact has not been processed yet…”); null once it reaches a terminal state. |
credits_charged | integer | Always 1. Refunded on cancel. |
created_at | string (ISO 8601) | UTC timestamp. |
updated_at | string (ISO 8601) | UTC timestamp of the last status change. |
Statuses
| Status | Meaning |
|---|---|
queued | Submitted, awaiting processing. |
processing | Processing in progress. |
completed | Result is on optimaldial_status. |
failed | Processing finished but did not produce a result; see error_message. |
discarded | Discarded by OptimalDial; credit refunded. Rare. |
Create a contact
201 with the new contact in queued status.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
phone | string | yes | Any common format. Normalized to E.164 server-side. Must be US or Canadian. |
properties | object | no | Arbitrary extra fields echoed back in result payloads. Use these to correlate the result with your own row IDs. |
callback_url | string (HTTPS) | no | Optional per-contact webhook. We POST to it when the contact’s result is ready. Signed with callback_secret if provided. Same retry semantics as registered org webhooks (6 attempts with exponential backoff). |
callback_secret | string | no | HMAC-SHA256 secret used to sign the callback_url payload. |
idempotency_key | string | no | Optional. Re-posting with the same key returns the existing contact without an extra credit charge. Scoped per (organization, api_key). |
- cURL
- Node.js
- Python
Response
201 Created:
Errors
| Status | When |
|---|---|
401 | Missing, invalid, or revoked API key |
402 | Organization out of credits |
403 | Enterprise access not enabled — contact support |
422 | Phone is unparseable or not US/CA |
429 | Rate limit hit |
Retrieve a contact
status == "completed".
List contacts
status filter.
| Param | Type | Default | Notes |
|---|---|---|---|
status | enum | — | Filter by one of the statuses. |
limit | integer (1–100) | 50 | Page size. |
cursor | string | — | Pass back next_cursor from the previous response. |
Result delivery
When a contact reachescompleted or failed, OptimalDial fires up to two notifications:
- Per-contact callback — if you provided
callback_urlon creation, we POST a signed JSON body to it. Same signature scheme and retry semantics as org-level webhooks: HMAC-SHA256 off"{ts}.{body}"using yourcallback_secret, 6 attempts with exponential backoff. Headers includeX-OptimalDial-SignatureandX-OptimalDial-Timestamp. - Org-level webhooks — your registered webhook endpoints receive
contact.completed/contact.failedevents for every contact that finishes. Useful for fan-out to internal systems independent of the per-contact callback.
properties object on the result echoes back exactly what you sent on creation — use it to correlate the result with your own row IDs without storing the OptimalDial contact_id.