Meeting Templates
Meeting Templates
A Meeting Template defines the meeting configuration that applies to all conversations within a campaign. When a candidate successfully completes the conversation flow, the meeting template settings determine how the meeting is scheduled.
Prerequisites
To use scheduling features, your campaign must have:
- Closing method set to
CALENDAR_MEETING_INTEGRATION - Meeting Template attached to the campaign
How It Works
CAMPAIGN
closingMethod .............. CALENDAR_MEETING_INTEGRATION
calendarMeetingTemplateId .. template_abc123
│
▼
MEETING TEMPLATE
30 minutes · Google Meet · Mon–Fri 09:00–17:00
1 interviewer, calendar connected
│
├──▶ Conversation · John
├──▶ Conversation · Sarah all three book against
└──▶ Conversation · Mike the same template
All conversations within a campaign share the same meeting template configuration. This ensures consistency across all candidate interactions.
What's Included in a Meeting Template
| Setting | Description |
|---|---|
| Duration | Meeting length in minutes (e.g., 15, 30, 45, 60) |
| Video Conferencing | Whether to include a video link (Google Meet, Microsoft Teams) |
| Participants | Who should attend the meeting and how availability is sourced |
| Open Hours | Days and times when meetings can be scheduled |
| Location | Physical address for in-person meetings |
| Title & Description | Meeting title and calendar invite description |
Meeting Participants
Each meeting template defines who attends the meeting and where their availability comes from.
Participant Roles
- Organizer: The meeting owner who sends the calendar invite
- Attendee: Additional participants who will join the meeting
Whether an organizer is required depends on the availability method: a collective meeting needs exactly one participant with isOrganizer: true; a round-robin pool needs none (isOrganizer defaults to false).
Supplying Availability
Every participant needs at least one of three ways to tell Popp when they are free:
| Participant setup | Where availability comes from |
|---|---|
isCalendarConnected: true | Their connected Google or Microsoft calendar, read in real time |
isCalendarConnected: false + availability.timeSlots | The slots you supplied |
isCalendarConnected: false + autoCollectAvailability: true | Popp emails them and parses the reply (guide) |
Participants on one template can use different options — an interviewer on auto-collect alongside a colleague with a connected calendar.
A participant with isCalendarConnected: false and neither availability.timeSlots nor autoCollectAvailability is rejected with 400:
Participant "[email protected]" must either have a connected calendar, provide availability time slots, or have autoCollectAvailability enabled
isCalendarConnected must match reality
isCalendarConnected must match realityPopp looks up each participant's calendar by email and rejects the request if the flag disagrees with what it finds. All three mismatches return 400:
| You sent | Popp found | Error |
|---|---|---|
isCalendarConnected: true | no connected calendar | Could not find a connected calendar for participant "…" |
isCalendarConnected: true | a Popp-managed virtual calendar | Participant "…" has a virtual calendar but was passed as connected |
isCalendarConnected: false | a real connected calendar | Participant "…" has a connected calendar but was passed as not connected |
If a participant has no calendar in Popp at all, send isCalendarConnected: false — Popp creates a virtual calendar for them automatically. To get a real calendar connected first, use Invite Calendar Contact.
Availability Method
availabilityMethod decides who has to attend the meeting. It is optional on create and update, and defaults to COLLECTIVE.
| Value | Who attends | Participants |
|---|---|---|
COLLECTIVE (default) | Every participant on the panel — Popp books the intersection of everyone's availability | Exactly one isOrganizer: true |
ROUND_ROBIN_MAX_AVAILABILITY | One participant from the pool, chosen to offer candidates the widest choice of slots | Pool of 2–10; no organizer needed |
Collective (default)
Omit availabilityMethod, or set it to COLLECTIVE, for a panel where everyone must be in the room. Every participant's availability is intersected, so the booking page only offers slots that work for all of them. Any number of them can be on autoCollectAvailability — see Collecting from Several Interviewers.
Exactly one participant must have isOrganizer: true, or the request fails with 400:
Exactly one participant must be marked as organizer
Round robin
ROUND_ROBIN_MAX_AVAILABILITY routes each meeting to one interviewer from a pool, so the candidate only ever meets a single person. Popp picks whichever member of the pool gives the candidate the widest choice of slots.
A pool needs 2 to 10 participants and no organizer — isOrganizer defaults to false, so leave it off. A pool outside that range fails with 400:
Round-robin requires a pool of 2–10 participants
A pool with no organizer, mixing connected calendars and auto-collect:
{
"availabilityMethod": "ROUND_ROBIN_MAX_AVAILABILITY",
"meetingParticipants": [
{ "name": "Jane Smith", "email": "[email protected]", "isCalendarConnected": true },
{ "name": "Raj Patel", "email": "[email protected]", "isCalendarConnected": true },
{
"name": "Mia Chen",
"email": "[email protected]",
"isCalendarConnected": false,
"autoCollectAvailability": true
}
]
}Collection Window vs Booking Horizon
Two fields control two different date ranges, and they are routinely confused. They are independent — neither derives from or caps the other.
| Field | Where it lives | What it controls | Default | Range |
|---|---|---|---|---|
availabilityOutreachSettings.periodDays | Outreach settings, template- or participant-level | The window an interviewer is asked to offer availability within — and the window their reply is read against | 14 | 7–60 |
availableDaysInTheFuture | Top-level template field | How far ahead a candidate may book on the booking page | 30 | ≥ 1 |
The distinction in one line: periodDays is about the interviewer being asked; availableDaysInTheFuture is about the candidate booking.
Worked example
{
"availableDaysInTheFuture": 30,
"availabilityOutreachSettings": {
"periodDays": 10
}
}The availability request emailed to the interviewer covers the next 10 days, not 30. The 30 only governs how far ahead the candidate's booking page lets them pick a slot.
Change periodDays to change what the interviewer is asked for; change availableDaysInTheFuture to change how far out candidates can book.
requiredHours is a target, not a gate
requiredHours is a target, not a gaterequiredHours (default 6, range 1–168) is how many hours the agent asks for, and what it nudges toward if the reply falls short. It is not a minimum that gates booking.
If the availability Popp ends up with is thinner than requiredHours — the interviewer offered less, or a collective panel's replies barely overlap — Popp books inside whatever overlap exists. Do not treat it as a guarantee of how much choice candidates will get.
Creating Meeting Templates
Create a meeting template via the API:
curl -X POST "https://api.joinpopp.com/v1/meeting-templates" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-organization-id: YOUR_ORGANIZATION_ID" \
-H "Content-Type: application/json" \
-d '{
"title": "Interview Call",
"description": "Initial screening interview",
"duration": 30,
"timezone": "Europe/London",
"videoConferencing": true,
"videoConferencingProvider": "Google Meet",
"openHours": [
{
"days": [1, 2, 3, 4, 5],
"start": "09:00",
"end": "17:00"
}
],
"meetingParticipants": [
{
"name": "Jane Smith",
"email": "[email protected]",
"isOrganizer": true,
"isCalendarConnected": true
}
],
"buffer": 15,
"noticePeriodMinutes": 60,
"availableDaysInTheFuture": 30
}'Required Fields
| Field | Type | Description |
|---|---|---|
title | string | The title of the meeting |
duration | integer | Meeting length in minutes (1-1440) |
timezone | string | IANA timezone (e.g., Europe/London, America/New_York) |
videoConferencing | boolean | Whether to include video conferencing |
openHours | array | Available time windows for scheduling |
meetingParticipants | array | List of participants. Exactly one must be the organizer for a collective meeting; a round-robin pool needs 2–10 and no organizer (see Availability Method) |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
description | string | - | Calendar invite description |
videoConferencingProvider | string | - | Google Meet or Microsoft Teams (required if videoConferencing is true) |
location | string | - | Physical address (cannot be used with video conferencing) |
buffer | integer | 0 | Buffer time in minutes before/after meetings (multiple of 5, max 120) |
noticePeriodMinutes | integer | 0 | Minimum notice required for booking |
availableDaysInTheFuture | integer | 30 | How far ahead a candidate may book (see Collection Window vs Booking Horizon) |
reminderMinutesBeforeMeeting | integer | 1440 | Minutes before meeting to send reminder |
availabilityMethod | string | COLLECTIVE | Who has to attend: COLLECTIVE or ROUND_ROBIN_MAX_AVAILABILITY (see Availability Method) |
guestLabel | string | candidate | What the availability email calls the person who books (see The guestLabel Field) |
Participant Configuration
A participant with a connected calendar:
{
"name": "Jane Smith",
"email": "[email protected]",
"isOrganizer": true,
"isCalendarConnected": true
}One without, supplying pre-defined availability:
{
"name": "John Doe",
"email": "[email protected]",
"isOrganizer": false,
"isCalendarConnected": false,
"availability": {
"timezone": "Europe/London",
"timeSlots": [
{
"date": "2025-01-20",
"startTime": "09:00",
"endTime": "12:00"
},
{
"date": "2025-01-21",
"startTime": "14:00",
"endTime": "17:00"
}
]
}
}Or set autoCollectAvailability: true (with isCalendarConnected: false) to have Popp email them for it. Any number of participants can use it — see Supplying Availability.
Availability Outreach Settings
When using autoCollectAvailability: true, you can customize how Popp collects availability from the participant using availabilityOutreachSettings. These settings can be configured at the template level (applies to all participants) or at the participant level (overrides template settings for that participant).
Resolution order: participant-level > template-level > system defaults.
Template-Level Settings
{
"title": "Panel Interview",
"availabilityOutreachSettings": {
"requiredHours": 4,
"periodDays": 10,
"customTemplatedSubjectLine": "{{INTERVIEWER_NAME}}, availability needed for upcoming interviews",
"customTemplatedMessage": "Hi {{INTERVIEWER_NAME}},\n\nWe're lining up interviews and would like to get yours booked in.\n\n{{MEETING_AVAILABILITY_TEXT}}\n\nThanks,\n{{AGENT_NAME}}",
"nudgeSettings": [
{ "delayHours": 12 },
{ "delayHours": 24 }
],
"additionalRecipients": ["[email protected]"]
},
"meetingParticipants": [
{
"name": "Jane Smith",
"email": "[email protected]",
"isOrganizer": true,
"isCalendarConnected": false,
"autoCollectAvailability": true
}
]
}Per-Participant Overrides
Each participant can override any field from the template-level settings. Fields not specified fall back to the template-level value, then to system defaults.
{
"meetingParticipants": [
{
"name": "Bob Smith",
"email": "[email protected]",
"isOrganizer": true,
"isCalendarConnected": false,
"autoCollectAvailability": true,
"availabilityOutreachSettings": {
"requiredHours": 6,
"periodDays": 14,
"additionalRecipients": ["[email protected]"]
}
}
]
}In this example, Bob's outreach email will request 6 hours over 14 days (his overrides), but use the template-level subject line and message (since he didn't override those).
Field Reference
| Field | Type | Default | Description |
|---|---|---|---|
requiredHours | integer | 6 | Hours of availability to ask for. A target the agent nudges toward, not a minimum that gates booking — see requiredHours is a target, not a gate |
periodDays | integer | 14 | The window the interviewer is asked to offer availability within, in days (min 7, max 60). Not the same as availableDaysInTheFuture — see Collection Window vs Booking Horizon |
customTemplatedSubjectLine | string | "Availability Request" | Email subject line for the outreach email |
customTemplatedMessage | string | System default | Opening email body sent to the participant |
nudgeSettings | array | 3 nudges at 24h intervals | Follow-up nudge configuration (see below) |
additionalRecipients | string[] | [] | Email addresses CC'd on all outreach communications |
Nudge Settings
nudgeSettings is an array where each entry represents one follow-up nudge. The delayHours field specifies the wait time since the previous message. The array length determines the total number of nudges.
"nudgeSettings": [
{ "delayHours": 12 },
{ "delayHours": 24 }
]This sends 2 nudges: the first 12 hours after the initial email, the second 24 hours after the first nudge. An empty array [] disables nudging entirely.
Supported Placeholders
Placeholder names are SCREAMING_SNAKE_CASE. These are available in customTemplatedSubjectLine and customTemplatedMessage for availability outreach:
| Placeholder | Resolves To |
|---|---|
{{INTERVIEWER_NAME}} | The meeting participant's first name |
{{CANDIDATE_FIRST_NAME}} | The recipient's first name. In availability outreach the recipient is the interviewer, so this resolves to the same person as {{INTERVIEWER_NAME}} — prefer {{INTERVIEWER_NAME}}, which reads correctly |
{{AGENT_NAME}} | The AI agent's name |
{{ORGANIZATION_NAME}} | Your organization name |
{{CAMPAIGN_OWNER_NAME}} | The campaign owner's name |
{{MEETING_AVAILABILITY_TEXT}} | The Popp-generated sentence stating the concrete ask — the collection window, the days and hours wanted, and the timezone |
{{INTERVIEWER_NAME}} and {{MEETING_AVAILABILITY_TEXT}} are specific to availability outreach; the rest are shared with campaign messaging.
{{MEETING_AVAILABILITY_TEXT}}is optional and not validated. It is the only thing that renders the concrete ask —requiredHoursandperiodDaysdo not reach the email on their own. AcustomTemplatedMessagethat omits it is accepted, and the interviewer is asked for availability without being told the window, the hours, or the timezone.Include the placeholder, or hand-write the ask yourself and keep it in sync — changing those two fields will not update your prose.
The guestLabel Field
guestLabel FieldguestLabel is a top-level template field — not part of availabilityOutreachSettings — and it does one job: it is the noun the availability email uses for the counterparty the interviewer is being scheduled to meet, the person who books the slot.
It defaults to "candidate". Override it when the meeting is not a candidate interview — an intake call where a recruiter books the slot, for example:
{
"guestLabel": "recruiter",
"availabilityOutreachSettings": {
"customTemplatedMessage": "Hi {{INTERVIEWER_NAME}},\n\nCould you share some availability for your intake call with the recruiter?\n\n{{MEETING_AVAILABILITY_TEXT}}\n\nThanks,\n{{AGENT_NAME}}"
}
}Three things to know:
- It applies to the whole meeting. There is no per-participant equivalent.
- It must not begin with
"the"— Popp prefixes that automatically — and is capped at 50 characters. - It never refers to the interviewer giving availability. That person is
{{INTERVIEWER_NAME}}.
Response
{
"id": "b0453b2c-9bf2-4903-a4da-b9cddb682425",
"title": "Interview Call",
"status": "ACTIVE",
"createdAt": "2025-01-01T09:00:00Z"
}Once you have a meeting template ID, attach it to your campaign by setting the closing method to CALENDAR_MEETING_INTEGRATION. All conversations in that campaign will use the template settings.
Listing Meeting Templates
Retrieve all meeting templates for your organization:
curl -X GET "https://api.joinpopp.com/v1/meeting-templates" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-organization-id: YOUR_ORGANIZATION_ID"Filtering
| Parameter | Type | Description |
|---|---|---|
title | string | Search by title (partial match) |
status | string | Filter by status (ACTIVE, ARCHIVED) |
location | string | Search by location (partial match) |
isVideoConference | boolean | Filter by video conferencing enabled |
limit | integer | Results per page (1-100, default: 100) |
nextToken | string | Pagination token from previous response |
Example with filters:
curl -X GET "https://api.joinpopp.com/v1/meeting-templates?status=ACTIVE&title=Interview&limit=10" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-organization-id: YOUR_ORGANIZATION_ID"Getting Meeting Template Details
Retrieve the full configuration for a specific meeting template:
curl -X GET "https://api.joinpopp.com/v1/meeting-templates/{templateId}" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-organization-id: YOUR_ORGANIZATION_ID"This returns the stored configuration, including availabilityMethod, per-participant autoCollectAvailability, availability outreach settings, buffer times, and reminder settings. It returns every field Update Meeting Template requires except isCalendarConnected, which you supply per participant — so a read can be modified and written straight back.
Note: Participant order is not guaranteed to be stable between reads. Match participants by
Updating a Meeting Template
PUT /v1/meeting-templates/{templateId} requires nearly every field, so in practice you send the template's whole configuration rather than a patch. The intended flow is read-modify-write: GET the template, change what you need, and send it back.
Omitting an optional field leaves its stored value unchanged — it does not clear it.
meetingParticipants is the exception
meetingParticipants is the exceptionThe participant array you send becomes the panel. It is not merged with the participants already on the template.
An omitted participant is removed from the panel. If a template has three interviewers and youPUTa payload listing two of them, the third is dropped from the meeting. There is no per-participant patch — always send the complete list of participants you want the template to end up with, and the whole pool on a round-robin template.
Fields that keep their stored value
| Field | Behaviour when omitted |
|---|---|
availabilityMethod | The template keeps its current method — it does not reset to COLLECTIVE. The participants you send are validated against whichever method results, so a round-robin template still needs its 2–10 pool even when you omit the field |
availabilityOutreachSettings | Merged key by key, so you can send only the keys you want to change |
guestLabel | Keeps its stored label. Send null to clear it explicitly |
Because an omitted availabilityMethod means "unchanged" rather than "collective", a PUT against a round-robin template that names no organizer is valid. The same payload sent to a collective template is rejected with Exactly one participant must be marked as organizer.
Inviting Calendar Contacts
Before creating a meeting template with a participant, they must have their calendar connected to Popp. Use the Invite Calendar Contact endpoint to send an invitation:
curl -X POST "https://api.joinpopp.com/v1/invite-calendar-contact" \
-H "x-api-key: YOUR_API_KEY" \
-H "x-organization-id: YOUR_ORGANIZATION_ID" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"name": "Jane Smith",
"reference": "hiring-manager-001"
}'The contact will receive an email invitation to connect their Google or Microsoft calendar to Popp.
Example Use Cases
Standard Interview
- Duration: 30 minutes
- Video: Google Meet
- Participants: Interviewer (calendar connected)
- Open Hours: Monday-Friday, 9am-5pm
Panel Interview
- Duration: 60 minutes
- Video: Microsoft Teams
- Participants:
- Interviewer (calendar connected, organizer)
- Team Lead (calendar connected)
- HR Representative (calendar connected)
- Open Hours: Tuesday-Thursday, 10am-4pm
On-site Visit
- Duration: 90 minutes
- Video: None
- Location: 123 Main St, Suite 400, New York, NY 10001
- Participants: Office Manager (pre-defined availability)
- Open Hours: Monday, Wednesday, Friday, 9am-12pm
API Reference
- Create Meeting Template - Create a new meeting template
- List Meeting Templates - List and search templates
- Get Meeting Template - Get full template details
- Update Meeting Template - Replace a template's configuration
- Invite Calendar Contact - Invite team members to connect calendars
Next Steps
Once your campaign has a meeting template configured:
- Auto-Schedule Conversations via the API
- Set up Webhooks to receive meeting notifications
Updated 1 day ago
