A sales team of 8 reps shares one “Book a demo” link. The hard part isn’t showing open times, it’s deciding who gets the lead. Hand every booking to the first free person and one rep drowns while others sit idle. Round-robin scheduling spreads bookings evenly, but doing it well means checking real-time availability across every member’s calendar and then assigning the slot to the right one. This recipe shows both halves: the availability call that spans a whole team, and the assignment logic that picks the next host.
How does round robin scheduling work in a team scheduling application?
Section titled “How does round robin scheduling work in a team scheduling application?”Round-robin scheduling treats a group of hosts as a single bookable resource and rotates bookings across them. When a request arrives, the system finds slots where at least one member is free, then assigns the slot to one host by a fairness rule, usually whoever was booked least recently. The booker sees one calendar for the whole team.
The mechanics break into two steps that run on every request. First, you ask for availability across all members at once so a slot counts as open if any single host can take it. Second, you pick one host from the free set and write the event to that person’s calendar. The Nylas POST /v3/calendars/availability endpoint handles both signals in one response: it returns a time_slots array, each entry carrying an emails array listing exactly which members are free, plus a top-level order array ranking participants by how recently they were last booked. With 8 reps, that single call replaces 8 separate calendar lookups, returning the whole free set in one round trip.
How do I implement round robin scheduling in Python for meeting assignment?
Section titled “How do I implement round robin scheduling in Python for meeting assignment?”To implement round-robin assignment in Python, send one availability request with every team member as a participant, set availability_method to max-fairness, then read the response order array to pick the host. The API ranks participants by how recently they were last booked for this event type, with never-booked members first, so the first email in order that appears in a slot’s emails list is your assignment.
The request below calls POST /v3/calendars/availability with all hosts as participants. Setting availability_method to max-fairness tells the API to rank participants so the least-recently-booked member sorts first, which is the core of even distribution. Each participant email must map to a valid Nylas grant in your application.
curl --request POST \ --url 'https://api.us.nylas.com/v3/calendars/availability' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "start_time": 1700000000, "end_time": 1700086400, "duration_minutes": 30, "interval_minutes": 30, "participants": [ { "email": "[email protected]", "calendar_ids": ["primary"] }, { "email": "[email protected]", "calendar_ids": ["primary"] }, { "email": "[email protected]", "calendar_ids": ["primary"] } ], "availability_rules": { "availability_method": "max-fairness", "round_robin_group_id": "demo_team" } }'The response returns order and a list of time_slots. Each slot carries the emails of members free for that window. The Python below picks the first slot and assigns the highest-ranked free host. It iterates the order list, which is sorted least-recently-booked first, so the assignment naturally balances load across the team over time.
from nylas import Client
nylas = Client(api_key="<NYLAS_API_KEY>")
response = nylas.calendars.get_availability( request_body={ "start_time": 1700000000, "end_time": 1700086400, "duration_minutes": 30, "interval_minutes": 30, "participants": [ ], "availability_rules": { "availability_method": "max-fairness", "round_robin_group_id": "demo_team", }, })
availability = response.dataranked = availability.order # least-recently-booked host first
slot = availability.time_slots[0]assigned_host = next(email for email in ranked if email in slot.emails)
print(f"Assign {slot.start_time}-{slot.end_time} to {assigned_host}")How do I assign each booking to the next free team member?
Section titled “How do I assign each booking to the next free team member?”Assignment comes down to intersecting two lists: the order array, which ranks every participant by fairness, and a slot’s emails array, which names who is actually free for that window. Walk the ranked order, take the first host that also appears in the slot, and write the event to that calendar. This guarantees both fairness and a real opening.
The pattern matters because a slot’s free set changes per window. The most-fair host overall might be booked at 2:00 PM but open at 3:00 PM, so you resolve the assignment slot by slot, not once per request. The Java below mirrors the Python logic for teams on the JVM. It reads getOrder() and each slot’s getEmails() from the GetAvailabilityResponse, then selects the first ranked host present in the target slot. With a 30-minute duration_minutes and a busy 8-person team, expect dozens of candidate slots in a single business day, so caching the response for the length of one booking session avoids redundant calls.
import com.nylas.NylasClient;import com.nylas.models.*;import java.util.List;
public class RoundRobinAssign { public static void main(String[] args) throws NylasSdkTimeoutError, NylasApiError { NylasClient nylas = new NylasClient.Builder("<NYLAS_API_KEY>").build();
List<AvailabilityParticipant> participants = List.of( );
AvailabilityRules rules = new AvailabilityRules.Builder() .availabilityMethod(AvailabilityMethod.MAX_FAIRNESS) .roundRobinGroupId("demo_team") .build();
GetAvailabilityRequest request = new GetAvailabilityRequest.Builder( 1700000000, 1700086400, participants, 30) .availabilityRules(rules) .build();
GetAvailabilityResponse data = nylas.calendars().getAvailability(request).getData();
List<String> ranked = data.getOrder(); // least-recently-booked first TimeSlot slot = data.getTimeSlots().get(0);
String assignedHost = ranked.stream() .filter(email -> slot.getEmails().contains(email)) .findFirst() .orElseThrow();
System.out.println("Assign slot to " + assignedHost); }}What is the difference between max-fairness and max-availability?
Section titled “What is the difference between max-fairness and max-availability?”The availability_method field accepts three values: collective, max-fairness, and max-availability, with max-availability as the default. For round-robin, the choice is between the last two. Use max-fairness to balance load evenly across the team, and max-availability to surface the most open slots even if one host ends up busier.
Both methods rank participants by how recently they were last booked for the event type, least-recently-booked first, using the key5 metadata convention to decide which events count. The difference is how strongly that ranking steers the result. max-fairness weights the booking history heavily so load evens out across the team over time, even when that means offering fewer total slots on a busy day. max-availability prioritizes open time instead, which surfaces more slots but can skew volume toward whoever has the widest availability.
| Concern | max-fairness | max-availability |
|---|---|---|
| Optimizes for | Even load across hosts | Most open slots offered |
| Best when | You promised reps equal lead volume | You want maximum booking conversion |
| Risk | Fewer slots shown on a busy day | One host absorbs most bookings |
order ranking | Least-recently-booked first, weighted for even load | Least-recently-booked first, weighted for open time |
To make either mode count the right history, tag the events you want included with metadata key key5 set to your group identifier. The group availability and booking best practices guide explains the key5 convention in full.
How do I check raw busy time before assigning?
Section titled “How do I check raw busy time before assigning?”When you need raw busy blocks rather than computed slots, call POST /v3/grants/{grant_id}/calendars/free-busy with the team’s email addresses. It returns each member’s busy time_slots directly from the provider, which is useful for building a custom fairness score or auditing why a host was skipped. The response carries one entry per address in the emails array.
This Free/Busy lookup is a lower-level companion to the availability call. The availability endpoint computes bookable slots for you; the Free/Busy endpoint hands back the underlying busy intervals so you can run your own logic, like weighting by meeting count or excluding all-day events. One request covers up to the grant’s connected calendars, and the response sets an error field per address when a single mailbox fails, so one bad calendar never breaks the whole batch.
curl --request POST \ --url 'https://api.us.nylas.com/v3/grants/<NYLAS_GRANT_ID>/calendars/free-busy' \ --header 'Authorization: Bearer <NYLAS_API_KEY>' \ --header 'Content-Type: application/json' \ --data '{ "start_time": 1700000000, "end_time": 1700086400, "emails": ["[email protected]", "[email protected]", "[email protected]"] }'Read the per-address busy blocks, score each host however your team distributes work, then write the event to the winner’s calendar. For the request and response fields in detail, see the check availability recipe.
One tradeoff worth naming
Section titled “One tradeoff worth naming”Building round-robin on the raw Calendar API gives you full control over the fairness rule, but you own the assignment loop, the booking write, and the concurrency guard. If two requests pick the same host for the same 30-minute window within a second, you can double-book unless you add a lock. The managed Scheduler handles that race for you. So if you only need standard fair rotation and a hosted booking page, the managed flow is the faster path. Reach for this Calendar API approach when your assignment logic is genuinely custom, like routing by deal size, language, or territory. The prevent double-booking recipe covers the lock you’ll need for the do-it-yourself path.
What’s next
Section titled “What’s next”- Check availability for the Free/Busy and availability request and response fields
- Prevent double-booking for the concurrency lock the custom path requires
- Round-robin email routing to distribute inbound messages across a team the same way
- Group availability and booking best practices for the
max-fairnessandkey5metadata details