Skip to main content
The Default public API lets your own server route a lead and book a meeting, whether the caller is a backend service, a chatbot, or an AI agent. You run a workflow that decides who a lead should meet, then book a meeting on the calendar it picks. The flow takes 4 requests. Every endpoint used here is documented in full in the API reference.
Building an AI agent? The @defaulthq/ai-tools package wraps this whole flow as ready made Vercel AI SDK tools.

Authentication

Create an API key in Settings → API Keys with the triggers:write and scheduling:write permissions. A write key also covers reads for its surface, so these 2 are enough for the whole flow. Send it on every request as Authorization: Bearer <key>.
This is a server to server API. It sends no CORS headers, so it cannot be called from a browser. Your API key should be kept private.

Before you start

You need a published workflow with an API trigger. In the workflow editor, add the API trigger, connect a form to it, and publish. The form’s fields define what your requests send. The workflow needs a Display Scheduler node on the path you expect to book from. The API trigger’s Connected Form must be an active form in Forms. If Forms has no forms yet, create one there with Create new, then New form, and give its fields the names your requests will send. A form created this way needs no Pixel on your site. See Create a form in Default.

The flow

1

Find your trigger

List the API triggers in your workspace to get the trigger id and the fields its form expects.
Each field’s name is the key you send in the next step. Fields marked required must have a value before the workflow will run. For select fields, send one of the option values. You can skip the email field, the next step fills it for you.Full reference: GET /v1/triggers
2

Fire the trigger

Send the lead’s email and their responses. The email input is the lead’s identity, and it automatically fills the form’s email field, so you never send it twice.If you know web context about the lead, send it in the optional context object: utmParams, gclid, pageUrl, referrer, userAgent, and ipAddress, all optional. The workflow can reference it as form submission data, and it records as attribution on the booked meeting.
The workflow runs your routing rules and responds with an execution id and an outcome.
Keep both values. outcome.type tells you what the workflow decided:If you would rather show the calendar in a browser than book through the API, schedulerUrl is a ready to use booking page and you can stop here.Full reference: POST /v1/triggers/{trigger}
3

Get available times

Ask for open slots, passing outcome.schedulingLinkId as the event. The link carries the routing decision, so the times you get back belong to the rep the workflow chose. Booking without a workflow works the same way, pass an event id or slug from your workspace instead and the times come from the event’s own hosts.
The range can span up to 63 days (9 weeks) from whatever start you choose, so 1 request covers about 2 months of availability. Keep the reservationId and pass it back if you query more date ranges, so the same host selection holds while the lead decides. Book before expiresAt or request slots again.Full reference: POST /v1/scheduling/events/{event}/slots
4

Book the meeting

Book a returned slot. Pass the same link id as event, the same email as personEmail, and the executionId from Step 2 as workflowExecutionId.
The workflowExecutionId is what ties the meeting back to the routing decision. It resumes the workflow, so CRM writeback, notifications, and routing fairness all record against this booking. Without it the meeting still books, but the workflow never learns about it.Full reference: POST /v1/scheduling/meetings

Handling errors

Every error comes back as { "error": { "code", "message" } }. Each endpoint’s reference page lists the exact codes it can return per status, with example payloads. When a book response is lost. A book request can time out before or after Default creates the meeting. Retry it right away, once, with the same reservationId and workflowExecutionId. A reservation can be used only once, so this retry can’t create a second meeting.
  • The retry succeeds: the first request did not book, and the retry did. Use the meeting it returns.
  • The retry returns RESERVATION_USED, CONFLICT, or RESERVATION_EXPIRED: these codes don’t tell you whether a meeting exists. The first request may have booked. It may also have failed after it used the reservation, the hold may have lapsed before it got there, or the workflow run may have stopped waiting when the Display Scheduler node’s Timeout passed.
To know which way a run went, plan for it before you go live. The API reads a meeting only by its meeting ID, so add a Send to Webhook node on the Display Scheduler node’s Booked branch that sends the booked meeting’s ID from Meeting details to your server, and another on its Not booked branch. A run waiting on the scheduler follows Booked when the lead books and Not booked when the lead closes or leaves the scheduler or the Timeout passes. Not booked doesn’t prove that no meeting exists. A book request that was already under way when the run followed Not booked, for example when the Timeout passed, can still create the meeting a moment later, and that run never follows Booked. To hear about these meetings, add a second workflow with a Meeting Status trigger that has Booked selected under Meeting statuses and Workflow under Sources. Follow it with a Send to Webhook node that sends the meeting’s ID and the lead’s email to your server. This workflow runs for every meeting a workflow books, whichever branch the first run followed. You can also filter Meetings in Default by Guest email. A check right after Not booked can come back empty while a book request is still finishing, so wait a few minutes after your last book request before you check. Only when neither that webhook nor Meetings shows a meeting for the lead, start over: fire the trigger again and book a fresh slot from step 2. If a meeting exists, read it with GET /v1/scheduling/meetings/{meetingId} and use it. Don’t book a new reservation for the same lead before you’ve checked, because the first request may already have booked. Every fire starts a new workflow run, so nodes before the scheduler run again. If your workflow writes to a CRM or sends notifications, expect a repeat fire to do that work again, and a step that assigns the routed rep, like writing an owner to your CRM, counts against routing fairness on each run. The booking itself is safe to retry, a meeting only counts once it actually books. When you already have a scheduler outcome, reuse it instead of firing again.
Last modified on October 1, 2026