api_version field on webhook payloads changes only when the payload shape itself changes.
2026-08-26 — Multiple phone columns per upload
- Map up to 10 phone columns in one upload with the new
phone_columnsfield — comma-separated in CSV mode, an array in JSON mode. See Multiple phone columns. - Billing is per number. A contact with a number in two mapped columns costs 2 credits at
standardandceil(2 × 1.5) = 3atmax. The same number appearing in more than one column — or already seen on an earlier contact — is de-duplicated and charged once. - New
valid_number_counton theUploadobject and in theupload.createdwebhook: the numbers you were charged for.valid_row_countkeeps its meaning of contact rows, so do not derive an invalid count by subtracting one from the other on a multi-column upload. - The processed file keeps one row per contact and carries one
{column}_OptimalDial_Statusper mapped column (plus{column}_OptimalDial_Answer_Intentand{column}_OptimalDial_Identityon identity lists). A blank cell means that column held no number for that contact. - The 100-number minimum now counts numbers rather than contacts, so 50 contacts with two mapped columns each qualifies.
- Nothing changes for single-column uploads.
phone_columnstill works on its own, the result column is still the plainOptimalDial_Status, andvalid_number_countequalsvalid_row_count. Noapi_versionbump.
2026-08-10 — Upload cancellation removed
- Breaking:
DELETE /api/v1/uploads/{id}is removed. It now returns410 Goneand no longer changes the upload or refunds credits. Submitting an upload is final — once we accept a list, we own the work and the refund decision. - The endpoint’s guarantees never held in practice: a cancel that arrived after processing began still flipped the upload to
cancelledwithout refunding anything, and a repeated call could erase the record of a refund that had already been paid out. - If you submitted an upload in error, email support@optimaldial.com with the upload id and we’ll refund the credits where the work hasn’t been done.
- The
cancelledstatus stays in theUploadschema so historical uploads still parse. No new upload can enter it.
2026-07-03 — Credit balance endpoint
- New Credit Balance API —
GET /api/v1/credits/balancereturns your organization’s current credit balance, split intosubscriptionandpurchasedpools plus atotal. Read-only, costs no credits, and available to every account with an API key. Use it to check remaining credits before submitting uploads or contacts.
2026-06-26 — Spam Monitoring API
- New Spam Monitoring API — track your outbound numbers for carrier spam/scam-likely flagging across AT&T, T-Mobile, and Verizon. Add a number, complete verification, then read per-carrier status, run history, and screenshots, or get pushed alerts over webhooks. Available to every account with an API key and an active subscription.
- New endpoints:
POST /api/v1/spam/numbers,GET /api/v1/spam/numbers,GET /api/v1/spam/numbers/{id},DELETE /api/v1/spam/numbers/{id},POST /api/v1/spam/numbers/{id}/verify,POST /api/v1/spam/numbers/{id}/verify/resend,GET /api/v1/spam/numbers/{id}/history, andGET /api/v1/spam/numbers/{id}/screenshot(streamsimage/png). - SMS-or-call verification. Adding a number auto-initiates verification; submit the code to
…/verify. Choosecall(default) orsms— SMS isn’t deliverable to landlines, so fall back tocall. Verification is required for monitoring to run, not a security gate. - Two new webhook events on the existing
POST /api/v1/webhooksendpoint:spam.detected— edge-triggered, fires once on a clean→spam transition per carrier (not on every daily re-test) — andnumber.verified. Same HMAC signing, headers, and retry semantics as existing events; noapi_versionbump.
2026-06-25 — Higher rate limits + per-row throughput
- Write-endpoint rate limits were raised and restructured into token-bucket tiers: 600/min per API key (was 60) and 1,500/min per organization (was 600).
POST /api/v1/contactsis now covered too, so high-volume per-row integrations (e.g. a Clay “Run column”) pace cleanly. 429responses gained ascopefield (per_key|per_org) andX-RateLimit-Limit/X-RateLimit-Remaining/X-RateLimit-Resetheaders; theobservedfield was removed.Retry-Afteris unchanged.- Buckets now refill continuously rather than resetting on a clock-aligned minute — burst up to the limit, then steady-state. Honor
Retry-Afterand large jobs drain without errors. - High-volume partner integrations can have their per-organization limit raised on request.
2026-06-24 — MAX validation tier on the Contacts API
POST /api/v1/contactsaccepts an optionalvalidation_tierfield (standard|max). Defaults tostandard, so existing integrations are unaffected. An unrecognized value returns400.maxhas no minimum submission size here — the 100-number floor applies only toPOST /api/v1/uploads. Per-row pipelines can requestmaxone contact at a time.- Because credits are whole numbers,
maxbills marginally on this endpoint: successivemaxcontacts are charged2, 1, 2, 1, …, so a queued batch of N totalsceil(N × 1.5)— the same price as those N numbers submitted as onemaxupload. Readcredits_chargedper response for the exact amount. See Validation tiers. - The contact object and the
contact.completed/contact.failedwebhook payloads now includevalidation_tier. Noapi_versionbump — the field is additive. - Documentation note: this field shipped on the date above but was missing from the Contacts API reference until 2026-08-11. The endpoint accepted
maxthroughout; only the docs were incomplete.
2026-06-24 — Contacts API generally available
- The Contacts API (
POST /api/v1/contacts,GET /api/v1/contacts,GET /api/v1/contacts/{contact_id}) is now available to every account with an API key. It was previously limited to Enterprise organizations. - This access change altered no request or response shapes. Calls no longer return
403 feature_not_enabled; access is gated only by your API key and credit balance.
2026-06-05 — MAX validation tier
POST /api/v1/uploadsaccepts an optionalvalidation_tierfield (standard|max) in both CSV and JSON modes. Defaults tostandard, so existing integrations are unaffected.maxis more thorough and is charged at 1.5 credits/number (billed asceil(valid_row_count × 1.5)). See Validation tiers.- The upload object now includes a
validation_tierfield.
2026-04-23 — v1 GA
Initial general availability of the public API. New endpointsPOST /api/v1/uploads— submit phone-number lists in CSV (multipart) or JSON form.GET /api/v1/uploads,GET /api/v1/uploads/{id}— list and retrieve uploads.DELETE /api/v1/uploads/{id}— cancel an upload that hasn’t started processing.GET /api/v1/uploads/{id}/download/{original|processed|processed-filtered}— short-lived signed download URLs.POST /api/v1/webhooks,GET /api/v1/webhooks,GET /api/v1/webhooks/{id},PATCH /api/v1/webhooks/{id},DELETE /api/v1/webhooks/{id}— manage webhook endpoints.GET /api/v1/webhooks/{id}/deliveries— recent delivery attempts for one endpoint.
od_live_*API keys, scoped to a single organization. Owner-only minting via the in-app developer panel; SHA-256 hashed at rest; auto-revoked when the creating user leaves the org.
- Three event types:
upload.created,upload.completed,upload.failed. - HMAC-SHA256 signatures over
{timestamp}.{body}, in Stripe-compatiblet=…,v1=…format. - 5-minute replay window.
- Up to 6 delivery attempts with backoff (1m, 5m, 30m, 2h, 12h between attempts).
- Endpoints auto-disabled after 20 consecutive failures.
- SSRF hardening: HTTPS-only, public IPs only, redirects not followed.
- 60 requests/minute per API key, 600 requests/minute per organization, on write endpoints.