Video call REST API

Schedule and control video meetings with the REST API

The Meeto REST API at https://api.meeto.me/api/v1 lets your server create one-off and recurring video meetings, invite email guests with reminder emails, run host controls in live rooms and fetch recordings and AI summaries. It authenticates with a secret mk_secret_… key and needs the key owner on Pro or a paid Team seat; other accounts get 402 plan_required. The embeddable widget stays free on every plan.

What can the Meeto API do?

It covers the full life of a meeting your product schedules: create it, invite people, move or cancel dates, control the room while the call runs and collect the recording and AI summary afterwards. All paths below are relative to https://api.meeto.me/api/v1.

Resource groups of the REST API
GroupEndpoints
MeetingsPOST /meetings, GET /meetings, GET · PATCH · DELETE /meetings/{id}, POST /meetings/{id}/reschedule, GET /meetings/{id}/ics
InvitationsGET · PUT /meetings/{id}/participants for Meeto accounts; email guests through the guests field
Calendar feedGET /calendar?from=…&to=… expands series into dates, up to 62 days per request
RoomsGET /rooms, GET /rooms/{slug}, live participants, join, settings (open, knock or password), end the session
Host controlsmute one, mute all, promote to co-host, remove and let back in, knock queue and POST /knocks/{id}/decide
Capturerecording start, stop and extend; AI summary start, stop and the live summary
MaterialsGET /recordings, GET /notes, then /materials/{token} to read, download video or audio, change sharing or delete

Recurring meetings use a subset of the iCalendar RRULE: DAILY, WEEKLY, MONTHLY or YEARLY; an interval up to 99; one or more weekdays for a weekly rule; for a monthly rule the 1st–4th or last weekday, the start's own day of the month or the last day; and COUNT or UNTIL. A yearly rule repeats on the start's own date. Dates keep their local time across daylight-saving changes in the meeting's IANA time zone, with the same rules the Meeto app offers when you schedule a meeting.

The API sees only what its key created. Meetings that guests book on your booking page are not listed here; their events reach your server through webhooks.

How does authentication work?

Send a secret server key as a bearer token. Create a website widget key in Settings → Website widget; the server key mk_secret_… is shown once, when the key is created. The public mk_live_… key belongs in browser code and cannot call this API (401 invalid_key).

Authorization: Bearer mk_secret_…

Each key is its own scope. It can read and change only the meetings, rooms and materials created through it; two keys of one account do not see each other's meetings, and a key never reaches billing, team settings or other rooms of the account. Revoking the key in the dashboard ends API access at once and stops new joins to its rooms. Keep the secret on your server, out of browser bundles, URLs and logs.

Which plan does the API need?

The owner of the key must be on Pro ($6.99/month or $69/year) or hold a paid active Team seat ($11.99 per seat per month). Every /api/v1 route checks this on each request:

HTTP/1.1 402 Payment Required
{"code":"plan_required","error":"plan_required","requestId":"…","retryable":false}

The free parts stay free: the public widget key, the widget's own instant rooms and POST /api/embed/rooms without scheduling fields work on every plan, as described in the widget developer docs.

Create a recurring meeting with email guests

Creation requires an Idempotency-Key header: 1–200 printable ASCII characters, no spaces, one per business operation. Repeat the same key and body after a timeout and you get the original meeting back instead of a duplicate; the same key with a different body answers 409 idempotency_conflict.

curl https://api.meeto.me/api/v1/meetings \
  -H "Authorization: Bearer $MEETO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: crm-appointment-872" \
  -d '{
    "title": "Weekly project review",
    "startsAt": "2027-03-22T10:00:00+02:00",
    "durationMin": 45,
    "timezone": "Europe/Tallinn",
    "rrule": "FREQ=WEEKLY;BYDAY=MO,TH;COUNT=8",
    "guests": ["sam@example.com"],
    "guestReminders": [1440, 60]
  }'

The answer is 201 (trimmed here). Share joinUrl unchanged: its k parameter is the room access key. Give hostSecret only to staff who should run the meeting.

{
  "meeting": {
    "id": "<meeting UUID>",
    "roomSlug": "misty-fox-a18f493cb027fe823cb6",
    "title": "Weekly project review",
    "startsAt": "2027-03-22T08:00:00Z",
    "durationMin": 45,
    "timezone": "Europe/Tallinn",
    "repeat": "custom",
    "rrule": "FREQ=WEEKLY;BYDAY=MO,TH;COUNT=8",
    "seriesEndsAt": "2027-04-15T07:45:00Z",
    "guests": ["sam@example.com"],
    "status": "scheduled",
    "joinUrl": "https://meeto.me/misty-fox-a18f493cb027fe823cb6?k=<room access key>"
  },
  "hostSecret": "<host credential>"
}
Creation fields
FieldRules
titleUp to 200 characters
startsAt / durationMinRFC 3339 with an offset; 1–1440 minutes
timezone / rruleIANA zone (default UTC); the start must be one of the rule's dates
guestsUp to 25 email addresses, no Meeto account needed; each gets a private calendar invitation
guestRemindersMinutes before each date: 15, 60 and/or 1440, at most two. Off unless you send it; not echoed in responses
participantUserIdsUp to 50 registered Meeto accounts to invite
callMode / regionaudio or video (default video); optional preferred media region

