Skip to content

Rate limits

The MK.IO APIs limit request rates to protect platform stability. Most integrations never reach those limits during normal use. Background workers, tight polling loops, and bulk scans are the patterns that approach them, so they are worth designing carefully.

When you exceed a limit, the API responds with 429 Too Many Requests. The body uses the same standard error shape as any other failure:

{
"error": {
"code": "<error_code>",
"detail": "<error_message>",
"extraDetail": {}
},
"status": 429,
"ref": "<request_reference>"
}

Record the ref value before you retry. If a 429 is unexpected for your request volume, ref is the fastest way to identify the request later. See Error handling for the full error model.

Most endpoints enforce these limits:

Request typeLimit
GET2,000 per minute
DELETE, PATCH, POST, PUT1,000 per minute

Some endpoints, including authentication flows, apply stricter limits.

Limits are scoped to the resource the path targets. Project-scoped endpoints (those with /projects/{project_name}/ in the path) count per project. Endpoints without a project in the path count per organization. This matters for multi-project automation: a process that fans out across projects behaves differently from one that repeatedly targets a single project.

Aggressive polling is the usual cause. Polling 50 jobs once per second is 3,000 GET requests per minute against one project, which exceeds the read limit before any list or detail requests are counted. This is why event-driven workflows scale better than timer-based status checks.

Where an operation has webhook coverage, subscribe instead of polling. Use MediaKind.JobFinished rather than polling a job, and use channel state events for live workflows. One event delivery replaces many repeated reads. See Webhooks.

Use $filter, $label, $label_key, and $top so you request only what you need:

Terminal window
curl -X GET "https://app.mk.io/api/v1/projects/<PROJECT_NAME>/media/assets?\$top=20&\$label=studio=paravalley" \
-H "Authorization: Bearer <YOUR_TOKEN>"

This returns far fewer items than listing everything and filtering locally. See Pagination and filtering.

When you scan a large collection, continue from your last $skiptoken rather than rerunning the first page from the top.

When you retry after a temporary failure, add a delay between attempts rather than retrying immediately. Even a fixed delay helps prevent a brief problem from becoming a sustained rate-limit issue.

A design pattern for long-running workflows

Section titled “A design pattern for long-running workflows”
  1. Create the resource.
  2. If webhook events exist for it, wait for the event.
  3. If you must poll, poll the narrowest endpoint available, such as /state.
  4. Add a delay between attempts.
  5. Stop polling once the resource reaches the state you need.

This keeps request volume predictable and usually improves end-to-end latency.

If a normal workflow returns 429 consistently after you have narrowed requests and reduced polling, collect the project or organization context, the endpoint being called, the approximate request rate, and the ref values from the failing responses. That gives you enough to investigate the traffic pattern rather than guess.

© 2026 MediaKind. All rights reserved.