Creating and scheduling bots

Learn how to schedule bots and avoid the 507 error

Bots are single-use and each run on their own machine. To make a bot join a meeting, you must have a meeting URL and a time for the bot to join the meeting. The most common way to get this information is to:

  • Use Recall.ai's Calendar Integration to easily connect and automate the bot scheduling lifecycle. If using this integration, you will can use the calendar endpoints defined in the linked guide to schedule bots.
  • Use your own calendar integration to get the meeting details from the user's calendar events. You will need to use the Create Bot endpoint to create/schedule bots.

When creating bots, you should schedule the bot as soon as you receive the meeting URL and the meeting start time (e.g. when the user connects their calendar or when you're notified that a calendar event was created).

Bots are meant to be scheduled to join calls more than 10 minutes in advance

Scheduled bots are created when a bot's join_at is more than 10 min in advance. Scheduled bots are guaranteed to join on-time and will never be late to meetings.

❗️

Bots joining calls with less than 10 min notice

Ad-hoc bots are created when a bot's join_at is less than 10 min in advance or omitted completely at the time you call the Create Bot endpoint. For example, users may meet spontaneously and the user will supply the meeting URL to join a live (on-demand) meeting.

Recall maintains a limited pool of warm bots called the ad-hoc bot pool (since bots take time to start up), and the pool can deplete during brief spikes in which the API will return 507 errors. We're constantly replenishing the pool so you should be able to claim a bot within a few attempts by retrying every 30s.

Ad-hoc bots are a secondary option to scheduled bots and should be used sparingly, filling in the gaps where scheduled bots can't (e.g. ad-hoc/on-demand meetings). If your use case heavily depends on ad-hoc bots, reach out to [email protected] with more details about your implementation to discuss potential options available to you.

How to schedule a bot

To schedule a bot, you only need to set the join_at field to a time that is more than 10 minutes in the future. Recall will automatically reserve and start up a machine for your bot to ensure the bot joins on time. You can create a scheduled bot using the example below:

curl -X POST https://$RECALLAI_REGION.recall.ai/api/v1/bot \
    -H 'Authorization: Token $RECALLAI_API_KEY' \
    -H 'Content-Type: application/json' \
    -d '
    {
      "join_at": "SOME_TIME_MORE_THAN_10_MIN_IN_THE_FUTURE",
      "meeting_url": "$MEETING_URL",
      "bot_name": "My Bot",
    }'

How to update a scheduled bot

Scheduled bots are editable up until they start joining the meeting. The main thing to watch is the 10-minute window around join_at.

Example: Bot hasn't started joining the call yet (any field except `join_at`)

It’s 2025-12-01 10:00 am UTC. Bot is scheduled for 2025-12-01 10:01 am UTC.

  1. Call Update Scheduled Bot to change any fields except join_at (e.g. bot_name, meeting_url, metadata, etc.).
Example: Bot has started joining or is in the call (cannot update bot)

Bot is joining or in the call. You need to change something.

  1. You cannot update the bot at this stage.

If you try to update the bot after the bot has started joining, the API will then return the following error:

{
"code": "update_bot_failed",
"detail": "Only non-dispatched bots can be updated"
}
Example: Update a bot's `join_at` (`join_at` is > 10 minutes away)

It’s 2025-12-01 10:00 am UTC. Bot is scheduled for 2025-12-01 10:30 am UTC.

  1. Call Update Scheduled Bot to change any fields (e.g. bot_name, meeting_url, join_at, metadata, etc.).
Example: Update a bot's `join_at` (`join_at` is <= 10 minutes away)

It’s 2025-12-01 10:00 am UTC. Bot is scheduled for 2025-12-01 10:30 am UTC. You want it to join at 2025-12-01 10:07 am UTC.

  1. Call Delete Scheduled Bot.
  2. Call Create Bot with join_at="2025-12-01 10:07".

If you try to update the bot to a time that is less than 10 min away, the API will return the following error:

{
"code": "update_bot_failed",
"detail": "Not enough time to launch new bot"
}

How to delete a scheduled bot

Cancelling depends on how close you are to join_at.

Example: cancel bot > 10 minutes before `join_at`

It’s 2025-12-01 10:00 am UTC. Bot is scheduled for 2025-12-01 10:30 am UTC. Meeting is canceled.

  1. Call Delete Scheduled Bot.
Example: cancel < 10 minutes before `join_at`

It’s 2025-12-01 10:00 am UTC. Bot is scheduled for 2025-12-01 10:06 am UTC. You don’t want it to join.

  1. Call Remove Bot From Call.
Example: Remove the bot from a call after the bot starts joining (or is already in the meeting)

Bot is joining / in the meeting. You need it to stop.

  1. Call Remove Bot From Call.

How to delete scheduled bots in bulk

To delete many scheduled bots at once, you will need to:

  • Iterate over the results returned by the List Bots endpoint with join_at >= now() (you can filter for specific bots if preferred)
  • Call the Delete Scheduled Bot for every bot in the results

You can also use this method to delete all of your scheduled bots.

📘

See this script to filter and unschedule/delete many scheduled bots in bulk.

How to list all scheduled bots

You can retrieve all bots scheduled in the future by calling the List Bots endpoint with the join_at_after=CURRENT_ISO8601_TIMESTAMP filter.

curl --request GET \
     --url 'https://REGION.recall.ai/api/v1/bot/?join_at_after=CURRENT_ISO8601_TIMESTAMP' \
     --header 'Authorization: API_KEY' \
     --header 'accept: application/json'

Scheduling bots with your own calendar integration

If you already integrate with Google Calendar / Outlook outside of Recall.ai's Calendar Integration, to sync bots to a calendar's events, you should:

  • Run a daily full sync of all events in the next 7 days to seed and reconcile your upcoming window.
  • Use webhooks / change notifications to upsert/delete events inside that window and adjust bot scheduling when times or URLs change.

A daily sync ensures a calendar's “upcoming” calendar event window stays complete as time moves forward. Meetings created weeks or months in advance will naturally enter the next-7-days window over time, and the daily pass is what brings them into scope even if nothing about the event changes.


How to deduplicate bots

❗️

Deduplication is only supported with the calendar integration.

If you schedule bots directly via the Create Bot endpoint, Recall will not deduplicate bots automatically. To avoid creating multiple bots for the same meeting, you must implement deduplication in your own app (typically by persisting a meeting → bot mapping in your database). See below for details on how to manually deduplicate bots.

Deduplication allows you to schedule one bot to join a meeting on behalf of multiple participants. This is useful in cases where multiple users have a shared event marked for recording and you want to avoid scheduling multiple bots.

The Calendar Integration supports bot deduplication by default:

For bots created outside of our calendar integration using the Create Bot endpoint, Recall does not provide built-in bot deduplication and you will need to manually implement the logic to deduplicate bots in your app.

Manually deduplicating bots

Defining a deduplication key

A deduplication key is a stable key that identifies the single bot for a given meeting instance for the scope you choose (per meeting, per company, or per participant).

Common deduplication patterns
Example: One bot joins per meeting (Recommended)

You can ensure only one bot joins per meeting by creating a deduplication key in the following format: {meeting_start_time}-{meeting_url}. This deduplication key will ensure only one bot is scheduled across all connected calendars(for your Recall account).

Example: One bot joins per company per meeting

You can ensure only one bot joins per company by creating a deduplication key in the following format: {meeting_start_time}-{meeting_url}-{calendar_email_domain}. This deduplication key will ensure one bot per unique company domain across all connected calendars(for your Recall account) is scheduled.

Example: Every participant gets a bot (No deduplication)

You can ensure only one bot joins per company by creating a deduplication key in the following format: {meeting_start_time}-{meeting_url}-{event_or_unique_id}. This deduplication key will ensure one bot will join per participant.

Note: meeting URLs can be reused (e.g., recurring meetings), which is why most keys include some notion of time and/or a company/user scope.

💡

Deduplicating ad-hoc bots for meetings with scheduled bots

In practice, ad-hoc bots rarely join calls alongside scheduled bots because they serve different purposes; most bots are scheduled in advance, while ad-hoc bots are typically deployed when scheduled bots cannot be arranged in time

That said, if you'd like to deduplicate ad-hoc bots too, developers have used some form of {meeting_url}-{approximate_start_time} as the deduplication key, where approximate_start_time could be the nearest half hour (or similar, depending on how your users typically conduct these ad-hoc meetings).

Implementing bot deduplication in your app

Once you’ve defined a dedup_key, treat it as your app’s identifier for the single bot to use for that meeting instance within the scope you chose (per meeting, per company, or per participant). In implementation, your backend stores a mapping of dedup_key → bot_id, meaning:

  • The dedup_key is how you identify “this meeting instance + scope” in your app.
  • The bot_id is the Recall bot you created the first time you saw that dedup_key, and it’s the bot you will use for every subsequent request for the same dedup_key.

A typical flow looks like this:

  1. Generate the dedup_key for the meeting instance based on the scope you chose.
  2. Check whether your app has already created a bot_id for that dedup_key.
  3. If a bot_id exists, you can reference this bot_id so the same bot is used for this meeting instance.
  4. If no bot_id exists yet:
    • Create a new bot for the meeting via the Create Bot endpoint, then
    • Store the returned bot_id under that dedup_key so future requests map to the same bot.
📘

Associate bot_id to users in your app

Many products have multiple users who should be able to view the same meeting outputs (transcript, recordings, metadata). To support this, store a relationship in your database between the requesting user(s) and the bot_id you returned (for example, a user_id ↔ bot_id table).

This association is not required for deduplication itself - it’s only needed if multiple users in your product should be able to access the same bot’s

Example: One bot per meeting — first request (no existing bot for this dedup_key)

In this example, your scope is one bot per meeting instance

The user wants to record a specific meeting on their calendar so for a given calendar event:

  • You choose dedup_key = {meeting_start_time}-{meeting_url} from the calendar event details.
  • Your backend generates the dedup_key and checks your DB for {dedup_key → bot_id}.
  • No mapping exists yet, so your backend creates a new bot via Create Bot endpoint.
  • Recall returns bot_id = bot_123.
  • Your backend stores {dedup_key → bot_123} so the next request for the same meeting instance returns the same bot.
Example: One bot per meeting — subsequent request (existing bot for this dedup_key)

In this example, your scope is one bot per meeting instance. This is what happens when another request comes in for the same meeting instance and you’re deduping per meeting.

The user wants to record a specific meeting on their calendar so for a given calendar event:

  • Your backend generates the same dedup_key = {meeting_start_time}-{meeting_url}.
  • Your backend finds {dedup_key → bot_123} in your DB.
  • Your backend returns bot_123 and does not create another bot.
  • (Optional) Your backend associates User B with bot_123 so both users can access the same outputs in your product.
Example: One bot per company per meeting — two companies on the same meeting

In this example, your scope is one bot per company per meeting instance. This means the same meeting can intentionally have multiple bots — one per company.

User A from ACME.com wants to record a specific meeting on their calendar so for a given calendar event:

  • You choose dedup_key = {meeting_start_time}-{meeting_url}-{calendar_email_domain} for the participant.
    • Your backend generates ...-acme.com, finds no mapping, creates a bot, and stores {dedup_key → bot_acme_123}.

User B from acme.com wants to record the same meeting instance.

  • Your backend generates the same deduplication key as above, finds {dedup_key → bot_acme_123}, and returns bot_acme_123 (no new bot is created).

User C from globex.com clicks “Record” for the same meeting instance.

  • Your backend generates a different key ...-globex.com, finds no mapping, creates a second bot, and stores {dedup_key → bot_globex_456}.

Result: the meeting instance can have two bots (one for acme.com, one for globex.com) because that’s the scope you chose.

⚠️

Tracking changes to the dedup_key inputs

To keep your dedup_key → bot_id mapping accurate over time (e.g., if a meeting is rescheduled, the meeting URL changes, or your dedupe scope changes), you need a stable way to locate the existing mapping when the meeting details change.

In practice, store a link between the record in your system that represents the meeting (e.g., a calendar event ID or an internal meeting ID) and either:

  • the current dedup_key, or
  • the inputs you used to build it (meeting_url, meeting_start_time, scope fields).

When that meeting record changes, recompute the dedup_key and update your stored mapping so future requests resolve to the correct bot_id.


FAQ

What's the concurrent bot limit?

The "concurrent bot limit" refers to concurrent bots live in meetings deployed ad-hoc (referred to as ad-hoc bots). Ad-hoc bots are rare in practice because most bots should be scheduled in advance. Ad-hoc bots are only meant to fill in the gaps where scheduled bots (bots scheduled more than 10 minutes in advance) can’t (e.g., last-minute meetings).

There are no limits on concurrent bots live in meetings scheduled more than 10 minutes in advance. This effectively means that most bots won’t count toward this 30 concurrent bots limit

If you are expecting high ad-hoc bot usage, please reach out to support with details around your constraint/limitations and we can work with you to find a oslution that fits your use case.