Documentation

Español

API 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

  1. In the desktop app, open Settings → Developers → MCP and create a personal access token. The token is shown once; Mico stores only its hash.
  2. 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 returns 405.
  • Every successful response wraps its payload in data. Lists add has_more and next_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-Id header. Include it when you contact support.

Pagination

List endpoints return newest first and use cursors:

  1. Request the first page, optionally with limit (1–200, default 50).
  2. If has_more is true, request the next page with cursor set to the next_cursor you received.
  3. Stop when has_more is false and next_cursor is null.

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.

ParameterTypeDefaultNotes
limitinteger501 to 200.
cursorstring—next_cursor from the previous page.
sincetimestamp—Only meetings created at or after this instant.
untiltimestamp—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.

ParameterTypeDefaultNotes
includestring—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.

ParameterTypeDefaultNotes
limitinteger501 to 200.
cursorstring—next_cursor from the previous page.
statusstring—Comma-separated: todo, in_progress, done.
assignee_human_idstring—Only items assigned to this person.
meeting_idstring—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.

ParameterTypeDefaultNotes
limitinteger501 to 200.
cursorstring—next_cursor from the previous page.
qstring—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.

ParameterTypeDefaultNotes
limitinteger501 to 200.
statusstring—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
  }
}
StatuscodeMeaning
400invalid_requestA parameter is invalid. param names it.
401unauthorizedNo token, not a mico_pat_ token, or an unknown token.
401token_revokedThe token was revoked. Create a new one.
402feature_not_includedYour plan does not include the API.
402no_planYour account has no active plan.
402quota_exhaustedThis billing period's requests are used up. resets_at says when they renew.
404not_foundNo such endpoint.
404meeting_not_foundNo meeting with that ID in your account.
404shared_note_not_foundNo note with that ID is shared with you.
404team_not_foundYou are not a member of that team.
402team_plan_requiredThe team's plan does not include team action items.
405method_not_allowedThe API only accepts GET.
429rate_limitedToo many requests in the last minute. Wait for Retry-After seconds.
500internal_errorSomething failed on Mico's side. request_id identifies the request.
503unavailableMico 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.

LimitFlowEnterprise
Requests per billing period50,00050,000, or what your contract says
Requests per minute120120

Successful responses report the billing-period quota in headers:

HeaderContent
X-Quota-LimitRequests included this billing period.
X-Quota-RemainingRequests left this billing period.
X-Quota-ResetWhen 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.