Skip to main content

DialStack Webhook Protocol (1.0.0)

Download OpenAPI specification:Download

Reference documentation for the scheduling requests DialStack sends to your system so an AI agent can look up callers, search availability and book appointments during a call.

Overview

When an AI agent with scheduling enabled needs customer or calendar data, DialStack sends a request to the base URL configured on that agent. Your system processes the request and returns a response that DialStack hands to the agent as is.

These are synchronous request/response calls, separate from the event webhooks you configure through the Webhook Endpoints API.

Configuration

Scheduling is configured per AI agent. Set scheduling.webhook_url when you create or update the agent (POST /v1/ai-agents or POST /v1/ai-agents/{ai_agent_id}). Scheduling is on for an agent while scheduling.webhook_url is set.

DialStack appends the operation path to that base URL:

  • {webhook_url}/customers/lookup
  • {webhook_url}/availability/search
  • {webhook_url}/bookings

Request Headers

All requests include these headers:

Header Description
Content-Type Always application/json
X-DialStack-Signature HMAC-SHA256 signature for verification
X-DialStack-Account-Id The account whose caller the agent is talking to

Signature Verification

Requests are signed with the secret of the agent's voice app. Read it with GET /v1/voice-apps/{voice_app_id}, using the agent's voice_app. If you rotate the voice app's secret, the agent signs with the new one from the next call.

The X-DialStack-Signature header contains a timestamp and signature:

X-DialStack-Signature: t=1697634600,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

To verify the signature:

  1. Extract the timestamp (t) and signature (v1) from the header
  2. Concatenate: {timestamp}.{request_body}
  3. Compute: HMAC-SHA256(secret, concatenated_string)
  4. Compare the computed signature with v1 (use timing-safe comparison)
  5. Reject requests where the timestamp is older than 5 minutes

Responses and Timeouts

  • Return 2xx with a JSON object. The agent reads the object you return as is, so the response schemas below are the shapes it understands best, and any extra fields are available to it in the conversation.
  • DialStack waits up to 10 seconds for your response.
  • A timeout, an unreachable URL, or a non-2xx status is reported to the agent as a failed request, with the status code but not your response body.

Platform-level scheduling

Some platforms have a single scheduling URL and secret that DialStack set up on their platform, rather than a URL on each AI agent. Requests for that setup differ from the per-agent requests described above:

  • They are sent to the platform's scheduling URL and signed with the platform's scheduling secret.
  • Only /availability/search and /bookings are sent; there is no customer lookup.
  • DialStack waits up to 30 seconds for a response, and returns your status code and response body to the requester unchanged.
  • Bodies carry account as well as account_id (both the same value).
  • The availability range and the booking fields, including customer.email, are passed through as the requester supplied them, and idempotency_key is the requester's Idempotency-Key.

Webhooks

Operations your system implements to receive scheduling requests from DialStack.

DialStack calls them when an AI agent needs to look up a customer, search for availability, or create a booking. Your system processes the request and returns a response.

Lookup Customer

The agent sends this request, normally at the start of a call, to determine if the caller is a new or existing customer. Not sent by platform-level scheduling.

Your platform should look up the caller by phone number and return their profile if found. Include upcoming appointment information if available — the voice AI uses this for context during the call.

Authorizations:
SignatureAuth
header Parameters
X-DialStack-Account-Id
required
string
Example: acct_01h2xcejqtf2nbrexx3vqjhp41

The DialStack account ID for this request

Request Body schema: application/json
required
account_id
required
string

The account ID (same as X-DialStack-Account-Id header)

required
object

Responses

Response Schema: application/json
found
required
boolean

Whether a matching customer record was found

object

Customer details (present only when found is true)

Request samples

Content type
application/json
{
  • "account_id": "acct_01h2xcejqtf2nbrexx3vqjhp41",
  • "customer": {
    }
}

Response samples

Content type
application/json
Example
{
  • "found": true,
  • "customer": {
    }
}

Search Availability

The agent sends this request when it needs to find available appointment slots on the dates the caller asked about.

Your platform should query your booking system and return matching availability.

Authorizations:
SignatureAuth
header Parameters
X-DialStack-Account-Id
required
string
Example: acct_01h2xcejqtf2nbrexx3vqjhp41

The DialStack account ID for this request

Request Body schema: application/json
required
account_id
required
string

The account ID (same as X-DialStack-Account-Id header)

account
string

The account ID. Sent only by platform-level scheduling, with the same value as account_id.

required
object (AvailabilityQuery)

Responses

Response Schema: application/json
required
Array of objects (Availability)

List of available appointment slots

Array
start_at
required
string <date-time>

Slot start time (ISO 8601)

duration_minutes
required
integer >= 1

Slot duration in minutes

Request samples

Content type
application/json
{
  • "account_id": "acct_01h2xcejqtf2nbrexx3vqjhp41",
  • "query": {
    }
}

Response samples

Content type
application/json
Example
{
  • "availabilities": [
    ]
}

Create Booking

The agent sends this request when it needs to book an appointment.

Your platform should:

  1. Check the idempotency_key - if you've seen it before, return the original response
  2. Verify the slot is still available
  3. Create the booking in your system
  4. Return the booking confirmation

Idempotency: The idempotency_key prevents duplicate bookings. Store it when processing a booking, and if the same key arrives again, return the original booking response. Keys can be safely expired after 24 hours.

For a booking you can't make, such as a slot taken since the search, return a non-2xx status so the agent doesn't confirm it to the caller.

Authorizations:
SignatureAuth
header Parameters
X-DialStack-Account-Id
required
string
Example: acct_01h2xcejqtf2nbrexx3vqjhp41

The DialStack account ID for this request

Request Body schema: application/json
required
account_id
required
string

The account ID (same as X-DialStack-Account-Id header)

account
string

The account ID. Sent only by platform-level scheduling, with the same value as account_id.

idempotency_key
required
string

Key to prevent duplicate bookings. The agent sends the same key if it books the same slot for the same caller twice in one call. If you receive the same key again, return the original booking response. Keys can be safely expired after 24 hours. Treat it as an opaque string.

required
object (BookingRequest)

Responses

Response Schema: application/json
required
object (Booking)
id
required
string

Your platform's booking ID

status
required
string
Enum: "confirmed" "pending"

Booking status

start_at
required
string <date-time>

Confirmed appointment start time

end_at
required
string <date-time>

Confirmed appointment end time

object
object

Appointment location details

notes
string

Additional booking information such as assigned provider

created_at
string <date-time>

When the booking was created

Request samples

Content type
application/json
{
  • "account_id": "acct_01h2xcejqtf2nbrexx3vqjhp41",
  • "idempotency_key": "booking-req-123456",
  • "booking": {
    }
}

Response samples

Content type
application/json
{
  • "booking": {
    }
}