Integration and API Spec
The reference during the build: every tool connection, auth scope, field mapping, and error-handling rule.
Integration and API Spec
Interview Scheduling Automation
[YourCompany.com] · HR Department · Prepared by FullSpec · [Today's Date]
This document is the authoritative technical reference for every integration point in the Interview Scheduling automation. It covers authentication methods, exact OAuth scopes, webhook configuration, field mappings between agents, credential store layout, and defined failure behaviours. The FullSpec team uses this spec to build, configure, and verify every connection. Nothing in this document should be changed without updating the corresponding test cases in the companion Test and QA Plan.
01Tool inventory
02Per-tool integration detail
Greenhouse acts as both the automation trigger source (via inbound webhook) and the write-back destination for confirmed interview data. The Harvest API v2 is required for candidate record updates. The Job Boards API is not used in this automation.
// Inbound webhook payload (trigger)
POST /webhooks/greenhouse
Headers: Signature: sha256=<hex>, Content-Type: application/json
{
"action": "candidate_stage_change",
"payload": {
"application": {
"id": 123456789,
"candidate_id": 987654321,
"current_stage": { "id": 111, "name": "Technical Interview" },
"job_id": 222333
}
}
}
// Write-back call (Agent 3 output)
PATCH /v1/applications/{application_id}/interviews/{interview_id}
{
"scheduled_at": "2025-05-14T10:00:00Z",
"interviewers": [ { "user_id": 441 }, { "user_id": 442 } ],
"status": "scheduled"
}Notion stores the interview panel rules database: which interviewers are assigned per job stage, interview duration, format (video/in-person), and any panel constraints. The automation reads this database on every trigger; it does not write to Notion.
// Query panel rules for a given job stage
POST https://api.notion.com/v1/databases/{NOTION_PANEL_DB_ID}/query
Headers: Authorization: Bearer {NOTION_API_TOKEN}, Notion-Version: 2022-06-28
{
"filter": {
"property": "Job Stage",
"title": { "equals": "Technical Interview" }
}
}
// Expected response fields extracted
results[0].properties.Interviewers -> array of interviewer emails
results[0].properties["Duration Minutes"] -> integer (e.g. 60)
results[0].properties["Interview Format"] -> string (e.g. "Video")
results[0].properties["Panel Constraints"]-> string (e.g. "No back-to-back slots")Google Calendar is queried to retrieve interviewer free/busy windows, and is then written to in order to create the confirmed interview event with all participants attached. Both read and write operations occur within the same OAuth token scope.
// Free/busy query for slot computation
POST https://www.googleapis.com/calendar/v3/freeBusy
{
"timeMin": "2025-05-14T08:00:00Z",
"timeMax": "2025-05-16T18:00:00Z",
"timeZone": "America/New_York",
"items": [
{ "id": "interviewer1@yourcompany.com" },
{ "id": "interviewer2@yourcompany.com" }
]
}
// Calendar event creation (on Calendly booking confirmed)
POST https://www.googleapis.com/calendar/v3/calendars/{GOOGLE_RECRUITER_CALENDAR_ID}/events?conferenceDataVersion=1&sendUpdates=all
{
"summary": "Technical Interview: [Candidate Name]",
"start": { "dateTime": "2025-05-14T10:00:00Z" },
"end": { "dateTime": "2025-05-14T11:00:00Z" },
"attendees": [ { "email": "candidate@email.com" }, { "email": "interviewer1@yourcompany.com" } ],
"conferenceData": { "createRequest": { "requestId": "unique-uuid", "conferenceSolutionKey": { "type": "hangoutsMeet" } } }
}Gmail is used for two distinct outbound sends: the initial booking link email to the candidate, and the timed day-before reminder. Both are sent from the recruiter's address using delegated OAuth access. No inbound Gmail parsing is required in this build.
// Send booking link email
POST https://gmail.googleapis.com/gmail/v1/users/{GMAIL_SENDER_ADDRESS}/messages/send
Body: RFC 2822 message, base64url-encoded
To: candidate@email.com
Subject: Your interview for {{job_title}} - please book your slot
Body: Hi {{candidate_first_name}}, please use this link to book: {{calendly_link}}
// Scheduled reminder (queued at booking time, fires -20h before start)
To: candidate@email.com
Subject: Reminder: Your interview is tomorrow
Body: Hi {{candidate_first_name}}, your interview is on {{interview_date}} at {{interview_time}}.
Join here: {{meet_link}}Calendly manages the candidate-facing booking experience. The automation generates a one-time scheduling link scoped to pre-computed available windows and monitors for the booking confirmation webhook. Rescheduling through Calendly re-fires the confirmation webhook with updated event data.
// Generate single-use scheduling link
POST https://api.calendly.com/scheduling_links
{
"max_event_count": 1,
"owner": "https://api.calendly.com/event_types/{CALENDLY_EVENT_TYPE_UUID}",
"owner_type": "EventType"
}
Response -> booking_url passed to Gmail send step
// Inbound webhook on booking confirmed
POST /webhooks/calendly
Headers: Calendly-Webhook-Signature: <sha256_sig>
{
"event": "invitee.created",
"payload": {
"event": "https://api.calendly.com/scheduled_events/{event_uuid}",
"invitee": { "email": "candidate@email.com", "name": "Alex Smith" },
"start_time": "2025-05-14T10:00:00Z",
"end_time": "2025-05-14T11:00:00Z"
}
}Slack is used exclusively for outbound interviewer briefing messages sent immediately after a Calendly booking is confirmed. One message is sent per interviewer. No Slack commands or inbound message handling are required in this build.
// Resolve interviewer Slack user ID from email
GET https://slack.com/api/users.lookupByEmail?email=interviewer1@yourcompany.com
Headers: Authorization: Bearer {SLACK_BOT_TOKEN}
Response -> user.id used as channel in postMessage
// Send briefing DM
POST https://slack.com/api/chat.postMessage
{
"channel": "U01ABCDEF",
"text": "Hi {{interviewer_first_name}}, you have an interview with {{candidate_full_name}} on {{interview_date}} at {{interview_time}}. CV: {{cv_link}}. Focus area: {{focus_area}}"
}03Field mappings between tools
The following tables document every field handoff between agents and tools. Source and destination field names are written exactly as they appear in each tool's API response or request body. All intermediate values are stored in the workflow execution context object between steps.
Handoff 1: Greenhouse webhook to Availability Matching Agent (Agent 1)
Handoff 2: Notion panel rules to Google Calendar free/busy query (Agent 1 internal)
Handoff 3: Availability Matching Agent output to Scheduling and Comms Agent (Agent 1 to Agent 2)
Handoff 4: Calendly booking webhook to Google Calendar event creation and Gmail send (Agent 2 internal)
Handoff 5: Google Calendar event creation response to Slack and Gmail reminder (Agent 2 internal)
Handoff 6: Confirmed booking data to Greenhouse write-back (Agent 2 to Agent 3)
04Build stack and orchestration
// Credential store contents (reference names only; values stored encrypted)
GREENHOUSE_API_KEY // Harvest API key, Basic Auth
GREENHOUSE_WEBHOOK_SECRET // HMAC-SHA256 secret for inbound webhook validation
GREENHOUSE_INTERVIEW_STAGES // Comma-separated stage names to act on (e.g. 'Technical Interview,Phone Screen')
NOTION_API_TOKEN // Internal integration bearer token
NOTION_PANEL_DB_ID // Database ID of the interview panel rules Notion database
GOOGLE_SERVICE_ACCOUNT_JSON // Full service account key JSON (base64-encoded string)
GOOGLE_RECRUITER_CALENDAR_ID // Calendar ID used as event organiser (recruiter's calendar)
GOOGLE_CONFERENCE_SOLUTION // Conference type key e.g. 'hangoutsMeet'
GMAIL_SENDER_ADDRESS // Recruiter email address used as sending identity
GMAIL_REPLY_TO_ADDRESS // Reply-to address for candidate replies
GMAIL_TEMPLATE_BOOKING_LINK // Full email body template string with {{placeholders}}
GMAIL_TEMPLATE_REMINDER // Day-before reminder email body template string
CALENDLY_ACCESS_TOKEN // OAuth 2.0 bearer token or personal access token
CALENDLY_ORG_URI // Organisation URI: https://api.calendly.com/organizations/{uuid}
CALENDLY_EVENT_TYPE_UUID // UUID of the interview scheduling event type
CALENDLY_WEBHOOK_SIGNING_KEY // Signing key for Calendly-Webhook-Signature validation
CALENDLY_LINK_TTL_DAYS // Scheduling link expiry window in days (default: 7)
CALENDLY_SLUG_BASE // Base URL slug for Calendly scheduling pages
SLACK_BOT_TOKEN // xoxb- prefixed bot token
SLACK_WORKSPACE_ID // Slack workspace identifier
SLACK_FALLBACK_CHANNEL_ID // Channel ID for unresolvable DM targets and error alerts
SLACK_BRIEFING_TEMPLATE // Interviewer briefing message template string with {{placeholders}}05Error handling and retry logic
More documents for this process
Every document generated for Interview Scheduling.