Skip to content
Median
Esc
↑↓navigate↵open⌘Jpreview
On this page

Errors and limits

The error envelope, every error code, rate limits per plan and size limits for the REST API.

Error response

Every error is JSON with a code and a message.

{
  "error": {
    "code": "invalid_session",
    "message": "Session tokens are 8 to 128 characters."
  }
}

Branch on code. The message is written for a person, names the fix, and can change.

Status codes

Status Meaning
400 The request is invalid, or it was refused by a rule with no status of its own
401 The credential is missing or matches nothing
403 The token’s person does not hold the role this needs
404 Not found, or not in your organization
409 It already exists, or it was already settled
429 Rate limited. Wait the seconds in Retry-After.
500 internal_error. Retry, and contact support if it continues.

Error codes

Credentials and requests

Code Status When
missing_api_key 401 No Authorization: Bearer header
invalid_api_key 401 The key matches no organization or was revoked, or an OAuth token was sent to a messaging route
publishable_key 401 A median_pk_ key was sent. The API takes MEDIAN_KEY.
invalid_token 401 The OAuth token is unknown or expired, or its person left the organization
no_organization 403 The OAuth token has no organization bound, or its organization is gone
token_required 401 A key was sent to an account route
forbidden 403 The token’s person lacks the role
needs_a_person 400 A key tried to invite or change members
legacy_api_key 400 A key from before Median keys was sent to PUT /v1/tool-endpoints
invalid_json 400 The body is not a JSON object
invalid_request 400 A field is missing or has the wrong type, or user, context or page holds a field that does not exist. In that last case the message lists the allowed fields. Unknown top-level fields are ignored.
not_found 404 No such route under /v1
rate_limited 429 See rate limits
internal_error 500 Median failed to handle the request

Messages and uploads

Code Status When
invalid_session 400 The session is not 8 to 128 characters after trimming
empty_message 400 No body and no attachments
message_too_long 400 The body is over 4,000 characters
too_many_attachments 400 More than 6 attachments
attachment_missing 400 An attachment id is not a file from POST /v1/uploads
attachment_wrong_type 400 The file is HTML, XHTML, SVG or XSLT
empty_file 400 The upload body is empty
file_too_big 400 The upload is over 20 MB

Keys, webhooks and tool endpoints

Code Status When
too_many_keys 400 The organization holds 10 Median keys
invalid_name 400 A key name is over 40 characters, or an agent name is not 2 to 40 characters
missing_median_key 400 Adding a webhook or tool endpoint before any Median key exists
invalid_url 400 The URL breaks the endpoint rules. The message says which.
no_events 400 A webhook endpoint with no events
too_many_endpoints 400 The organization holds 10 webhook endpoints
too_many_tool_endpoints 400 The organization holds 10 tool endpoints
no_endpoint 400 A sync with no url and no tool endpoint connected
endpoint_required 400 A sync with no url while several endpoints are connected
endpoint_not_found 404 A sync url that matches no connected endpoint
invalid_input 400 A tool’s input does not match its schema
too_many_running 400 Three tools are already running in the conversation
conversation_archived 400 Running a tool in an archived conversation

Organization and members

Code Status When
invalid_slug 400 The slug is not 3 to 32 lowercase letters, numbers and single dashes, or it is reserved
slug_taken 400 Another organization has the slug
too_many_organizations 400 You are in 50 organizations
invalid_email 400 The invitation address is not an email address
too_many_invites 400 100 invitations are pending
cannot_grant 400 Only an owner can invite or make an owner
cannot_manage_self 400 Changing your own role or removing yourself
outranked 400 The member ranks at or above you and you are not an owner
last_owner 400 Demoting or removing the only owner
member_not_found 404 The user is not in the organization

Inbox, knowledge, signals and tasks

