Connect by JBRH Open Connect

Calling from the browser

A softphone is a person's own phone line inside the browser: a channel_routes row with channel='softphone', a per-person SIP endpoint, and a dialler whose every state comes from a SIP event rather than from a click. Dialling does not hand the carrier a number to ring — the carrier posts back to the same answer URL a customer's call arrives on, marked Direction=outbound, and the XML decides who rings.

Status
Available What this means
Audience
both
Channels
softphone
In the app
#/calls
Last verified
Product version
6.3.2

A person's line is a route like any other#

channel_routes already answers "whose endpoint is this and what is it for" for email, WhatsApp and the business number, so a browser line is a row in it with channel='softphone'. That is not a filing decision; it is what lets the same permission, hours and routing logic apply to a person's line without a second implementation of any of it.

Each person gets their own SIP endpoint. The password is generated rather than chosen, stored encrypted, served only to its owner and only by POST, and can be revoked individually — one person losing a laptop is one credential, not a shared line everybody has to re-register.

The address that answers#

The registrar address comes from the provider's own browser SDK. Their written documentation names a different one, which answers nothing from any network — every browser registration failed while both the code and the CSP pointed at the documented address.

wss://registrar.vobiz.ai:5063   # the address the provider's browser SDK uses
# the address in the provider's written documentation does not answer

The lesson generalises past this one carrier: when a browser transport silently never connects, verify the endpoint against what the vendor's own client library uses at runtime, not against what their reference page says it should be.

Every state comes from a SIP event#

The dialler never shows a state because somebody clicked something. Ringing, answered, held, ended — each is rendered from the SIP event that says so. A click that produces no event produces no state change, which looks unresponsive for a moment and is honest: the alternative is a dialler that says "connected" while the far end is silent.

That rule is why a registration problem shows up as a line that never becomes ready, rather than as a call that appears to place itself and then does nothing.

How a browser call actually rings somebody#

  1. The dialler sends a SIP INVITE to the endpoint's registrar with the number in it.

    Result The carrier does not dial that number. This is the step most people assume and it is wrong.

  2. The carrier posts to the voice application's answer URL — the same URL a customer's inbound call arrives on — carrying Direction=outbound.

    Result One handler now has two completely different jobs, told apart only by that field.

  3. carrier_incoming matches the From value against the workspace's channel='softphone' routes.

    Result The call is attributed to the person whose endpoint placed it, inside the owning workspace.

  4. may_place_call is asked under the business's own line.

    Result Memory blocks, consent, autonomy and budget apply to a person's browser call exactly as they apply to one Connect places itself.

  5. The answer is <Dial callerId=…> — or a spoken refusal, if the gate said no.

    Result Only now does a phone ring anywhere. The bridged leg is written as a Call with direction='outbound' and owner_kind='human', so the record distinguishes a person's call from the voice's.

An endpoint that is not attached to the voice application registers perfectly and can never place a call. The registration is with the registrar; the dialling is done by the application. Both have to be true, and only one of them is visible in the dialler.

The defect this design produced#

Direction was, for a while, never read. Because the carrier posts to the same answer URL either way, a person dialling out from the browser was greeted as though they were a customer calling in — and the number they had dialled never rang at all. Nothing errored; the greeting played into the agent's own headset.

Reading the carrier's own call log next to the calls table is the fastest audit available for this class of fault. A completed call on their side with no matching row on yours is a bug every time, and it is the only way some of these show up.

Questions#

Does a browser call go through the same rules as an automated one?

Yes. may_place_call runs under the business's line for both, so a suppressed number, a memory block, an autonomy rule or a spent budget stops a person's browser call the same way it stops one the voice would have placed. The refusal is spoken rather than silent.

Why does my line register but every call fail?

The endpoint is almost certainly not attached to the voice application. Registration is a conversation with the registrar and succeeds on its own; placing a call depends on the application answering the carrier's request with dialling instructions.

Can two people share one softphone endpoint?

They should not. Each endpoint is a channel_routes row with its own generated credential, and call attribution — including owner_kind='human' on the resulting record — is done by matching the endpoint. Sharing one makes every call on it belong to the wrong person.