Migrating from 911 Access Dashboard (DASH)
Moving from the DASH API to the Unified Emergency Services Provisioning API on the Bandwidth App? This guide covers everything you need to make the switch.
For the complete API reference, see the ES Provisioning API Reference and the ES Provisioning API Usage Guide.
Before you start
Before writing any code, you need:
- A Bandwidth App account : if you don't have one yet, contact your account manager.
- Bandwidth App API credentials : your DASH API credentials will not work on the new API. Create new API credentials on your Bandwidth App account (Account > API Credentials) or the Bandwidth API. The Bandwidth App does not support HTTP Basic authentication; you will need to implement OAuth2.
You can develop and test against the ES Provisioning API independently of your endpoints migration.
Overview of Changes
| DASH API | ES Provisioning API | |
|---|---|---|
| Production Base URL | https://service.dashcs.com/ | https://api.bandwidth.com/ |
| Staging Base URL | https://staging-service.dashcs.com/ | https://test.api.bandwidth.com |
| Protocol | REST, SOAP | REST |
| Content type | XML | JSON |
| Authentication | HTTP Basic | OAuth2 |
| Processing | Synchronous | Asynchronous (with order tracking) |
| Phone number format | 11-digit | E.164 |
| Region support | Not applicable (US/Canada only) | Mandatory region parameter (NA/ROW) |
New workflow
The biggest conceptual change is how addresses and endpoints relate to each other.
In DASH, an address and a phone number (URI) are bound together as a single "location". You add a location, then provision it.
In the ES Provisioning API, addresses and endpoints are decoupled. You create an address first, then create an endpoint that links a phone number to that address. Endpoint operations are asynchronous and return an order you must poll for completion.
DASH workflow
- Add a location (binds an address to a URI):
POST /addlocation- Returns a
locationId
- Returns a
- Provision that location:
POST /provisionlocation
ES Provisioning API workflow
- Create an address :
POST /accounts/{accountId}/emergency/addresses?region=NA- Synchronous. Validates the address and returns the address
idimmediately. - The address exists independently and is not yet linked to any phone number.
- Synchronous. Validates the address and returns the address
- Create an endpoint :
POST /accounts/{accountId}/emergency/endpoints?region=NA- Links a phone number to the address (using the address
idfrom step 1) and provisions it in the background. - Asynchronous. Returns an
orderId.
- Links a phone number to the address (using the address
- Poll the order :
GET /accounts/{accountId}/emergency/orders/{orderId}/details?region=NA- Check until status is
COMPLETED(orPARTIAL/FAILED).
- Check until status is
Because addresses are decoupled, you can create many addresses up front and reuse them across endpoints. You can also provide a full inline address when creating an endpoint instead of referencing an address id, but creating addresses separately is the recommended pattern.
API calls migration
This section shows the DASH request/response alongside the ES Provisioning API equivalent for each common operation.
All ES Provisioning API paths require the ?region=NA query parameter.
Add an address (formerly: Add a location)
What changed:
- Response includes the unique address
idyou will use for endpoints - Response includes
validationStatus:VALIDorINVALID, no separate/validateLocationstep - Addresses are decoupled from phone numbers (no
uriparameter) countryis now required<type>ADDRESS</type>is no longer needed- Field change:
communityis nowcity
Request
- DASH
- ES Provisioning API
POST /addlocation
<addLocation>
<uri>
<uri>13035551236</uri>
<callername>Bandwidth Test User 3</callername>
</uri>
<location>
<address1>1860 Blake St</address1>
<address2>Suite 420</address2>
<community>Denver</community>
<postalcode>80202</postalcode>
<plusfour></plusfour>
<state>CO</state>
<type>ADDRESS</type>
</location>
</addLocation>
POST /accounts/{accountId}/emergency/addresses?region=NA
Authorization: Bearer <token>
Content-Type: application/json
{
"id": "home_office",
"description": "Home office, downstairs",
"addressLine1": "14111 NE 145th St",
"addressLine2": "Apt. 8",
"city": "Woodinville",
"state": "WA",
"postalCode": "98072",
"country": "US"
}
Response
- DASH
- ES Provisioning API
<ns0:addLocationResponse xmlns:ns0="http://dashcs.com/api/v1/emergency"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Location>
<activatedtime>2018-03-12T13:24:26.296Z</activatedtime>
<address1>1860 BLAKE ST</address1>
<address2>STE 420</address2>
<callername>Bandwidth Test User 3</callername>
<community>DENVER</community>
<legacydata>
<housenumber>1860</housenumber>
<streetname>BLAKE ST</streetname>
<suite>STE 420</suite>
</legacydata>
<locationid>67880038</locationid>
<latitude>39.753095</latitude>
<longitude>-104.995857</longitude>
<plusfour>1228</plusfour>
<postalcode>80202</postalcode>
<state>CO</state>
<status>
<code>GEOCODED</code>
<description>Location is geocoded</description>
</status>
<type>ADDRESS</type>
</Location>
</ns0:addLocationResponse>
{
"id": "homeoffice",
"validationStatus": "VALID",
"address": "14024 NE 181st St, Apt. 8",
"addressLine1": "14024 NE 181st St",
"addressLine2": "Apt. 8",
"houseNumber": "14024",
"predirectional": "NE",
"postdirectional": "",
"streetName": "181st",
"streetSuffix": "ST",
"city": "Woodinville",
"state": "WA",
"postalCode": "98072",
"country": "US",
"description": "Home office, upstairs",
"latitude": "47.732682",
"longitude": "-122.155174",
"created": "2015-03-11T04:09:25.399Z",
"updated": "2016-03-11T04:09:25.399Z"
}
Create an endpoint (formerly: Provision a location)
What changed:
- Addresses are decoupled from phone numbers, the
uribecomesphoneNumberin E.164 format - No separate provision step: creating an endpoint links a phone number to an address and activates it
- The address is referenced by
addressId(you can also include a full inline address object) - The response is an order acknowledgement, not the final status. You must poll for completion (see Order tracking)
- You can provision up to 5000 endpoints in one call
Request
- DASH
- ES Provisioning API
POST /provisionlocation
<provisionLocation>
<locationid>67880038</locationid>
</provisionLocation>
POST /accounts/{accountId}/emergency/endpoints?region=NA
Authorization: Bearer <token>
Content-Type: application/json
{
"endpoints": [
{
"phoneNumber": "+15555555555",
"name": "Caller Name",
"lang": "en",
"country": "USA",
"addressId": "7888993"
}
]
}
Response
- DASH
- ES Provisioning API
<ns0:provisionLocationResponse xmlns:ns0="http://dashcs.com/api/v1/emergency">
<LocationStatus>
<code>PROVISIONED</code>
<description>Location is currently provisioned for URI</description>
</LocationStatus>
</ns0:provisionLocationResponse>
{
"orderId": "08e0be9a-52fd-45a0-be2e-86835c534aad",
"updatedBy": "joe@crabshack.com",
"orderStatus": "PROCESSING",
"acceptedCount": 1,
"invalidCount": 0,
"updated": "2022-05-18T08:57:04Z",
"totalNumber": 1,
"orderType": "ADD_ENDPOINTS"
}
Query endpoints and addresses (formerly: Query locations by URI)
What changed:
- DASH had separate endpoints for listing URIs (
GET /uris), getting locations for a URI (GET /locationsbyuri), and getting the provisioned location (GET /provisionedlocationbyuri). The ES Provisioning API consolidates all of this intoGET /endpointswith optional filters. - Address details are not included in the endpoint response, it contains only the address
id - Phone numbers (formerly URI) now require E.164 format
- Supports pagination (
limitandoffsetquery parameters) - Supports filtering (
phoneNumber,addressId,callerId) - Field change:
callernameis nowname
Request
- DASH
- ES Provisioning API
GET /locationsbyuris/{uri}
GET /accounts/{accountId}/emergency/endpoints/?region=NA&phoneNumber=%2B1303555432
Authorization: Bearer <token>
Response
- DASH
- ES Provisioning API
<ns0:getLocationsByURIResponse xmlns:ns0="http://dashcs.com/api/v1/emergency"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Locations>
<activatedtime>2014-10-08T16:57:48Z</activatedtime>
<address1>1855 BLAKE ST</address1>
<callername>Bandwidth Test User 1</callername>
<community>DENVER</community>
<legacydata>
<housenumber>1855</housenumber>
<streetname>BLAKE ST</streetname>
</legacydata>
<locationid>20914831</locationid>
<latitude>39.75302</latitude>
<longitude>-104.996203</longitude>
<plusfour>1288</plusfour>
<postalcode>80202</postalcode>
<state>CO</state>
<status>
<code>PROVISIONED</code>
<description>Location is currently provisioned for URI</description>
</status>
<type>ADDRESS</type>
<updatetime>2014-10-08T17:23:49Z</updatetime>
</Locations>
</ns0:getLocationsByURIResponse>
{
"links": [
{ "href": "/endpoints", "rel": "self", "method": "GET" },
{ "href": "/endpoints", "rel": "first", "method": "GET" },
{ "href": "/endpoints?offset=99000&limit=1000", "rel": "last", "method": "GET" },
{ "href": "/endpoints?offset=1000&limit=1000", "rel": "next", "method": "GET" }
],
"endpoints": [
{
"id": "13035554321",
"accountId": "5001232",
"phoneNumber": "+13035554321",
"name": "Joe's Home",
"lang": "fr",
"created": "2016-06-22T16:33:21.959Z",
"updated": "2016-06-22T16:33:21.959Z",
"country": "US",
"addressId": "7888993",
"provisioningStatus": "PROVISIONED"
},
{
"id": "JDF9223kslemm23432",
"accountId": "5001232",
"phoneNumber": "+13035554322",
"name": "Joe's Office",
"lang": "en",
"created": "2015-03-11T04:09:25.399Z",
"updated": "2016-06-22T16:33:27.980Z",
"country": "US",
"addressId": "cafoffice",
"provisioningStatus": "PROVISIONED"
}
]
}
To get the full address details, use the addressId from the endpoint response:
GET /accounts/{accountId}/emergency/addresses/7888993?region=NA
{
"id": "homeoffice",
"validationStatus": "INVALID",
"address": "14024 NE 181st St, Apt. 8",
"addressLine1": "14024 NE 181st St",
"addressLine2": "Apt. 8",
"houseNumber": "14024",
"predirectional": "NE",
"postdirectional": "",
"streetName": "181st",
"streetSuffix": "ST",
"city": "Woodinville",
"state": "WA",
"postalCode": "98072",
"country": "US",
"description": "Home office, upstairs",
"latitude": "47.732682",
"longitude": "-122.155174",
"created": "2015-03-11T04:09:25.399Z",
"updated": "2016-03-11T04:09:25.399Z"
}
Update an endpoint's address
What changed:
- In DASH, address and URI are bound within a location. To change the address, you create a new location and provision it.
- In the ES Provisioning API, addresses are decoupled and can be changed with a
PATCHrequest. - Endpoint update is asynchronous, it returns an
orderIdfor order tracking.
- DASH
- ES Provisioning API
In DASH, you would call POST /addlocation with the new address, then POST /provisionlocation to activate it. See Create an endpoint above.
Request
PATCH /accounts/{accountId}/emergency/endpoints/{endpointId}?region=NA
Authorization: Bearer <token>
Content-Type: application/json
{
"action": "PROVISION",
"addressId": "7888993"
}
Response
{
"orderId": "08e0be9a-52fd-45a0-be2e-86835c534aad",
"updatedBy": "joe@crabshack.com",
"orderStatus": "COMPLETED",
"acceptedCount": 1,
"invalidCount": 0,
"updated": "2022-05-18T08:57:04Z",
"totalNumber": 1,
"orderType": "UPDATE_ENDPOINTS"
}
Delete an address (formerly: Remove a location)
What changed:
POST→DELETE- You can only delete an address if no endpoints are currently linked to it. Unlink first if needed
Request
- DASH
- ES Provisioning API
POST /removelocation
<removeLocation>
<locationid>77</locationid>
</removeLocation>
DELETE /accounts/{accountId}/emergency/addresses/{addressId}?region=NA
Response
- DASH
- ES Provisioning API
<ns0:removeLocationResponse xmlns:ns0="http://dashcs.com/api/v1/emergency">
<LocationStatus>
<code>REMOVED</code>
<description>Location removed from the system</description>
</LocationStatus>
</ns0:removeLocationResponse>
204 No Content
Delete an endpoint (formerly: Remove a URI)
What changed:
- Unlike DASH's
removeUri, deleting an endpoint does not cascade-delete its associated address - Endpoint deletion is asynchronous, it returns an
orderIdfor order tracking - Bulk deletion supported by passing an array of
endpointIds
Request
- DASH
- ES Provisioning API
POST /removeuri
<removeUri>
<uri>13035551236</uri>
</removeUri>
DELETE /accounts/{accountId}/emergency/endpoints/{endpointId}?region=NA
Response
- DASH
- ES Provisioning API
<ns0:removeURIResponse xmlns:ns0="http://dashcs.com/api/v1/emergency">
<URIStatus>
<code>REMOVED</code>
<description>URI removed from system</description>
</URIStatus>
</ns0:removeURIResponse>
{
"orderId": "08e0be9a-52fd-45a0-be2e-86835c534aad",
"updatedBy": "joe@crabshack.com",
"orderStatus": "COMPLETED",
"acceptedCount": 1,
"invalidCount": 0,
"updated": "2022-05-18T08:57:04Z",
"totalNumber": 1,
"orderType": "DELETE_ENDPOINTS"
}
Order tracking
On the ES Provisioning API, every endpoint change (add, update, delete) is asynchronous and returns an order.
How it works
- You submit a request:
POST /accounts/{accountId}/emergency/endpoints?region=NA - The response is
202 Acceptedwith anorderIdand initialorderStatus - You poll regularly until the order reaches a terminal status:
GET /accounts/{accountId}/emergency/orders/{orderId}/details?region=NA
Order statuses
| Status | Meaning |
|---|---|
RECEIVED | Order accepted, not yet processing |
PROCESSING | Order is being processed |
COMPLETED | All endpoints in the order succeeded |
PARTIAL | Some endpoints succeeded, some failed. Check individual endpoint statuses |
FAILED | The entire order failed |
For more details, see the Emergency Services order documentation.
Error handling
The new API uses structured JSON error responses with HTTP status codes.
Error mapping
| DASH API | ES Provisioning API | Meaning |
|---|---|---|
ParseException | 400 Bad Request | Invalid phone number format or parameter |
NotFoundException | 404 Not Found | No data found matching your criteria |
LockedException | 202 Accepted Order status: PARTIAL or FAILED | Endpoint creation is accepted but the order failed for this endpoint |
ProvisionException | 202 Accepted Order status: PARTIAL or FAILED | Endpoint creation is accepted but the order failed for this endpoint |
Deprecated endpoints
The following DASH API endpoints have no equivalent on the ES Provisioning API:
| DASH API endpoint | Notes |
|---|---|
GET /authenticationcheck | No equivalent. Use any read endpoint to verify credentials. |
POST /validatelocation | No standalone validation. Validation happens during address creation (POST /addresses). |
GET /provisionedlocationhistorybyuri/{uri} | No direct equivalent. Use order history (GET /orders/{orderId}/history) for change tracking. |
Additional Resources
We hope this guide helps you transition smoothly to the ES Provisioning API. For further details, please refer to the resources below.
- ES Provisioning API Reference
- How to provision Emergency Services on the Universal Platform
- Support: If you have questions or require assistance during your upgrade, please contact Bandwidth support for help.