Code Status When
bad_snooze_time 400 The snooze time is invalid, under a minute away, or over a year away
not_archived 400 Deleting a conversation that is not archived
customer_unreachable 400 Reaching out to a customer who never opened the widget and has no email address
invalid_feedback 400 A feedback note over 2,000 characters
title_missing 400 A knowledge document with an empty title
body_missing 400 A knowledge document with an empty body
body_too_large 400 A knowledge document over 900,000 bytes
doc_is_synced 400 Editing a document synced from a repository or imported from Notion
folder_name_missing 400 A folder with an empty name
folder_too_deep 400 A fourth folder level
folder_cycle 400 Moving a folder into itself
order_invalid 400 The move destination no longer exists
bad_url 400 The crawl address is not a site address
upgrade_required 400 Starting a crawl without a paid plan
too_many_crawls 400 Three crawls are running
signal_empty 400 A signal with an empty title
title_required 400 A task with an empty title
key_prefix_invalid 400 A task key prefix that is not up to 8 letters or numbers starting with a letter
not_a_member 400 A task assignee who is not in the organization, or switching to an organization you are not in
invalid_query 400 An explorer query names a field or measure its dataset lacks
invalid_personality 400 Agent personality over 2,000 characters

Integrations

Code Status When
slack_not_connected, discord_not_connected, linear_not_connected, github_not_connected 400 Connect the app in the dashboard first. With several GitHub accounts connected, github_not_connected also means none of them owns the repository.
channel_not_found, role_not_found, team_not_found 404 No Slack or Discord channel, Discord role, or Linear team by that name. The message lists what exists.
mirror_bot_offline, mirror_bot_timeout, mirror_act_failed, discord_bot_offline, discord_bot_timeout, discord_act_failed 400 The bot could not look up Slack or Discord channels or roles. Try again.
repo_name_invalid 400 The repository is not written as owner/repo
repo_already_connected 400 The repository is already connected
bad_docs_url 400 The published address of a repository is not a valid URL
address_private 400 The published address is not on the public internet
repo_not_connected 400 The repository is not connected
commit_repo_not_found 404 The repository’s commits are not read
issue_repo_missing 400 Changing the issue repository’s settings without naming a repository when none is set
address_taken 400 The support email address belongs to another organization
linear_failed 400 Median could not read your Linear teams. The message says why.

Not found

The 404 codes are conversation_not_found, customer_not_found, fact_not_found, knowledge_doc_not_found, knowledge_folder_not_found, suggestion_not_found, signal_not_found, commit_not_found, approval_not_found, invite_not_found, endpoint_not_found, tool_not_found, key_not_found, org_not_found, task_not_found and log_not_found, and any other code ending in _not_found, such as member_not_found, channel_not_found, role_not_found, team_not_found, repo_not_found and commit_repo_not_found. An id from another organization reads as not found.

Conflicts

Code Status When
already_a_member 409 The invited address is already in the organization
already_invited 409 An invitation to that address is pending
approval_settled 409 The tool call was already decided
approval_expired 409 The tool call expired, or its conversation ended
suggestion_settled 409 The suggestion was already approved or dismissed
suggestion_stale 409 The document changed after the suggestion was written
suggestion_gone 409 The suggestion’s document was deleted
signal_exists 409 A signal with the same title or alias exists
crawl_running 409 That site is already being crawled
already_a_task 409 The signal is already on the task board
not_a_request 409 Declining a card that is not in Requests

Rate limits

Limits apply per organization. Every key, OAuth token, MCP session and assistant action in the organization draws from one allowance. Each class is a token bucket with a sustained rate per minute and a burst that can be spent at once.

Tier (tier) Plan Reads a minute Writes a minute Uploads a minute
explore Explore 120, burst 20 30, burst 10 5, burst 2
standard Standard 6,000, burst 1,000 1,200, burst 300 300, burst 100
higher Pro, or Standard with the API limits add-on 12,000, burst 2,000 2,400, burst 600 600, burst 200
highest Pro with the API limits add-on 24,000, burst 4,000 4,800, burst 1,200 1,200, burst 400
unlimited Unlimited API add-on No fixed limit. Fair use applies.

Plan and add-on prices are in Plans.

