E911 Dispatch Addresses
When a user dials 911 from a DialStack device, the platform must tell the upstream provider where the call originates so emergency services can dispatch to the correct address. This guide explains the object model behind that lookup, how to provision and assign locations through the API, and what happens at call time.
US federal law (Kari's Law and RAY BAUM's Act) makes this dispatch obligation strict: the address must be specific enough for first responders to find the caller, and 911 must be reachable without prefixes or unlocking. DialStack handles the carrier side of that obligation; the account is responsible for keeping each device's location current as people move desks, branches, or sites.
Object model
The dispatch lookup involves two kinds of resources:
- Location — a physical site (
name, structuredaddress). Once registered with the upstream provider it gains ane911_status. - Device — a physical thing that sits at a site:
- Deskphone — a desktop PoE/WiFi phone. Carries its own
location. - DECT base — a box that hosts one or more wireless handsets. Carries its own
location. Every handset paired with the base inherits it, because the base radio defines where the handset can physically reach. - DECT handset — a cordless handset paired with a base. Has no
locationof its own.
- Deskphone — a desktop PoE/WiFi phone. Carries its own
Softphone and in-app SDK calls don't follow this model — they have no physical device. They use a per-user emergency-address flow described in Emergency Calling (E911).
Provisioning a location for E911
Create the location with its street address, then register it for E911. The carrier validates the address and assigns a registration ID; the location is unusable for emergency dispatch until that completes.
const location = await dialstack.locations.create({
name: 'New York HQ',
address: {
address_number: '350',
street: '5th Avenue',
unit: 'Suite 4200',
city: 'New York',
state: 'NY',
postal_code: '10118',
country: 'US',
},
});
await dialstack.locations.provisionE911(location.id);
The location moves through a status machine:
e911_status | Meaning |
|---|---|
none | No registration attempted yet. |
pending | Submitted to the carrier; waiting for a response. |
binding | Carrier accepted the address and is finalizing the dispatch record. |
provisioned | Ready. Emergency calls from devices assigned here will dispatch to this address. |
failed | Carrier rejected the registration (typically a non-deliverable address). Retry from the admin portal or the API. |
Only provisioned locations are usable at call time. Assigning a device to a location that is still pending or failed is allowed (so admins can pre-stage during onboarding), but the call-time lookup treats it as unassigned.
Assigning a device to a location
Set location on the device itself, at create time or later. The unified /v1/devices endpoint covers all three device kinds:
// Deskphone — register the MAC and bind it to a location in one call
await dialstack.devices.create({
type: 'deskphone',
mac_address: '00:04:13:aa:bb:cc',
location: locationId,
});
// DECT base — shared by every handset paired with this base
await dialstack.devices.create({
type: 'dect_base',
mac_address: '00:04:13:bb:cc:dd',
location: locationId,
});
// Move a base to a different site (e.g. branch office reshuffle)
await dialstack.devices.update(baseId, { location: locationId });
// Reset to the default location
await dialstack.devices.update(deviceId, { location: null });
Deskphones and DECT bases always have a location. When you create one without it, or update it to explicit JSON null, it gets a default: the account's only location, else the location of a user on the device, else the account's main location. A default is a guess, so set the real site for devices at secondary locations. Before assigning a user seated at another location, move the device to that site, or the assignment returns 409 location_conflict. On update, omit location to leave it unchanged. DECT handsets have no location of their own — to change where a handset dispatches, change its paired base's location, or re-pair the handset to a base at the target site (POST /v1/devices/:handset_id with base).
The deprecated location_id field is still accepted as an alias of location.
The Location ID must reference a location on the same account; cross-account assignment is rejected at the API layer.
Call-time resolution
When a user dials 911 (or another configured emergency number), DialStack resolves the dispatch address by walking from the calling user to the device they're assigned to:
- DECT handset → paired DECT base → base's
location. - Deskphone → deskphone's
location. - Softphone / SDK call → no device. The call uses the user's per-call registered emergency address instead; see Emergency Calling (E911).
- Deskphone or DECT handset with no user assigned (for example, after a hot-desk logout, or while its user is logged in on another phone) → the deskphone's
location, or the handset's paired base's. The phone can dial only 911, the 933 test line and the hot-desk login codes. Its caller ID is the account's default outbound number, falling back to the first active outbound number.
For device-backed calls, only a location with e911_status: provisioned is used. If the base's location isn't dispatchable (still pending, for example) the lookup falls through to the deskphone candidate; if neither is dispatchable, the call still completes but no dispatch address is sent (the call.emergency webhook reports e911_provisioned: false).
When a dispatchable location is resolved, the call carries its registration so the carrier can route it to the correct emergency dispatch center — the public safety answering point (PSAP) — with the correct address on file.
Outbound calls need a dispatchable location
A deskphone or DECT handset whose location doesn't resolve to a provisioned location can't place non-emergency calls to outside numbers: the caller hears an announcement that the phone has no registered emergency address, and the call ends. 911 and the 933 test line always go through, and calls between extensions on the account are not affected. Provisioning the location, or assigning the device to a provisioned one, lifts the block on the next call.
The call.emergency webhook
Every emergency call fires a call.emergency webhook, which carries the call, the user, the device and the resolved location. See Webhook Events for the payload.
e911_provisioned: false means the platform completed the call but could not attach a dispatch address — first responders will fall back to whatever default the carrier has on file for the underlying number, which is rarely the actual caller location. The webhook fires on every direct emergency call regardless of dispatchability, so treat false as an actionable signal even if the moment of the call itself was missed: alert the admin, the front desk, or whoever is best placed to clear the misconfiguration.
When an emergency call is placed via a transfer, e911_provisioned is omitted from the payload entirely (not false). On a transfer the platform deliberately attaches no dispatch address — it cannot know whether the transferring or transferred party's location is correct — and lets emergency dispatch resolve it. The field's absence distinguishes this intentional case from an unprovisioned direct call.
user is absent when the call came from a phone with no user assigned; device identifies the phone instead. A call from a phone with an active hot-desk session carries the logged-in user.
This webhook is the recommended hook for any in-building notification you need to layer on top — paging a security desk, flashing a kiosk, sending an SMS to the receptionist.
Failure modes
| Situation | What happens at call time |
|---|---|
Assigned location is still pending / binding / failed | 911 completes, e911_provisioned: false. No dispatch address sent. Non-emergency outside calls are blocked. |
| Call placed via a transfer | Call completes, no dispatch address attached by design; e911_provisioned is omitted from the webhook (emergency dispatch resolves the location). |
A location can't be deleted while a device is still assigned to it: DELETE /v1/locations/{location_id} returns 409 with code: location_in_use. Reassign the devices first.
Testing in non-production environments
Do not place real 911 calls to test. Dial 933 instead — the carrier's non-routable test number that exercises the full dispatch flow (address lookup and the call.emergency webhook) and reads the registered address back to the caller, without contacting a real PSAP.
Related
- Admin portal: Locations, Devices
- API: Webhook Events, Device Provisioning