Connect by JBRH Open Connect

Making a call from the browser

A browser line is a channel_routes row with channel='softphone', registered over SIP-to-WebSocket with a per-person endpoint. Pressing dial sends an invite the carrier does not act on directly: it posts to the same answer URL a customer's call arrives on, marked as outbound, and Connect answers with a dial instruction under the business's own line. The bridged leg is a call owned by the person, not the engine.

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

The chain, from a click to a ringing handset#

  1. Trigger — a person presses dial in the app.
  2. User event — the browser sends a SIP invite to the endpoint's registrar over a WebSocket.
  3. Authentication and workspace resolution — the endpoint is per person, its password generated and stored encrypted; the workspace is entered before any line setting is read.
  4. Ingest — the carrier posts to the application's answer URL with the direction marked outbound.
  5. Canonical record — the caller is matched against the workspace's softphone routes.
  6. Reasoning — no model is involved; this is a person's call, and the engine's job is permission and routing.
  7. Knowledge, memory and rules — the business line's own caller identity and permissions apply, not the person's.
  8. Autonomy and approval — may_place_call is asked under the business's line before anything is dialled.
  9. Action through a provider — the answer is a dial instruction with the business's caller identity, or a spoken refusal.
  10. Result — the far end rings; the bridged leg is a Call with an outbound direction and a human owner.
  11. Relationship, timeline and memory — the call joins the person's history like any other.
  12. Audit, usage and Needs You — cost and duration are booked; a stale session is swept even though no worker holds it.

The invite does not dial the number in it#

This is the part that surprises everyone. The dialer sends an invite to the registrar; the carrier does not place a call to the number inside it. Instead it posts to the voice application's answer URL — the same one an inbound customer call arrives on — and does whatever the returned document says. So an endpoint that registers perfectly but is not attached to the voice application can never place a call, and nothing about the registration will tell you.

The corollary is the sixth production defect on this path: because both directions arrive at the same URL, a handler that never reads the direction greets its own colleague as though they were the customer, and the person they dialled never rings at all.

StageWhat you seeWhat changesWhat can fail
RegistrationThe line shows as registeredA SIP session from the browserThe wrong registrar address — the one in the provider's written documentation answers nothing from any network
PolicyNothingNothingThe content security policy does not name the SIP WebSocket, and the line silently never registers
Dial pressedDialling stateAn invite to the registrarAn endpoint not attached to the voice application: registered, and unable to call
Answer URL postedStill diallingDirection read; softphone route matchedDirection ignored, so the agent is greeted as a customer
PermissionEither it rings or a refusal is spokenmay_place_call under the business's lineThe business line has no outbound permission, or hours are closed
BridgeThe far end ringsA Call row, outbound, human-ownedA leg answered at the carrier that never joins is written off rather than waited on
Registrar (SIP over WebSocket, from the browser):
  wss://registrar.vobiz.ai:5063

The same host must appear in the app's content security policy.
A registration that never happens looks identical to one nobody tried.

Every state on the dialer comes from a SIP event#

Nothing the dialer displays is inferred from the click that caused it. Ringing means a ringing event arrived; connected means the session established. A dialer that shows "connected" because a button was pressed is a dialer that lies exactly when it matters — during the seconds a person is deciding whether the call failed.

The endpoint's password is generated rather than chosen, stored encrypted, served only to its owner and by a request that carries it in the body rather than a URL, and revocable one person at a time. A shared browser line would make the human-owner attribution on the call record meaningless.

What the record says afterwards#

  • The bridged leg is a Call with an outbound direction and a human owner, which is how the ledger separates a person's calls from the engine's.
  • The business's caller identity is what the far end sees, not the person's own number.
  • The call is metered and swept like any other. Because no worker holds a browser call, the sweep runs from the engine tick too — a browser call once sat active for the better part of a day.
  • Recording is not part of this path either: it is a foundation capability and is not enabled on the live carrier.

Questions#

The browser line registers but every call fails. What is it?

Almost always the endpoint is not attached to the voice application. Registration proves the browser can reach the registrar; placing a call additionally requires the carrier to post to the application's answer URL and receive a dial instruction back. The two are independent, and only one of them shows a green state.

Whose number does the person being called see?

The business line's caller identity. The dial instruction is answered under the workspace's own line, which is also why permission is checked against that line rather than against the individual's endpoint.

Why did nothing register at all, with no error?

The content security policy has to name the SIP WebSocket host. When it does not, the connection is refused by the browser before the SIP stack sees anything, and the line simply never appears — no failure, no state, nothing.