What counts

Class Requests
Read Every GET, plus POST /v1/analytics/explore and POST /v1/analytics/records
Upload POST /v1/uploads
Write Every other POST, PUT, PATCH and DELETE
  • Each median.* call inside an MCP median_run counts as one request of its class.
  • The assistant’s actions count the same way.
  • A request is charged before it runs, so a request that fails afterwards still counts.
  • POST /v1/organizations and POST /v1/me/organization always draw from a per-person allowance. GET /v1/me does too while the token has no organization, or its person has left it. The allowance is 600 reads a minute with a burst of 100, and 120 writes a minute with a burst of 30.

When you hit a limit

HTTP/1.1 429 Too Many Requests
retry-after: 3
content-type: application/json

{"error":{"code":"rate_limited","message":"Your organization's API allowance is temporarily full. Please retry shortly."}}
  • Retry-After is in whole seconds, at least 1.
  • Median can restrict an organization under fair use. The response is the same 429 rate_limited, with "reason": "fair_use" in error and “API access is temporarily limited to protect shared capacity. Please retry shortly.” or “API access is temporarily limited because unusual automated traffic was detected. Contact support for review.”
  • Each refusal of the organization’s allowance is recorded in Logs as API limit reached.

Read your limits

curl https://api.median.sh/v1/billing/limits \
  -H "Authorization: Bearer $MEDIAN_KEY"
{
  "tier": "standard",
  "version": "2026-09-22",
  "limits": {
    "read": { "perMinute": 6000, "burst": 1000 },
    "write": { "perMinute": 1200, "burst": 300 },
    "upload": { "perMinute": 300, "burst": 100 }
  }
}

limits is null on unlimited. Any member can call it. The CLI is median billing limits. The dashboard shows the same numbers in Settings → Billing on the API limits row.

Other limits

These are separate buckets. A REST call that meets one is still charged to the tier as well.

What Limit Counted per
Manifest syncs from POST /v1/tool-endpoints/sync, the Sync button, and one per endpoint from POST /v1/tools/sync 60 an hour, burst 10 Organization
Invitation emails, sent or resent 30 an hour, burst 10 Organization
MCP client registration, POST /oauth/register 300 an hour, burst 50 Caller IP address
Device login start, POST /oauth/device_authorization 300 an hour, burst 50 Caller IP address
  • Adding a tool endpoint or changing its URL is not counted as a sync.
  • Registration and device login also share a ceiling of 6,000 an hour across all callers.
  • The REST buckets refuse with 429 rate_limited and “Too many requests. Wait a moment and try again.” The OAuth routes refuse with 429 and the OAuth error slow_down.

Size limits

Limit Value Past it
Message body 4,000 characters after trimming message_too_long
Attachments 6 per message too_many_attachments
Upload 20 MB per file file_too_big
Upload file name 200 characters Cut to fit
Attachment types text/html, application/xhtml+xml, image/svg+xml, text/xsl and application/xslt+xml upload, but are refused at send attachment_wrong_type
Session token 8 to 128 characters after trimming invalid_session
user.name 80 characters Cut to fit
user.email 320 characters Cut to fit
user.avatarUrl An https URL, up to 512 characters Dropped
user.metadata 16 entries. Keys and values up to 200 characters. Extra entries dropped, text cut
Thread history 200 messages across the session’s 10 most recently started conversations. The most recently active fill it first. Older messages left out
Knowledge document 900,000 bytes body_too_large
Feedback note 2,000 characters invalid_feedback
Median keys 10 per organization too_many_keys
Webhook endpoints 10 per organization, URLs up to 512 characters too_many_endpoints
Tool endpoints 10 per organization, URLs up to 512 characters too_many_tool_endpoints
Pending invitations 100 per organization too_many_invites
Organizations 50 per person too_many_organizations
Crawls running 3 per organization too_many_crawls
Tools running 3 per conversation too_many_running
Knowledge folders 3 levels deep folder_too_deep

Was this page helpful?