# Your business number in Connect

Your business number becomes a line the moment a workspace claims it as a `channel_routes` row. That row is the whole configuration: which provider carries the number, who or what it is assigned to, whether it may take calls in or place them out, its opening hours, its routing, its recording policy, the provider capabilities behind it and its limits.

- **Status:** Available
- **Audience:** both
- **Channels:** phone
- **In the app:** #/calls
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/phone/business-number/

## A line is a row, not a table

`channel_routes` already answers one question for every channel Connect speaks on: whose endpoint is this, and what is it for. A mailbox is a row there. A WhatsApp sender is a row there. So a phone number is a row there too, and every phone fact hangs off it rather than off a table invented for telephony.

That has a consequence worth knowing before you configure anything: a person's browser line is the same kind of object. A softphone endpoint is a `channel_routes` row with `channel='softphone'`, which is why an outbound call from the browser can be checked against the business's own line rather than trusted because a logged-in person clicked dial.

Claiming is what turns a number at a carrier into a line here. Until a workspace owns the row, an inbound call on that number reaches no workspace, and the handler has nothing to enter — no settings, no credentials, no greeting. That is not an error state to debug in the conversation layer; it is a number that has not been claimed.

## What the line carries

| Fact | What it decides | Read by |
|---|---|---|
| Provider | Which adapter speaks to the carrier, and which capabilities are even askable | `telephony.can()` |
| Assignment | Whether the line is the business's own, a purpose, or one person's browser endpoint | Routing and the softphone match on `From` |
| Inbound permission | Whether a call arriving on this number is answered at all | The inbound handler |
| Outbound permission | Whether Connect or a person may place a call from this number | `may_place_call` |
| Hours | When the line is open, in the line's own timezone | The closed-line refusal and follow-up scheduling |
| Routing | Which workspace and which behaviour the call belongs to | `carrier_incoming` |
| Recording policy | What would be recorded if the provider allowed it | `telephony.CAPABILITIES` — see the caution below |
| Capabilities | The provider's answers about recording, transfer and WebRTC | Everything that must not assume |
| Limits | Per-line ceilings on what may be spent or held | Admission and metering |
| Status | Whether the line is on, off, or unhealthy | The Phone screen and Needs You |

> **Careful** A recording policy on the line is a statement of intent, not a guarantee that recording happens. Call recording is `foundation`: the capability is asked of the provider, and it is not enabled on the live carrier. Never plan a process around an audio file you can play back.

## Choosing a number

1. Get a number from a carrier Connect has an adapter for, in the country you actually trade in.
   - Result: The number exists at the provider but does nothing in Connect yet.
2. Point it at Connect. On the turn-based path that means the carrier's application posts to Connect's answer URL; on the realtime path the number is linked at the carrier to an inbound trunk whose origination URI is the LiveKit project's SIP host.
   - Result: Calls arrive as signed webhooks or as a SIP leg that spawns a worker.
3. Claim it in the workspace, so the `channel_routes` row exists with a provider and an assignment.
   - Result: The number now resolves to exactly one workspace, and a handler can enter that workspace before it reads any setting.
4. Set inbound permission, outbound permission and hours.
   - Result: The line answers, or refuses in words, according to rules you can point at.

> **Note** Linking a number to a trunk is console work at the carrier and cannot be done through an API on the live provider. The origination URI is written as `host:5060` with **no** `sip:` prefix, and the host is the LiveKit project's own SIP subdomain rather than the server URL you use elsewhere. Both details have cost real time when guessed.

## One number, several jobs

A workspace normally wants more than one behaviour from its telephony: a main line that answers anyone, a line that only ever calls out, a person's own extension in the browser. Because each of those is a row rather than a mode, they can differ completely — different hours, different permissions, different voice profile — while sharing the same workspace, the same records and the same audit trail.

Voice profiles resolve down that same hierarchy: the workspace's setting is the base, then the default profile, then a profile chosen by purpose, then a profile pinned to a line number, then one set on the contact. The narrowest wins. That is why giving a second number its own personality does not require a second configuration of everything else.

## Questions

### Can I keep my existing business number?

If it can be ported to, or forwarded from, a carrier Connect has an adapter for, yes — nothing in Connect requires a newly issued number. What Connect needs is a number whose calls arrive at its answer URL or its SIP trunk, and a `channel_routes` row that says which workspace owns it.

### What happens to a call on a number no workspace has claimed?

It resolves to nothing. There are no settings to read, no greeting to speak and no `Call` row to write, so the useful diagnosis is at the carrier: the number is pointed at Connect but not claimed here. Claiming it is the fix, not a change to the conversation.

### Is a softphone extension a phone number?

It is a SIP endpoint rather than a public number, but it is stored the same way — a `channel_routes` row with `channel='softphone'` — so it inherits the same permission checks. A browser call is authorised against the business's line, which is why an endpoint that is not attached to the voice application registers happily and can still never place a call.

## Related

- [Configuring a phone line](https://connectbyjbrh.com/docs/phone/line-configuration/)
- [How a call reaches your workspace](https://connectbyjbrh.com/docs/phone/carrier-routing/)
- [Business hours and the closed line](https://connectbyjbrh.com/docs/phone/business-hours/)
- [Calling from the browser](https://connectbyjbrh.com/docs/phone/softphone/)
- [Voice profiles](https://connectbyjbrh.com/docs/phone/voice-profile/)
- [Security and isolation](https://connectbyjbrh.com/docs/security/)

## What this page is based on

- AGENTS.md §9a — `channel_routes` as the line record (via docs-source/sources/PHONE.md)
- `backend/app/telephony.py` — provider capabilities
- `backend/app/softphone.py` — browser endpoints as routes
- Connect capability registry (docs-source/facts.py)
