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:

  1. Closing method set to CALENDAR_MEETING_INTEGRATION
  2. 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

SettingDescription
DurationMeeting length in minutes (e.g., 15, 30, 45, 60)
Video ConferencingWhether to include a video link (Google Meet, Microsoft Teams)
ParticipantsWho should attend the meeting and how availability is sourced
Open HoursDays and times when meetings can be scheduled
LocationPhysical address for in-person meetings
Title & DescriptionMeeting 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 setupWhere availability comes from
isCalendarConnected: trueTheir connected Google or Microsoft calendar, read in real time
isCalendarConnected: false + availability.timeSlotsThe slots you supplied
isCalendarConnected: false + autoCollectAvailability: truePopp 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

Popp 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 sentPopp foundError
isCalendarConnected: trueno connected calendarCould not find a connected calendar for participant "…"
isCalendarConnected: truea Popp-managed virtual calendarParticipant "…" has a virtual calendar but was passed as connected
isCalendarConnected: falsea real connected calendarParticipant "…" 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.

ValueWho attendsParticipants
COLLECTIVE (default)Every participant on the panel — Popp books the intersection of everyone's availabilityExactly one isOrganizer: true
ROUND_ROBIN_MAX_AVAILABILITYOne participant from the pool, chosen to offer candidates the widest choice of slotsPool 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.

FieldWhere it livesWhat it controlsDefaultRange
availabilityOutreachSettings.periodDaysOutreach settings, template- or participant-levelThe window an interviewer is asked to offer availability within — and the window their reply is read against147–60
availableDaysInTheFutureTop-level template fieldHow far ahead a candidate may book on the booking page30≥ 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 (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

FieldTypeDescription
titlestringThe title of the meeting
durationintegerMeeting length in minutes (1-1440)
timezonestringIANA timezone (e.g., Europe/London, America/New_York)
videoConferencingbooleanWhether to include video conferencing
openHoursarrayAvailable time windows for scheduling
meetingParticipantsarrayList 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

FieldTypeDefaultDescription
descriptionstring-Calendar invite description
videoConferencingProviderstring-Google Meet or Microsoft Teams (required if videoConferencing is true)
locationstring-Physical address (cannot be used with video conferencing)
bufferinteger0Buffer time in minutes before/after meetings (multiple of 5, max 120)
noticePeriodMinutesinteger0Minimum notice required for booking
availableDaysInTheFutureinteger30How far ahead a candidate may book (see Collection Window vs Booking Horizon)
reminderMinutesBeforeMeetinginteger1440Minutes before meeting to send reminder
availabilityMethodstringCOLLECTIVEWho has to attend: COLLECTIVE or ROUND_ROBIN_MAX_AVAILABILITY (see Availability Method)
guestLabelstringcandidateWhat 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

FieldTypeDefaultDescription
requiredHoursinteger6Hours 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
periodDaysinteger14The 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
customTemplatedSubjectLinestring"Availability Request"Email subject line for the outreach email
customTemplatedMessagestringSystem defaultOpening email body sent to the participant
nudgeSettingsarray3 nudges at 24h intervalsFollow-up nudge configuration (see below)
additionalRecipientsstring[][]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:

PlaceholderResolves 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 — requiredHours and periodDays do not reach the email on their own. A customTemplatedMessage that 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 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

ParameterTypeDescription
titlestringSearch by title (partial match)
statusstringFilter by status (ACTIVE, ARCHIVED)
locationstringSearch by location (partial match)
isVideoConferencebooleanFilter by video conferencing enabled
limitintegerResults per page (1-100, default: 100)
nextTokenstringPagination 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 email, not by position.

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

The 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 you PUT a 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

FieldBehaviour when omitted
availabilityMethodThe 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
availabilityOutreachSettingsMerged key by key, so you can send only the keys you want to change
guestLabelKeeps 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

Next Steps

Once your campaign has a meeting template configured:


Did this page help you?