Skip to main content

Dialpad

Dialpad is a cloud phone and meetings platform. This driver connects GEM to the Dialpad API so that a conference room can turn itself on before a meeting, follow the room's live call state, and shut down when the room is done — with nobody pressing a button.

It does two things:

  • Meeting schedule → pre-warm. The driver fetches the upcoming Dialpad meetings for the users you choose and turns them into zone state on a local clock: prewarm a configurable lead time before a meeting, meeting during it, ending_soon near the end, idle after.
  • Live call events → call state. The driver opens an outbound websocket to Dialpad's event service (no inbound webhook, no port forwarding) and follows calls on the room's Dialpad user or room phone: ringing, in_call, call_state, the other party, and the call id. It can also hang up a call and, when enabled, place one.

One GEM device represents one Dialpad company. Each zone is one conference room.

Prerequisites​

  • A Dialpad company API key, created by a Dialpad company admin on the API keys page of the Dialpad Admin portal. The websocket and call-event subscription endpoints need a company key; a user-level key can read meetings but cannot stream call events.
  • For pre-warm: the Dialpad user or users whose meetings book the room (see How meetings map to a room).
  • Outbound HTTPS/WSS (port 443) from the controller to dialpad.com and Dialpad's websocket host.

Setup​

  1. Create the API key in Dialpad Admin. Copy it; it is shown once.

  2. Add the device. In Admin → System → Devices, create a device with the driver Dialpad and paste the key into Dialpad API Key. It is stored encrypted.

  3. Find ids. From the device's command panel, run get_users (optionally with an email) and get_rooms. Each result includes a ready-made zone address.

  4. Create one zone per conference room, with the Dialpad device as its device and one of these addresses:

    AddressMeaningMeetingsCalls
    user:<id> or user:<email>a Dialpad user (for example a dedicated room account)yes — that user's meetingsyes
    room:<id>a Dialpad room phonevia meeting_usersyes
    office:<id>, department:<id>, …other Dialpad call targetsvia meeting_usersyes

    A bare id or email is read as a user.

  5. (Room phones and shared rooms) Set the zone attribute meeting_users to the comma-separated emails or ids whose meetings book the room.

  6. Save, then run get_status. You should see events.connected: true, a subscription for each zone target, and a meeting count per watched user.

How meetings map to a room​

Dialpad meetings have no room or location field. The driver only knows that a meeting belongs to a user. A room is considered booked when one of its watched users has a meeting:

  • For a user: zone, the watched user is the zone's own user, unless meeting_users is set.
  • For any other zone, set meeting_users.

Two setups work well:

  • A dedicated room account in Dialpad (for example boardroom@example.com). People invite it to the meetings held in the room. Use user:boardroom@example.com as the zone address.
  • A short list of organizers who always meet in the room, listed in meeting_users.

If anyone can book the room from their own account, a calendar room resource (Google Workspace / Microsoft 365) is the better schedule source. Keep this driver for live call state.

Zone state​

Zones are written only when a value changes. Build triggers and macros on these:

AttributeTypeMeaning
statestringidle, prewarm, meeting or in_call. A live call wins over the schedule. Written last, so a trigger on state sees the other attributes already updated.
meeting_statestringThe schedule alone: idle, prewarm or meeting.
prewarmboolTrue from the pre-warm lead before a meeting until it ends. Stays true across back-to-back meetings, so it rises once per block of bookings.
meeting_activeboolA meeting's scheduled window contains now.
ending_soonboolThe current meeting ends within ending_soon_minutes, and no meeting follows it within the pre-warm lead.
current_meeting / next_meetingjson{id, title, start, end, organizer, meeting_url, dial_in_number, participant_pin}, or {}.
next_meeting_title, next_meeting_startstringConvenience copies for tiles and labels (start is ISO-8601 UTC).
meeting_url, dial_in_numberstringJoin details of the current meeting, or the next one if nothing is on now.
in_callboolA call on the zone's target is connected, merged or on hold.
ringingboolAn inbound call is ringing.
call_statestringMost significant active call state (connected, merged, hold, calling, ringing, parked) or idle.
call_id, call_direction, call_partystringThe call behind call_state; call_party is the contact's name or number.

Device attributes maintained by the driver: events_connected (bool), last_event_at (ISO time of the last event frame) and dialpad_websocket_id (the Dialpad endpoint this device owns — leave it alone).

