Device Provisioning
Manage physical phones through the API — add devices by MAC address, assign users, customize settings, and monitor provisioning status.
Device Types
Two categories of devices can be provisioned:
- Deskphones — standalone desk phones with programmable keys, assigned directly to users
- DECT systems — a base station with paired wireless handsets, where each handset is assigned to a user
Both types follow the same provisioning flow: add the device, assign users, and the phone retrieves its configuration from the provisioning server.
The typical deployment is 1:1 user-to-device, but you can assign multiple users to a single device (shared reception phone, multi-line executive desk setup, etc.) or the same user to multiple devices. DialStack bills for each user provisioned on the system, regardless of how users and devices are paired.
How Provisioning Works
- Add the device — create a device via the API with its MAC address and type. The vendor is automatically detected from the MAC.
- Assign users — assign users to the device so it can make and receive calls.
- Device fetches config — when the phone powers on (or is triggered via check-sync), it contacts the provisioning server and receives its configuration.
- Status updates — the device status transitions from
pending-synctoprovisionedafter its first successful configuration fetch.
Settings Inheritance
Device configuration follows a layered inheritance model:
Global defaults → Platform config → Account config → Device overrides
Each layer can override settings from the layer above. Omitted fields inherit from the parent, so you only need to specify what you want to change.
Prerequisites
- An API key with account access
- The MAC address of the physical device
- At least one user to assign to the device
Provisioning a Deskphone
Step 1: Create the deskphone
Register the device with its MAC address:
curl -X POST https://api.dialstack.ai/v1/devices \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"type": "deskphone",
"mac_address": "00:04:13:aa:bb:cc"
}'
{
"id": "YOUR_DEVICE_ID",
"type": "deskphone"
}
The vendor is detected automatically based on the MAC address prefix (OUI). The model is detected when the device first contacts the provisioning server. Use GET /v1/devices/YOUR_DEVICE_ID to retrieve the full device details.
Step 2: Assign a user
curl -X POST https://api.dialstack.ai/v1/devices/YOUR_DEVICE_ID/users \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"user_id": "YOUR_USER_ID"
}'
{
"user_id": "YOUR_USER_ID",
"device_id": "YOUR_DEVICE_ID",
"created_at": "2025-10-18T10:01:00Z"
}
Each user assignment consumes one line appearance on the phone — an individually-registered SIP account, shown as a distinct "line" on the phone's display. DialStack caps deskphones at 24 line appearances, but the practical limit is what the phone model itself supports (ranges from 2 lines on entry-level handsets to 16+ on high-end executive phones). Assignments beyond the phone's hardware capacity will be accepted by the API but not all will appear on the device. Consult the phone vendor's datasheet for the supported line count.
Step 3: Trigger configuration reload
If the phone is already powered on, send a check-sync to have it reload its configuration:
curl -X POST https://api.dialstack.ai/v1/devices/YOUR_DEVICE_ID/status/check-sync \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID"
{
"success": true,
"lines_notified": 1,
"lines": [
{
"line_number": 1,
"status": "delivered"
}
]
}
A 200 response means at least one line accepted the request. Each entry
in lines carries a 1-indexed line_number and a status — one of
delivered, not_registered, unreachable, or error.
Trigger check-sync when you actually change configuration, not on every
admin-UI interaction. A 200 OK only means the phone accepted the
request — what happens next depends on the phone, the firmware, and
sometimes the call state at that exact moment.
With reboot: false (the default), the typical behavior is:
- The phone reloads configuration in place and stays registered, with a brief (usually under 5 seconds) re-registration if the SIP server or credentials changed.
- Some phones defer applying new configuration while a call is in progress, so the change may not take effect until the call ends.
- Some settings (firmware, certain network parameters) still require a reboot, which the phone performs on its next idle window.
- For DECT, the request reaches the base no matter which ID you target (base or handset), and every handset paired with the base reloads.
reboot: false is not a guarantee that the phone keeps its calls.
Some models — particularly certain DECT bases — reboot on every
check-sync regardless of the flag, drop active calls, and take
30–90 seconds to come back. Treat any check-sync as potentially
disruptive, and only send it when configuration actually changed.
With reboot: true:
- The phone reboots immediately, dropping any active call.
- Roughly 30–90 seconds offline.
- Only use for recovery or for changes that explicitly require a reboot.
If the device could not be reached, the API returns 409 Conflict with a
reason field:
not_registered— the device has no active registration. It may be powered off, unable to reach the SIP server, or has never registered.unreachable— the device didn't respond in time. It is likely offline or has lost its connection.
Step 4: Verify provisioning
curl https://api.dialstack.ai/v1/devices/YOUR_DEVICE_ID \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID"
After the device fetches its configuration, status changes to provisioned and last_provisioned_at is populated.
Provisioning a DECT System
DECT systems have a two-level hierarchy: base station → handsets. Each handset is then assigned to one or more users.
Step 1: Create the DECT base
curl -X POST https://api.dialstack.ai/v1/devices \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"type": "dect_base",
"mac_address": "00:04:13:bb:cc:dd"
}'
{
"id": "YOUR_BASE_ID",
"type": "dect_base"
}
Step 2: Add a handset
Each handset is identified by its IPEI (a unique hardware identifier for wireless handsets, formatted as a hexadecimal string). Handsets are created as devices linked to their parent base.
curl -X POST https://api.dialstack.ai/v1/devices \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"type": "dect_handset",
"base_id": "YOUR_BASE_ID",
"ipei": "0328A0000F",
"display_name": "Front Desk"
}'
{
"id": "YOUR_HANDSET_ID",
"type": "dect_handset"
}
Step 3: Assign a user to the handset
Users are assigned to individual handsets, not to the base station directly.
curl -X POST https://api.dialstack.ai/v1/devices/YOUR_HANDSET_ID/users \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"user_id": "YOUR_USER_ID"
}'
{
"user_id": "YOUR_USER_ID",
"device_id": "YOUR_HANDSET_ID",
"created_at": "2025-10-18T10:03:00Z"
}
Customizing Device Settings
Use the overrides field to customize device behavior. Settings use a two-tier structure:
abstractions— vendor-agnostic settings that are translated to vendor-specific parameters automaticallyvendor_overrides— raw vendor-specific key-value pairs for parameters not covered by abstractions
curl -X POST https://api.dialstack.ai/v1/deskphones/YOUR_DEVICE_ID \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"overrides": {
"abstractions": {
"audio": {
"codecs": ["PCMU", "PCMA"],
"echo_cancellation": true
},
"display": {
"time_format": "24h",
"backlight_level": "medium"
}
}
}
}'
The abstractions schema is actively expanding as new hardware capabilities are added. Use vendor_overrides for vendor-specific parameters not yet available as abstractions.
Multicell DECT Deployments
For larger spaces requiring multiple base stations, use multicell roles to coordinate them:
data_master— the primary base that distributes configuration to other basessecondary— subordinate bases that receive configuration from the data master
curl -X POST https://api.dialstack.ai/v1/devices \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID" \
-H "Content-Type: application/json" \
-d '{
"type": "dect_base",
"mac_address": "00:04:13:bb:cc:ee",
"multicell_role": "secondary"
}'
Managing Devices
Unified Device View
List all devices (deskphones and DECT bases) in a single request:
curl "https://api.dialstack.ai/v1/devices?type=deskphone" \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID"
The type parameter is optional — omit it to list all device types.
Listing Users on a Device
curl https://api.dialstack.ai/v1/devices/YOUR_DEVICE_ID/users \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID"
Removing a User from a Device
curl -X DELETE https://api.dialstack.ai/v1/devices/YOUR_DEVICE_ID/users/YOUR_USER_ID \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID"
Deleting a Device
curl -X DELETE https://api.dialstack.ai/v1/devices/YOUR_DEVICE_ID \
-H "Authorization: Bearer sk_live_YOUR_SECRET_KEY" \
-H "DialStack-Account: YOUR_ACCOUNT_ID"
Deleting a device removes all associated user assignments. Deleting a DECT base also removes all its handsets.