Connecting a phone line, end to end
A working line is four things, not one: a number the carrier will route, an application that posts to a reachable public URL, a channel_routes row that says what the line is for and who may use it, and a real call proving all three. Configuration that has never carried a call is a guess. The last step is dialling the number yourself and reading both call logs side by side.
The chain, from no number to an answering line#
- Trigger — a business wants a number answered.
- User event — someone with access to both the carrier account and the workspace begins setup.
- Authentication and workspace resolution — credentials are stored per workspace; anything read outside that scope reads as empty.
- Ingest — the carrier's number, application and webhook targets are recorded.
- Canonical record — a
channel_routesrow: provider, assignment, inbound and outbound permission, hours, routing, recording policy, capabilities, limits, status. - Reasoning — the line's purpose selects the persona, the opening and the voice profile.
- Knowledge, memory and rules — the greeting text, the closed-line message and the behaviour block are set for this line.
- Autonomy and approval — outbound permission and the autonomy mode are decided here, not on the first call.
- Action through a provider — the carrier is pointed at the answer, turn and status URLs.
- Result — a real inbound call is placed and answered.
- Relationship, timeline and memory — the test call produces a
Callrow like any other, which is exactly the proof wanted. - Audit, usage and Needs You — the carrier's own log is compared with
calls, and line health starts reporting.
A line is not a new table. channel_routes already answers "whose endpoint is this and what is it for" for every channel, so the phone facts live there — including a person's browser line, which is a row with channel='softphone'.
The verifications, and what each one catches#
| Stage | What you see | What changes | What can fail |
|---|---|---|---|
| Credentials stored | The line shows its provider | Encrypted credentials on the workspace | Credentials read outside workspace scope look empty, and every real call is answered 403 before pickup |
| Public URL set | The line reports its webhook targets | The URLs the carrier will call | An unset public URL emits a host-less action URL: the greeting plays and the call goes silent |
| Answer URL wired | A test call is greeted | A Call row appears | The number is linked to the wrong application, or to none |
| Status URL understood | Nothing visible when correct | Provider status events recorded | The status URL is also the hangup URL; ending the call on *any* status once hung up on a live caller at ringing |
| Direction read | An outbound leg rings the person you dialled | direction and owner_kind on the call | A carrier posts to the same answer URL both ways; ignoring Direction greets your own agent as though they were the customer |
| Hours and purpose set | Out-of-hours callers hear the closed-line message | Hours and purpose on the route | Hours left empty, so nothing is ever out of hours |
Decisions to make before the first caller, not after#
- Purpose
inbound,service,transactionalorpromotional. It selects the voice profile and the behaviour block, and it is what "per campaign" means here — there is no separate campaign model.- Voice
- Connect's own text-to-speech, rather than the carrier's two voices and sixteen European locales. Settings live on the Phone screen's Behaviour section for both audiences.
- Closed-line message
- Deterministic, in the business's own name, and deliberately without opening hours in it. It is warmed alongside the greetings so an out-of-hours caller hears a sentence rather than a dropped line.
- Outbound permission
- Separate from inbound. A line that answers is not automatically a line that may call.
- Engine
- The turn-based carrier path is the default. The realtime engine is a separate, opt-in piece of setup with its own console steps.
What this line will not do#
Two capabilities are asked of the provider rather than assumed, through telephony.can, and neither is enabled on the live carrier: call recording, and a completed transfer to a person. The model and the tests for both exist; the usable capability is narrower than the code, and the screen says so rather than offering a control that does nothing.
The live carrier also carries no SMS. readiness.messaging states that on the Phone screen instead of presenting a message thread that cannot send. If a line's purpose depends on texting a caller, that is a provider decision to make before the line is promised to anyone.
Questions#
Why does the first test call matter so much?
Because every one of the known telephony defects here was silent. A signature check that passed, a URL that resolved, a setting that read as false — all looked correct and all produced a caller hearing nothing. A single real call, compared against the carrier's own log, catches what configuration review does not.
Can one workspace run several numbers?
Yes. Each is its own channel_routes row with its own purpose, hours, permissions and voice profile, and profiles resolve by purpose and by line number before falling back to the workspace default.
Where do the credentials live?
On the workspace, encrypted, and read only inside it. That scoping is not a detail: reading them outside the workspace is what made every real call fail with a refusal before the caller was even connected.