Skip to content

Public API

The REST API at /api/v1: endpoints, authentication, errors and rate limits. Every path below is relative to the base URL shown on your API keys page, for example https://api.example.com/api/v1.

<!-- source: services/api/src/public/routes.ts (V1_ROUTES), services/api/src/public/mount.ts -->

Availability

ConditionResult
public-api.enabled flag off (the default)every /api/v1 route, including openapi.json, returns 404
flag on for the key's user or organizationroutes respond as listed below

Authentication

ItemValue
HeaderAuthorization: Bearer <key>
Key formatstarts with mrk_; shown once at creation
Key scopeone organization: the one you were in when you created it
Acts asthe key's owner (a person or a service account), with that owner's roles
Limited keysmay only call endpoints whose required permission is in the key's allowlist
No auth neededGET /openapi.json

Endpoints

Method and pathDoesRequired permissionMCP tool
GET /mereturns the key's userId and organizationIdnonemonark_whoami
GET /modelslists the organization's data models (paginated)data-models.read-schemamonark_list_models
GET /models/{key}returns one data model by its keydata-models.read-schemamonark_get_model
GET /models/{key}/fieldslists a model's fieldsdata-models.read-schemamonark_list_model_fields
GET /models/{key}/recordslists a model's records (paginated)data-models.record-readmonark_list_records
POST /models/{key}/recordscreates a recorddata-models.record-writemonark_create_record
GET /records/{id}returns one recorddata-models.record-readmonark_get_record
PATCH /records/{id}updates a record; only the fields you send changedata-models.record-writemonark_update_record
DELETE /records/{id}soft-deletes a record and returns { "ok": true }data-models.record-deletemonark_delete_record
GET /openapi.jsonthe OpenAPI 3 document for every endpoint abovenonenone

Projects, tasks and every other kind of entity are data model records; there is no endpoint per feature.

Parameters

EndpointParameterInTypeNotes
GET /models, GET .../recordslimitqueryinteger, 1 to 100defaults to 25
GET /models, GET .../recordscursorquerystringthe nextCursor from the previous page
GET /models, GET .../recordssearchquerystring, up to 120 characterson records, matches the title or slug, ignoring case
POST .../recordsdatabodyobject, field key → valuerequired
POST .../records, PATCH /records/{id}slugbodystring, 1 to 60 characters, or nulloptional
PATCH /records/{id}databodyobject, field key → valueoptional; omitted fields keep their value
DELETE /records/{id}hardquerybooleantrue purges the record permanently

Paginated responses

FieldTypeMeaning
itemsarraythe rows on this page
nextCursorstring or nullpass as cursor for the next page; null on the last
totalintegerrows matching the same filter, across all pages

OpenAPI extensions

ExtensionOnValue
x-required-permissionoperationthe permission the key's owner needs
x-mcp-tooloperation{ name, description } of the MCP tool built from the route

Errors

Every error body is { "error": { "code": "<code>", "message": "<text>" } }.

StatuscodeWhen
400validation_errora query or body field fails validation; the message names each field
401unauthorizedthe header is missing, or the key is invalid, expired or revoked
403forbiddena limited key wasn't granted the endpoint's permission
403variesthe key's owner lacks the permission
404not_foundthe public API is off, or the route doesn't exist
404variesthe model or record doesn't exist or isn't visible to the key
409variesthe change conflicts with the record's current state
429rate_limitedthe key's rate limit is used up
500internalunexpected server error

Rate limits

Each key has its own token bucket, shared across every API server.

ItemValue
Sustained rate5 requests per second (PUBLIC_API_RATE_PER_SECOND)
Burst20 requests (PUBLIC_API_BURST)
X-RateLimit-Limiton every authenticated response: the bucket size
X-RateLimit-Remainingon every authenticated response: requests left right now
Retry-Afteron a 429: seconds to wait before retrying

Related