Example automations​

  • Pre-warm: trigger on zone prewarm becoming true → displays on, DSP preset, cameras to home, lights to the conference scene, HVAC occupied.
  • Shutdown: trigger on zone state becoming idle → wait 10 minutes → if the room's occupancy sensor is clear, run the room-off macro.
  • Incoming call: ringing → pulse the room lights or chime the panel.
  • On a call: in_call → video-conference lighting scene, "In Session" sign on.
  • Wrap-up: ending_soon → show a "5 minutes left" banner on the touch panel.

Device attributes​

AttributeDefaultDescription
api_key—Company API key. Secure.
prewarm_minutes15Pre-warm lead in minutes. A zone attribute with the same name overrides it per room.
ending_soon_minutes5How long before a meeting's end ending_soon turns on.
meeting_poll_interval120000Milliseconds between meeting fetches (minimum 30000). State changes run on a 15-second local clock, so this only bounds how fast a new or moved booking is seen.
lookahead_hours24How far ahead meetings are fetched.
enable_eventstrueStream call events. Off disables all call attributes.
max_call_hours8A call with no event for this long is dropped: the backstop for a lost hangup.
allow_outbound_callsfalseEnables the dial command, which places real calls billed to the company.
api_basehttps://dialpad.comUse https://sandbox.dialpad.com for a sandbox company.

Commands​

CommandArgumentsDescription
refresh—Re-resolve emails, re-poll meetings and re-sync subscriptions now.
get_status—Diagnostics: API health, event stream (age, last event, rotations, reconnects, rejected frames), subscriptions, meeting poll per user, per-zone state.
get_meetingsaddress, hoursFetch meetings live (not from the cache) for a zone's watched users, or for every watched user.
get_usersemailFind users and their zone addresses.
get_rooms—List Dialpad room phones and their zone addresses.
get_meeting_rooms—List Dialpad Meetings rooms (dial-in numbers and join paths).
get_subscriptions—List the call-event subscriptions on this device's websocket.
get_callcall_idRead one call. Dialpad limits this to 10 per minute.
hangupaddress or call_idHang up every active call on a zone, or one call. A non-admin caller may only hang up a call GEM is tracking on a zone they can control.
dialaddress, phone_numberRings the zone user's Dialpad apps and connects them to an E.164 number. The zone must be a user: zone, and the device needs allow_outbound_calls.
clear_call_stateaddressForget the calls tracked for a zone.
reconnect_events—Close and reopen the event stream.
remove_event_endpoint—Decommission: delete this device's subscriptions and websocket endpoint in Dialpad. Use it before deleting the device.

How the event stream works​

  • On connect the driver creates one websocket endpoint in Dialpad, protected by a random signing secret, and stores its id on the device. Later restarts reuse the same endpoint. If someone deletes it in Dialpad, the driver creates a new one.
  • The driver keeps exactly one call-event subscription per zone target on that endpoint. It adds any that are missing, removes stale or incomplete ones, and never touches subscriptions that belong to other integrations. It re-checks every 15 minutes and on refresh.
  • Dialpad's connection URL is valid for one hour. Every 55 minutes the driver opens a fresh connection and closes the old one only after the new one is up, so no events are missed. Events that arrive on both connections are counted once.
  • Every event is a JWT signed with the endpoint secret. The driver checks the signature, discards anything that fails, and counts it under rejected in get_status.
  • A dropped connection reconnects with backoff (1 s up to 60 s). If the gap was longer than a few seconds, the driver asks Dialpad whether the calls it still holds open have ended.

Limits and quirks​

  • Meeting times without a zone designator are read as UTC.
  • Meetings are taken as the API returns them, one row per occurrence. Check recurring series against the live account before depending on them.
  • Dialpad allows about 20 API requests per second per company. The driver spaces its own requests under that and honours Retry-After on a 429.
  • dial uses Dialpad's ring-all-devices call API (5 per minute per user). It rings the user's Dialpad devices and connects the call once one of them answers.

Troubleshooting​

SymptomCheck
connected stays false; log shows dialpad 401The key was revoked or mistyped. Create a new company key and paste it again.
Meetings work, but in_call never changesRun get_status: events.connected should be true and subscriptions should list the zone's target. A user-level key cannot create websockets. Use a company key.
Log shows zone address not understoodUse user:<id or email> or room:<id>; get_users and get_rooms print valid addresses.
prewarm never turns onRun get_meetings with the zone's address. If the list is empty, the meetings are under another user; add that user to meeting_users.
events.rejected keeps risingFrames are failing signature checks. Run reconnect_events; if it persists, remove_event_endpoint followed by refresh creates a new endpoint and secret.