A candidate finishes your take-home on a Friday afternoon. By the time a recruiter has cross-referenced three interviewers' calendars and emailed back a slot, it's Wednesday — and the candidate already has another offer in hand. Interview scheduling loses good people not because anyone is careless, but because the coordination loop is human-speed.
Here's a pipeline that takes the human out of that loop entirely: candidates pick their own slot from a booking page, the load spreads across your panel automatically, every call gets a conferencing link and a recording bot, and a structured transcript lands in your ATS after each interview. It's built on the Nylas Scheduler, Calendar, and Notetaker APIs, and it pairs naturally with Agent Accounts (currently in beta) if you want the recruiting side to run from its own dedicated mailbox instead of a recruiter's inbox.
Candidate visits a scheduling page → Scheduler assigns an interviewer via round-robin → an event lands on that interviewer's calendar with a meeting link → a booking.created
webhook creates the record in your ATS → Notetaker joins the call → a notetaker.media
webhook delivers transcript, summary, and action items → you attach them to the candidate's record.
The interesting part is that none of these steps need a person. The full recipe lives in the interview scheduling pipeline tutorial.
You define the panel once, in a scheduling Configuration:
curl --request POST \
--url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{
"requires_session_auth": false,
"participants": [
{ "name": "Sarah Kim", "email": "sarah.kim@yourcompany.com", "is_organizer": true,
"availability": { "calendar_ids": ["primary"] }, "booking": { "calendar_id": "primary" } },
{ "name": "Marcus Johnson", "email": "marcus.johnson@yourcompany.com",
"availability": { "calendar_ids": ["primary"] }, "booking": { "calendar_id": "primary" } }
],
"availability": {
"duration_minutes": 45,
"availability_rules": { "availability_method": "max-fairness" }
},
"event_booking": { "title": "Interview with {{invitee_name}}" }
}'
Two distribution strategies exist, and the choice matters more than it looks:
max-fairness
max-availability
One practical limit from the docs: keep a Configuration under 10 interviewers. Bigger panels should split by interview stage or role.
Attach Notetaker to the Configuration and every booked call gets recorded, transcribed, and summarized. The detail that makes this useful for hiring specifically is custom_instructions
— you tell the summarizer to focus on technical skills demonstrated, communication quality, and follow-up topics, so output maps to your scorecard instead of being a generic recap.
Two hard constraints to design around:
notetaker.media
webhook fires. Download immediately.Also: the bot joins as a non-signed-in participant. If nobody admits it from the lobby within 10 minutes, it gives up with failed_entry
and the recording is gone. For automated pipelines, configure Meet/Teams/Zoom to let anonymous participants in — "Anyone with the link can join" for Meet, "Anonymous users can join" for Teams, waiting room off for Zoom.
The Configuration alone doesn't give candidates anything to click. The fastest option is a Nylas-hosted page — add a slug
and you're done:
curl --request PUT \
--url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/scheduling/configurations/<CONFIGURATION_ID>' \
--header 'Authorization: Bearer <NYLAS_API_KEY>' \
--header 'Content-Type: application/json' \
--data '{ "slug": "interview-engineering-team" }'
The booking page is now live at book.nylas.com/interview-engineering-team
. Drop that URL into recruiter emails or your ATS's candidate templates and you have a working self-booking flow with zero frontend work.
If you'd rather keep candidates on your own careers site, embed the scheduling UI instead:
<script src="https://cdn.jsdelivr.net/npm/@nylas/react@latest/dist/cdn/nylas-scheduling/nylas-scheduling.es.js"></script>
<nylas-scheduling configuration-id="<CONFIGURATION_ID>"></nylas-scheduling>
The web component handles date selection, time slots, the booking form, and confirmation. Round-robin assignment and Notetaker consent apply automatically — the embedded version isn't a second-class citizen. (For production, pin the package to a specific version instead of @latest
and add a Subresource Integrity hash so a CDN change can't alter what your careers page loads.)
Subscribe to three triggers: booking.created
, booking.cancelled
, and notetaker.media
. That covers the full interview lifecycle — scheduled, cancelled, and debriefed.
When a candidate books, the booking.created
payload hands you everything your ATS needs in one shot:
{
"type": "booking.created",
"data": {
"grant_id": "<NYLAS_GRANT_ID>",
"object": {
"booking_id": "<BOOKING_ID>",
"booking_info": {
"event_id": "<EVENT_ID>",
"start_time": 1719842400,
"end_time": 1719844500,
"title": "Interview with Dana Chen",
"location": "https://meet.google.com/abc-defg-hij"
}
}
}
}
Your handler creates the interview record, stores the booking_id
and event_id
for later correlation, and gets out. One operational rule worth following: respond with a 200 immediately and process asynchronously. Nylas retries failed deliveries, but an endpoint that's consistently slow or unreachable eventually gets its notifications dropped — and a silently missed booking is the worst possible failure mode in a hiring pipeline.
When the notetaker.media
webhook arrives with state: "available"
, download the transcript, summary, and action items right away (remember the 60-minute URL expiry), then look up the linked calendar event through the Notetaker API to attach everything to the right candidate record.
One local-dev note: Nylas blocks requests to ngrok URLs, so use VS Code port forwarding or Hookdeck to expose your webhook server while you build.
Everything above runs on your interviewers' connected calendars. But the communication side — emailing candidates the booking link, confirming, nudging no-shows — doesn't have to come from a recruiter's personal address. An Agent Account is a real mailbox with its own grant ID that works with the same Messages and Events endpoints, so a recruiting@yourcompany.com
identity can own candidate correspondence end to end. The recruiting overview lists the agent-driven variants, including a scheduling agent with its own calendar.
booking.cancelled
and removes the event; the candidate rebooks from scratch. Link ATS records by candidate email so the rebook ties back to the same person.Don't migrate the whole hiring funnel at once. Pick one role, build the Configuration for that panel, wire the two webhooks, and compare time-to-scheduled against your current process for a couple of weeks. The full tutorial has the complete webhook handlers in Node and Python. What's the slowest step in your hiring loop right now — scheduling, or the debrief?