Email guests need the owner's address to be verified by Google or Apple sign-in (403 guests_need_verified_email otherwise). Invitations, updates and cancellations count against the account's guest-mail budget; past it, creation answers 429 guest_limit and nothing is created. Reminder emails do not count against that budget.

How do I move or cancel one date of a series?

Send occurrence, the date as it stands, with the new startsAt. Only that date moves; it becomes a meeting of its own with a new ID and keeps the same room link, and guests get an updated invitation.

curl -X PATCH https://api.meeto.me/api/v1/meetings/$MEETING_ID \
  -H "Authorization: Bearer $MEETO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "occurrence": "2027-03-25T08:00:00Z",
    "startsAt": "2027-03-26T10:00:00+02:00"
  }'

Leave occurrence out to edit the whole series. scope: "following", which changes a date and every later one, works from the first date of a series (where it means the whole series); from a later date it is not enabled yet and answers 409 split_unavailable. Add expectedRevision to refuse a stale edit. DELETE /meetings/{id}?occurrence=… removes one date; DELETE without it cancels the meeting, which stays readable with "status": "canceled".

Control the live room and collect recordings

The meeting's roomSlug addresses the room routes. The secret key acts as host for its own rooms, so your backend can mute everyone, promote a co-host or remove someone without the host secret. Moderation needs a live identity from GET /rooms/{slug}/participants; a person who has left answers 404 participant_not_found. A removed person cannot rejoin that session until you allow them back.

curl -X POST https://api.meeto.me/api/v1/rooms/misty-fox-a18f493cb027fe823cb6/recording/start \
  -H "Authorization: Bearer $MEETO_API_KEY"

# → 201 { "id": "…", "status": "…", "startedAt": 1805702460,
#         "notesStarted": true, "pageToken": "…" }

curl https://api.meeto.me/api/v1/recordings?limit=20 \
  -H "Authorization: Bearer $MEETO_API_KEY"

Recording starts the MP4 recording and the AI summary together. If the summary cannot start, the video continues and the answer carries notesError, so you can retry notes/start. Recording and AI summary have separate stop endpoints. Call it while the meeting is in progress; everyone in the call sees a capture indicator.

Rate limits, errors and retries

Request rate

Each client IP has a bucket of 60 requests that refills by one per second. Meeting creation has its own bucket per key: 60, then one every 5 seconds.

Retry-After

Every 429 and 5xx answer has retryable: true; 429 and 503 also carry Retry-After. Retry a create with the same idempotency key.

Tracing

Every answer has X-Request-ID. Keep it with your own operation ID when you contact support.

Common error codes
StatusCodes
400bad_json, bad_time, bad_duration, bad_timezone, bad_rrule, rrule_start_mismatch, bad_guest, too_many_guests, idempotency_key_required, bad_pagination
401 · 402 · 403invalid_key · plan_required · account_unavailable, guests_need_verified_email
404 · 409 · 410not_found (missing or created by another key) · idempotency_conflict, meeting_changed, occurrence_moved, split_unavailable · key_revoked
429 · 502 · 503rate_limited, guest_limit · livekit_error from the media service · auth_unavailable, service_unavailable

Errors share one shape: code, error (the same code), requestId, retryable and, for creation, the failing field. Lists take limit (1–100, default 50) and offset, and return hasMore with nextOffset. Media is encrypted in transit; Meeto is not end-to-end encrypted. See security for how calls are handled.

Frequently asked questions

Is there a server SDK for the REST API?

No. The API is plain HTTPS with JSON bodies, so any HTTP client works. The npm packages and the iOS and Android libraries are for the embeddable call widget, not for /api/v1.

Do meetings created through the API appear in the Meeto app?

Yes. The account that owns the key is the organizer, so the meeting appears in its web and mobile calendar and the owner can sign in and host it with normal host rights on any device.

How long and how far ahead can an API meeting be?

durationMin is an integer from 1 to 1440 minutes. startsAt must be in the future and less than three years ahead. A series may have up to 730 occurrences with COUNT, or end with UNTIL no later than 2100.

What happens when the key owner leaves Pro?

Every /api/v1 call answers 402 plan_required until the owner is on Pro or a paid Team seat again. The public widget key keeps working on every plan, and calls in the owner's rooms follow the Free limits.

Can the API send webhooks for meetings it creates?

Webhook events follow bookings made on a Meeto booking page. For meetings created through the API, read GET /meetings/{id}, GET /notes and GET /recordings to learn what happened.

Put it to work

Open your Meeto account to set it up, or explore the working product first.