Skip to main content

How It Works

An inbound call is a call someone places to one of your TopCalls phone numbers. You decide which campaign answers it.
  1. You attach a campaign to a phone number with PATCH /v1/phone-numbers/{phone_number_id}.
  2. You start the campaign with POST /v1/campaigns/{id}/start. Until then the number stays silent, even if it is attached.
  3. When the number rings, TopCalls checks that the campaign is running, then the campaign’s business hours and your account’s concurrency limit.
  4. The call is answered and the caller hears the campaign’s first_sentence.
  5. The campaign takes over the conversation, exactly as it does on an outbound call: same prompt, same knowledge base, same tools.
  6. When the call ends you receive the usual completion webhook, and the call appears in GET /v1/calls with direction: "inbound".
Greeting, who speaks first, max duration and webhook live on the campaign, not on the number. Enabling fails with 422 when the campaign has no first_sentence. Inbound calls have no lead, so a first_sentence that still contains a {{...}} placeholder is rejected with 422 (code: "greeting_placeholder"). Write the opening line as an answer: who is speaking, and what the caller can ask for.

Campaign direction

An inbound campaign has direction: "inbound". Create it, attach a number with PATCH /v1/phone-numbers/{id}, then POST /v1/campaigns/{id}/start — the same start/pause/resume/stop as outbound. It is never dialled and needs no lead list. Callers are answered only while status is running. Pause stops answering; resume starts again; stop completes it. POST /v1/campaigns/{id}/test still places a billed outbound test call to a number you pass, using this campaign’s prompt. A number can only be routed to an inbound campaign. Switching a draft campaign back to outbound while a number still routes to it returns 409 (code: "campaign_has_inbound_routes"); disable the routing first. Bring-your-own-trunk (BYOT) numbers must originate from static source ranges, or use registration or credential authentication. A carrier that sends inbound calls from more than one address declares each range as its own inbound gateway: the primary gateway on sip_gateway, and any additional ranges in inbound_gateways. Each inbound range is an IPv4 address or a CIDR (ipv4 plus an optional netmask, defaulting to 32); hostnames are rejected for inbound because inbound calls are matched by source IP. A BYOT number whose carrier has no active inbound gateway is refused at enable time with 422 (code: "carrier_no_inbound_gateway"). For a provider that originates from several ranges, add the carrier with every range declared:
The primary sip_gateway still carries outbound dialling; each inbound_gateways entry is inbound-only. Omitting inbound_gateways keeps the original single-gateway behaviour.

Business Hours

By default a running inbound campaign answers around the clock. Restrict the window on the campaign (config.inbound_business_hours): timezone, weekdays (0 is Sunday), and HH:MM start/end. An overnight window (start after end) stays open past midnight on the weekday the night started on. Outside that window the call is declined without being answered. Sending business_hours on the number is rejected with 400.

Answering Style

Who speaks first is a campaign setting (first_sentence_wait_for_caller):
  • Off (default) speaks the campaign first_sentence as soon as the call is answered.
  • On answers the line silently and lets the caller speak first, then speaks the greeting after the caller’s first sentence (waiting at most 5 seconds, or the campaign’s first_sentence_delay_seconds).

Concurrency and Duration

  • Each account can have a limited number of inbound calls in progress at the same time. When the limit is reached, additional callers are declined until a call ends.
  • The campaign’s max_duration caps an inbound call in minutes (1 to 60). When it is reached the agent wraps up and the call ends.
  • Inbound calls consume plan minutes the same way outbound calls do. When the balance is exhausted, the caller hears a short unavailable message and the call ends.

What You Receive

The call object

Inbound calls appear in GET /v1/calls and GET /v1/calls/{call_id} alongside outbound calls. These fields tell them apart: phone_number is always the other party, so GET /v1/calls?phone_number=+40... finds every conversation with that person in either direction. Filter by direction with GET /v1/calls?direction=inbound. A caller who withholds their number is recorded with phone_number set to "+10000000000".

The webhook

The completion webhook carries the same payload as for outbound calls, plus:
  • direction: "inbound" or "outbound".
  • caller_name: the name presented by the caller’s network, when available. Present only on inbound calls; null when the network did not provide one.
Inbound calls use the campaign’s webhook.

Enabling Inbound on a Number

The number must be active and the campaign must belong to your account, have direction: "inbound", not be cancelled or completed, and use the standard (non-realtime) mode. campaign_id is required when enabling. The campaign must already have a first_sentence. Greeting, who speaks first, hours, max duration and webhook live on the campaign. Sending those fields on inbound is rejected with 400. Enabling wires the number. The campaign answers only after POST /v1/campaigns/{id}/start (and while status stays running).
The response is the phone number object with its stored inbound routing:
Enabling runs the campaign prompt through the same safety review as an outbound campaign. A refused prompt returns 422 with a code naming the reason, and the number stays unchanged. Each enabling request is the complete routing for the number: the stored settings are replaced by what you send, and any optional field you leave out returns to its default. To change one setting, resend the whole inbound object with the change applied.

Errors

Disabling Inbound

Disabling always succeeds, whatever the state of the number or the campaign. Callers are declined from the next call onwards; a call already in progress runs to its end. The previous settings remain visible on the phone number object, so you can copy them into a new enabling request. Re-enabling goes through the safety review again. Deleting the campaign detaches it from the number: the number stays enabled but declines callers until a new campaign is attached.

Current Limits

  • Calls are answered by the campaign only. Transferring a caller to a person is not available yet.
  • Campaigns in the realtime mode cannot answer inbound calls. Use the standard mode.
  • One number answers with one campaign. To route by menu choice, build the routing into the campaign prompt.

Making Calls

Outbound calls, campaigns and call configuration.

Webhooks

The completion payload, retries and filtering.

API Reference

Phone number and call endpoints.