Kumo.io

Docs Reference

API

API conventions

Every Kumo.io API response is JSON in one of three shapes, a single object, a page of objects, or an error, and every list pages the same way.

Applies to: BothPlan: Team

Requests

  • Base URL and version. Paths start with /v1, and almost all of them are scoped to your account: /v1/accounts/<account-id>/…. For the base URL and the Authorization header, see How do I authenticate to the API?
  • JSON. Send request bodies as JSON with Content-Type: application/json. A body that isn't valid JSON is refused with 400 BAD_REQUEST ("malformed or unsupported request body").
  • Size. A request body can be up to 1 MiB. Workspace imports can be up to 32 MiB. A larger body is refused with 413 PAYLOAD_TOO_LARGE.
  • IDs. Objects are identified by opaque IDs. Use them as given; a malformed ID is treated as not found.

A single object

A request that returns one object wraps it in data:

{
  "data": { "id": "…", "name": "Production" }
}

Some responses add a meta object alongside data with extra information about the response. meta is left out when there is nothing to say.

A page of objects

A request that returns a list returns one page at a time:

{
  "data": [ { "id": "…" }, { "id": "…" } ],
  "page": { "limit": 100, "nextCursor": "c1:…" },
  "meta": { "totalMatching": 240 }
}
Field Meaning
dataThe objects on this page.
page.limitThe page size actually applied.
page.nextCursorPass this back to get the next page. null means this is the last page.
meta.totalMatchingOn lists that report it, how many objects match in total.

Paging through a list

Two query parameters control paging:

Parameter Meaning
limitPage size. Default 100, maximum 500. A larger value is reduced to 500 without an error, and page.limit shows the value used. A value of 0, a negative number or a non-number is refused.
cursorThe page.nextCursor from the previous page. Leave it out for the first page.
GET /v1/accounts/<account-id>/workspaces?limit=200
GET /v1/accounts/<account-id>/workspaces?limit=200&cursor=<page.nextCursor>

Keep requesting until page.nextCursor is null. Treat cursors as opaque: don't build or change them. An invalid limit or cursor returns 400 BAD_REQUEST_PAGINATION.

A few list endpoints use a different default or maximum page size; the response's page.limit always tells you what was applied.

Errors

Any response that isn't a success has the same shape:

{
  "error": {
    "code": "NOT_FOUND",
    "message": "workspace not found",
    "status": 404,
    "requestId": "req-1a"
  }
}
Field Meaning
codeA stable, machine-readable code. Branch on this, not on the message.
messageA human-readable explanation. It can change; don't parse it.
statusThe HTTP status, repeated in the body.
requestIdIdentifies the request. Include it when you contact support.
detailsSometimes present, with extra fields for that code, for example featureKey on FEATURE_NOT_ENTITLED.

Ignore fields you don't recognise: new ones may be added.

Error codes

Status Code When
400BAD_REQUESTThe request is malformed or fails validation.
400BAD_REQUEST_PAGINATIONlimit or cursor is invalid.
400BAD_REQUEST_AS_OFA point-in-time (asOf) value is invalid.
400INVARIANT_VIOLATIONThe request would break a rule, for example an invalid combination of values.
401UNAUTHENTICATEDNo valid token. See API authentication.
403AUTHORIZATION_DENIEDYour roles don't allow this, or the path names another account.
403FEATURE_NOT_ENTITLEDYour plan doesn't include this feature.
403LICENSE_DENIEDThe self-hosted installation isn't licensed.
404NOT_FOUNDThe object or path doesn't exist in your account.
409CONFLICTThe request conflicts with the object's current state.
409SYNC_RUN_IN_PROGRESSThe workspace already has a sync running.
409WORKSPACE_ARCHIVEDThe workspace is archived; restore it first.
409JOB_STATE_CONFLICTThe job can't make that change from its current state.
409REPORT_STATE_CONFLICTThe report run can't make that change from its current state.
413PAYLOAD_TOO_LARGEThe request body is too large.
429RATE_LIMITEDToo many requests, too many failed logins, or a sync started sooner than your plan allows.
429QUOTA_EXCEEDEDYou've reached a plan limit. See plans and limits.
501NOT_IMPLEMENTEDThis operation isn't available on this deployment.
503BILLING_UNAVAILABLEBilling is temporarily unavailable.
500INTERNAL_ERRORSomething went wrong on Kumo.io's side. The message is always "Internal server error".

Rate limits and retries

  • The API allows 1,000 requests per 60 seconds per IP address. Over that, it returns 429 RATE_LIMITED with a Retry-After header giving the seconds to wait.
  • A sync started too soon also returns 429 RATE_LIMITED, without a Retry-After header; the message says how long to wait ("retry in Ns").
  • 429 QUOTA_EXCEEDED doesn't clear by waiting, except for monthly limits at the start of the next month. Free capacity or change plan instead.
  • Retry 500 and 503 with a backoff. Don't retry 4xx errors other than 429 without changing the request.

Long-running requests

Requests that start work in the background return 202 Accepted, usually with a Location header that points at the status of that work. See How do I track a long-running request?

Reference

Every endpoint is in the API reference. Open a route there to see its query parameters, its request body and its success response, field by field. The shapes are generated from the server's own types, so they change when the API changes. Files and event streams are listed by media type, and errors always use the error shape above.

See your own cloud in Kumo.io. Read-only access. Nothing in your account changes.

Free Trial