Documentation
EspañolAPI reference
Read your Mico meetings, notes, and action items over HTTPS with the REST API v1.
The Mico API is a read-only REST API for your own scripts, servers, and integrations. It serves the meetings you already sync to Mico, from Mico's cloud, so it works while the desktop app is closed. It requires a plan that includes the API (Flow), and Mico checks the plan on every request.
The API reads the same data as the remote MCP server. Choose MCP for AI agents and the API for code you write yourself. To be told when something happens instead of asking, use webhooks.
Authentication
- In the desktop app, open Settings → Developers → MCP and create a personal access token. The token is shown once; Mico stores only its hash.
- Send it as a bearer token on every request:
curl -H "Authorization: Bearer mico_pat_..." \
"https://<project>.supabase.co/functions/v1/api/v1/meetings?limit=5"
The exact base URL is shown under Settings → Developers → API. It has the form:
https://<project>.supabase.co/functions/v1/api/v1
Tokens are personal: a token reads only the meetings of the account that created it. Revoke a token in the same settings page; it stops working on the next request.
A personal access token reads all of your meetings and does not expire. Keep it on a server. The API sends no CORS headers, so browsers cannot read its responses from a web page.
Requests and responses
- Every endpoint is
GET. Any other method returns405. - Every successful response wraps its payload in
data. Lists addhas_moreandnext_cursor. - Missing values are
null, never an empty string. - Timestamps are ISO 8601 in UTC.
- New fields can appear in any object. Ignore fields you do not know.
- Every response carries an
X-Request-Idheader. Include it when you contact support.
Pagination
List endpoints return newest first and use cursors:
- Request the first page, optionally with
limit(1–200, default 50). - If
has_moreistrue, request the next page withcursorset to thenext_cursoryou received. - Stop when
has_moreisfalseandnext_cursorisnull.
Send the same filters with every page. Cursors are opaque: do not build or edit them.
curl -H "Authorization: Bearer $MICO_TOKEN" \
"$MICO_API/meetings?limit=100&cursor=eyJjIjoi..."
Endpoints
GET /v1/meetings
Your meetings, newest first by created_at. Deleted meetings are excluded.
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 50 | 1 to 200. |
cursor | string | — | next_cursor from the previous page. |
since | timestamp | — | Only meetings created at or after this instant. |
until | timestamp | — | Only meetings created before this instant. |
since and until must include a time and a time zone, for example 2026-10-01T00:00:00Z.
{
"data": [
{
"id": "6f1c2a0e-...",
"title": "Weekly sync",
"kind": "meeting",
"status": "active",
"started_at": "2026-10-03T09:00:00+00:00",
"ended_at": "2026-10-03T09:42:10+00:00",
"created_at": "2026-10-03T08:59:58.412093+00:00",
"updated_at": "2026-10-03T10:05:11.130045+00:00",
"series_id": null
}
],
"has_more": true,
"next_cursor": "eyJjIjoiMjAyNi0xMC0wM1QwODo1OTo1OC40MTIwOTMrMDA6MDAiLCJpIjoiNmYxYzJhMGUtLi4uIn0"
}
GET /v1/meetings/{meeting_id}
One meeting with its note, summaries, participants, and action items. A meeting that does not exist, was deleted, or belongs to someone else returns 404 meeting_not_found.
| Parameter | Type | Default | Notes |
|---|---|---|---|
include | string | — | transcript adds the full transcript. |
{
"data": {
"id": "6f1c2a0e-...",
"title": "Weekly sync",
"kind": "meeting",
"status": "active",
"started_at": "2026-10-03T09:00:00+00:00",
"ended_at": "2026-10-03T09:42:10+00:00",
"created_at": "2026-10-03T08:59:58.412093+00:00",
"updated_at": "2026-10-03T10:05:11.130045+00:00",
"series_id": null,
"timezone": "Europe/Madrid",
"language": "es",
"note": {
"id": "b2d0...",
"kind": "note",
"title": "Notes",
"template_id": null,
"text": "Budget approved.\nAna sends the minutes",
"created_at": "2026-10-03T09:05:00+00:00",
"updated_at": "2026-10-03T10:05:00+00:00"
},
"summaries": [
{
"id": "c81e...",
"kind": "summary",
"title": "Summary",
"template_id": null,
"text": "Decisions\nThe Q4 budget is approved.",
"created_at": "2026-10-03T09:43:02+00:00",
"updated_at": "2026-10-03T09:43:02+00:00"
}
],
"participants": [
{
"human_id": "a1f3...",
"name": "Carla Ruiz",
"email": "carla@example.com",
"role": null,
"job_title": "CFO"
}
],
"action_items": [
{
"id": "e4a9...",
"text": "Send the minutes",
"status": "todo",
"assignee_human_id": "a1f3...",
"due_at": null,
"completed_at": null
}
]
}
}
Note and summary text is plain text with one line per paragraph or heading. kind is summary for the generated summary and template_output for a summary made from a template.
With ?include=transcript, the meeting also contains:
"transcript": {
"text": "Hi everyone\n\nGood morning",
"segments": [
{ "id": "1d0e...", "track": "mic", "start_ms": 0, "end_ms": 25000, "text": "Hi everyone" },
{ "id": "7c3b...", "track": "speaker", "start_ms": 0, "end_ms": 25000, "text": "Good morning" }
]
}
start_ms and end_ms are offsets from the start of the recording. track is mic for your microphone, speaker for the other participants' audio, and mixed when both were recorded on one track. The transcript is returned whole, so request it only when you need it.
GET /v1/action-items
Your action items across meetings, newest first.
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 50 | 1 to 200. |
cursor | string | — | next_cursor from the previous page. |
status | string | — | Comma-separated: todo, in_progress, done. |
assignee_human_id | string | — | Only items assigned to this person. |
meeting_id | string | — | Only items from this meeting. |
{
"data": [
{
"id": "e4a9...",
"text": "Send the minutes",
"status": "todo",
"assignee_human_id": "a1f3...",
"due_at": null,
"completed_at": null,
"meeting": { "id": "6f1c2a0e-...", "title": "Weekly sync" }
}
],
"has_more": false,
"next_cursor": null
}
meeting is null for an action item that did not come from a meeting.
Team endpoints
Your token also reads what other people share with you, including everything shared with your teams. It sees exactly what you see in the app: the same rules decide, and you stop seeing a team's notes the moment you leave it. Notes come as their shared version (the note and its summary). Transcripts of other people's meetings are never included.
GET /v1/shared-notes
Notes others share with you, newest first. Your own meetings are in /v1/meetings.
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 50 | 1 to 200. |
cursor | string | — | next_cursor from the previous page. |
q | string | — | Only notes whose title or text contain every word. |
{
"data": [
{
"id": "2d8f...",
"title": "Pricing review",
"team": { "id": "9b1e...", "name": "Acme" },
"owner_name": "Bea Ruiz",
"access": "viewer",
"published_at": "2026-10-05T10:00:00Z"
}
],
"has_more": false,
"next_cursor": null
}
team is null when the note was shared with you directly rather than with a team. access is viewer, commenter or editor.
GET /v1/shared-notes/{shared_note_id}
One shared note with its text.
{
"data": {
"id": "2d8f...",
"title": "Pricing review",
"team_name": "Acme",
"published_at": "2026-10-05T10:00:00Z",
"text": "We raise Flow in January\nNew price list goes out on the 15th"
}
}
GET /v1/teams
The teams you belong to.
{
"data": [
{
"id": "9b1e...",
"name": "Acme",
"role": "member",
"member_count": 4,
"plan": "flow",
"can_collaborate": true
}
]
}
plan is null when the team has no active plan. A team without can_collaborate has nothing shared to read.
GET /v1/teams/{team_id}/action-items
Action items from the notes shared with a team. The team's plan has to include team action items.
| Parameter | Type | Default | Notes |
|---|---|---|---|
limit | integer | 50 | 1 to 200. |
status | string | — | One of todo, in_progress, done. |
{
"data": [
{
"id": "e4a9...",
"text": "Send the proposal",
"status": "todo",
"due_at": null,
"assignee": "Ana",
"owner_name": "Bea Ruiz",
"created_at": "2026-10-04T10:00:00Z",
"shared_note": { "id": "2d8f...", "title": "Planning" }
}
]
}
assignee is the name written in the note, not a Mico account. Open the source with GET /v1/shared-notes/{shared_note.id}.
Errors
Errors use one envelope. Branch on code; the message can change.
{
"error": {
"code": "feature_not_included",
"message": "Your plan does not include the Mico API",
"feature": "public_api",
"used": 0,
"limit": null,
"resets_at": null
}
}
| Status | code | Meaning |
|---|---|---|
400 | invalid_request | A parameter is invalid. param names it. |
401 | unauthorized | No token, not a mico_pat_ token, or an unknown token. |
401 | token_revoked | The token was revoked. Create a new one. |
402 | feature_not_included | Your plan does not include the API. |
402 | no_plan | Your account has no active plan. |
402 | quota_exhausted | This billing period's requests are used up. resets_at says when they renew. |
404 | not_found | No such endpoint. |
404 | meeting_not_found | No meeting with that ID in your account. |
404 | shared_note_not_found | No note with that ID is shared with you. |
404 | team_not_found | You are not a member of that team. |
402 | team_plan_required | The team's plan does not include team action items. |
405 | method_not_allowed | The API only accepts GET. |
429 | rate_limited | Too many requests in the last minute. Wait for Retry-After seconds. |
500 | internal_error | Something failed on Mico's side. request_id identifies the request. |
503 | unavailable | Mico could not check your token or plan. Retry shortly. |
Quotas and rate limits
Each request that passes authentication and parameter validation counts as one API request, including requests that end in 404 meeting_not_found, 404 shared_note_not_found or 404 team_not_found for a well-formed ID. Requests rejected with 400, 401, 404 not_found, 405, or 429 do not count, and neither do requests your plan does not cover.
| Limit | Flow | Enterprise |
|---|---|---|
| Requests per billing period | 50,000 | 50,000, or what your contract says |
| Requests per minute | 120 | 120 |
Successful responses report the billing-period quota in headers:
| Header | Content |
|---|---|
X-Quota-Limit | Requests included this billing period. |
X-Quota-Remaining | Requests left this billing period. |
X-Quota-Reset | When the count resets. |
When you exceed the per-minute limit, the API returns 429 rate_limited with a Retry-After header. Back off for that many seconds before retrying.
Example: export every meeting from October
MICO_API="https://<project>.supabase.co/functions/v1/api/v1"
cursor=""
while :; do
page=$(curl -sf -H "Authorization: Bearer $MICO_TOKEN" \
"$MICO_API/meetings?limit=200&since=2026-10-01T00:00:00Z&until=2026-11-01T00:00:00Z${cursor:+&cursor=$cursor}")
echo "$page" | jq -c '.data[]'
cursor=$(echo "$page" | jq -r '.next_cursor // empty')
[ -z "$cursor" ] && break
done
What is not here yet
- Write endpoints. The API is read-only.
- Team tokens that belong to a team instead of a person. Today a personal token reads what that person can see, team notes included; team tokens will add to that without changing it.