Skip to content
Docs

Verticals

Call tracking

Tracking numbers, dynamic number insertion pools, buyer routing, qualification rules and call conversions.

Call tracking attributes phone calls to the click or campaign that caused them and turns qualified calls into conversions with payouts, just like web conversions.

Provider

Telephony runs through a provider. Twilio is supported (and a deterministic fake for testing). Configure it with PUT /calls/provider: provider, credentials (sealed with DT_SECRETS_KEY), and the public origin the provider will call back. The provider calls Metrixed at POST /calls/voice/{provider}/{tenant} for call control and POST /calls/webhook/{provider}/{tenant} for status and recordings; those endpoints are authenticated by the provider's signature, not an API key. DT_TWILIO_BASE_URL overrides the Twilio API base for tests.

Numbers, pools and routing

ObjectPurpose
NumbersTracking numbers you search for (GET /calls/numbers/available), buy and assign, in E.164 format.
PoolsA set of numbers shared by visitors for dynamic number insertion (DNI).
DestinationsBuyer phone numbers with time zone, business hours, weight and position.
RoutesHow a number's calls reach destinations.

Routing strategies: round_robin, weighted and priority, with a fallback number dialled when no destination is open or available, and an optional press-1 menu (IVR) that maps digits to destinations. Business hours are weekday windows in the destination's time zone; a window that ends before it starts runs past midnight.

Dynamic number insertion

DNI shows each web visitor a different number from a pool so a call can be tied back to a visit.

  1. Include the snippet from the pool page. It loads /dni.js from ingest (under 3 kB).
  2. The script asks POST /dni/v1/assign for a number, keyed by the click id (or a session id). The assignment is a lease held in Redis for the pool's TTL, so the same visitor keeps the same number and a number is shared by only one visitor at a time.
  3. When a call arrives on a leased number, the webhook looks up the lease and finds the click, hence the offer and partner. If every number in the pool is busy the visitor gets the pool's fallback number and the call is unattributed.

Pools are published to Redis with POST /calls/pools/{id}/publish. Set DT_API_REDIS_ADDR on the API, DT_INGEST_DNI_REDIS_ADDR (or DT_INGEST_REDIS_ADDR) on ingest, and DT_CALLS_INGEST_URL so the snippet points at your ingest origin.

Qualification and conversions

A finished call becomes a conversion only if it qualifies. Per offer or route the rules are:

RuleReason code when it fails
The call was answered and completednot_answered
Minimum duration in secondstoo_short
Inside the destination's business hours (optional)outside_business_hours
No qualified call from the same caller for the same offer within a repeat window (optional)repeat_caller

Qualified calls are converted by the calls worker (calls-sync, with retries) through an internal ingest path, so they pass the normal payout engine, caps and fraud hooks and arrive as ordinary conversions (conversion method call). Calls are mirrored to ClickHouse for reporting. Caller numbers are stored only as a salted hash, never in the clear.

Reports and portals

Traffic, Call log, Numbers & pools and Call routing in the admin portal; GET /calls/stats and the call log API for analysis; partners get their own statistics through GET /partner/calls/stats. Calls on partner-less pools keep the partner empty until ingest resolves it from the click, so those calls are missing from partner statistics.

Switches

DT_CALLS_DISABLE=1 stops the calls worker; DT_CALLS_INTERVAL sets its poll period.