Skip to content

API Reference

This page is a hand-written conceptual overview. The Mako API is a RESTful API built with Hono. All endpoints are prefixed with /api.

Two authentication methods:

  1. Session cookies — For the web app (set automatically on login)
  2. API keys — For programmatic access (prefix: revops_)
Terminal window
# API key authentication
Authorization: Bearer revops_YOUR_API_KEY

Create API keys in Workspace settings → API Keys. The same page surfaces your Workspace ID (the value to substitute for :wid / :workspaceId / WORKSPACE_ID below) with a copy button.

MethodEndpointDescription
POST/api/auth/registerCreate account (email/password)
POST/api/auth/loginLogin, returns session cookie
GET/api/auth/meGet current user session
POST/api/auth/logoutEnd session
GET/api/auth/googleGoogle OAuth redirect
GET/api/auth/githubGitHub OAuth redirect
MethodEndpointDescription
GET/api/workspacesList user’s workspaces
POST/api/workspacesCreate a workspace
GET/api/workspaces/:idGet workspace details
GET/api/workspaces/:id/settings/limitsGet refresh concurrency limits (dashboardRefreshConcurrency, appBindingRefreshConcurrency; defaults 2, clamped to the per-workspace max)
PUT/api/workspaces/:id/settings/limitsUpdate refresh concurrency limits

These endpoints manage connections to user databases (PostgreSQL, MySQL, MongoDB, BigQuery, ClickHouse, Redshift, SQLite, Cloudflare D1/KV) that Mako queries on the user’s behalf. For SaaS connectors (Stripe, Close, PostHog, GraphQL, REST, BigQuery sync), see SaaS Connectors.

MethodEndpointDescription
GET/api/workspaces/:wid/databasesList database connections
POST/api/workspaces/:wid/databasesAdd a database connection
GET/api/workspaces/:wid/databases/:idGet a single database connection (passwords masked)
PUT/api/workspaces/:wid/databases/:idUpdate a database connection
DELETE/api/workspaces/:wid/databases/:idRemove a database connection
POST/api/workspaces/:wid/databases/test-connectionTest a candidate connection without saving
POST/api/workspaces/:wid/databases/:id/testTest an existing connection
POST/api/workspaces/:wid/databases/demoProvision the demo Chinook database (onboarding)

Create and update accept an optional verifyBeforeSave: true flag: the connection is tested before persisting, a failing test refuses the write with a structured connection_test_failed result, and a passing test stamps lastConnectedAt. Without the flag the legacy save-without-testing behavior is kept for programmatic callers. The app UI always sets it (with a “Save anyways” escape hatch).

For MongoDB connections, collection and view management is exposed under the same workspace-scoped database routes. The legacy unauthenticated /api/database/* routes were removed in #408 — all callers must use the endpoints below.

MethodEndpointDescription
GET/api/workspaces/:wid/databases/:id/collectionsList collections
POST/api/workspaces/:wid/databases/:id/collectionsCreate a collection
GET/api/workspaces/:wid/databases/:id/collections/:nameGet collection stats and indexes
GET/api/workspaces/:wid/databases/:id/collections/:name/infoGet collection metadata only
DELETE/api/workspaces/:wid/databases/:id/collections/:nameDrop a collection
GET/api/workspaces/:wid/databases/:id/viewsList views
POST/api/workspaces/:wid/databases/:id/viewsCreate a view (viewOn, pipeline)
GET/api/workspaces/:wid/databases/:id/views/:name/infoGet view metadata
DELETE/api/workspaces/:wid/databases/:id/views/:nameDrop a view

Session cookie or Authorization: Bearer revops_* API key required. Use the database connection ID from GET /api/workspaces/:wid/databases.

MethodEndpointDescription
POST/api/workspaces/:wid/databases/:databaseId/executeRun a query against a specific connection (body.query)
POST/api/workspaces/:wid/executeExecute with query or queryDefinition; supports pagination via body.pagination
POST/api/workspaces/:wid/execute/exportStream results as format = arrow, parquet, ndjson, or csv
POST/api/workspaces/:wid/execute/cancelCancel an in-flight query by executionId
MethodEndpointDescription
GET/api/workspaces/:wid/consoles/listList all consoles
GET/api/workspaces/:wid/consoles/:id/detailsGet console details + code
POST/api/workspaces/:wid/consoles/:id/executeExecute a saved console
GET/api/workspaces/:wid/consoles/:id/versionsList version history (paginated, newest first)
GET/api/workspaces/:wid/consoles/:id/versions/:versionGet a specific version snapshot
POST/api/workspaces/:wid/consoles/:id/versions/:version/restoreRestore the console to a past version
PUT/api/workspaces/:wid/consoles/:id/scheduleCreate or update a saved console schedule (admin only)
DELETE/api/workspaces/:wid/consoles/:id/scheduleRemove a saved console schedule (admin only)
POST/api/workspaces/:wid/consoles/:id/schedule/runTrigger a scheduled console immediately (admin only)
GET/api/workspaces/:wid/consoles/:id/schedule/runsList scheduled run history (admin only)
GET/api/workspaces/:wid/consoles/:id/executionsList recent query executions with trigger source (?limit=, ~90-day retention)
GET/api/workspaces/:wid/scheduled-queriesList scheduled consoles in the workspace (admin only)
GET/api/workspaces/:wid/consoles/:id/collaboratorsList per-user collaborators
POST/api/workspaces/:wid/consoles/:id/collaboratorsAdd/update a collaborator ({ userId, role }; owner/admin only)
PATCH/api/workspaces/:wid/consoles/:id/collaborators/:userIdChange a collaborator’s role (owner/admin only)
DELETE/api/workspaces/:wid/consoles/:id/collaborators/:userIdRemove a collaborator (owner/admin only)
PATCH/api/workspaces/:wid/consoles/:id/sharingUpdate general access ({ access, workspaceRole }; owner/admin only)

See Console for full API documentation with examples. Scheduled query endpoints require workspace admin access and use the same session/API-key authentication as other workspace endpoints. Version history is covered under Version History.

A connector is code (Stripe, Close, PostHog, a workspace-authored ws: connector, …); a source connection is a credential configured with one — what a flow reads from. These routes manage source connections. The primary path is /connections/sources; /connectors is the pre-2026-09 alias and still works. Database connections are under Database Connections. See SaaS Connectors.

MethodEndpointDescription
GET/api/workspaces/:wid/connections/sourcesList source connections (credentials masked)
POST/api/workspaces/:wid/connections/sourcesAdd a source connection (secret fields encrypted per the connector’s schema)
GET/api/workspaces/:wid/connections/sources/:idGet one source connection
PUT/api/workspaces/:wid/connections/sources/:idUpdate a source connection
DELETE/api/workspaces/:wid/connections/sources/:idRemove a source connection
POST/api/workspaces/:wid/connections/sources/:id/testTest the credential
POST/api/workspaces/:wid/connections/sources/:id/probeProbe live: test the credential and read one bounded page of an entity
GET/api/workspaces/:wid/connections/sources/:id/entitiesEntities the connection’s connector offers
PATCH/api/workspaces/:wid/connections/sources/:id/enableEnable or disable

The same methods are also served at /api/workspaces/:wid/connectors (and /connectors/:id/…) as a deprecated alias.

POST …/connections/sources/:id/probe (or the legacy POST …/connectors/:id/probe) takes an optional JSON body — entity (omit to test the credential only), limit (1–200, default 20), fields (top-level fields to keep), since (ISO 8601 instant, honoured where the connector can) — and answers { success, data: { connection, check, entity?, durationMs } }. entity carries records, schema, count, received, truncated, hasMore and logs. One API page is read and nothing is written; credential values are scrubbed from every string in the result. Errors carry a code (invalid_input, not_found, unknown_entity, timeout, connector_unavailable). Requires a browser session or a legacy (unscoped) API key: scoped MCP keys stay MCP-only, and reach the same probe through the probe_connection tool.

MethodEndpointDescription
POST/api/workspaces/:wid/flowsCreate/trigger a flow
GET/api/workspaces/:wid/flows/:idGet flow status
GET/api/workspaces/:wid/flows/:id/sync-cdc/statusGet CDC stream status
GET/api/workspaces/:wid/flows/:id/sync-cdc/schema-healthCompare live destination column types to the connector schema (BigQuery; detects drift)
GET/api/workspaces/:wid/flows/:id/sync-cdc/destination-countsBatched row counts per entity in the destination

Returns a map of CDC entity name to destination row count. Mako batches BigQuery and PostgreSQL counts into one metadata query and may return 0 for configured entities whose destination table does not exist yet.

{
"success": true,
"data": {
"contacts": 125000,
"organizations": 8421,
"opportunities": 0
}
}
{
"success": true,
"data": {
"hasDrift": true,
"entities": [
{
"entity": "customers",
"hasDrift": true,
"columns": [
{ "column": "created_at", "liveType": "STRING", "expectedType": "TIMESTAMP", "status": "drift" },
{ "column": "id", "liveType": "STRING", "expectedType": "STRING", "status": "match" }
]
}
]
}
}

Accepts an optional ?entity=<name> query parameter to scope the check to a single entity. Drift is auto-corrected on the next CDC merge — see Schema Evolution.

Email, webhook, and Slack notifications for terminal scheduled-query and flow runs. See Notifications for the full guide and webhook payload shape.

MethodEndpointDescription
GET/api/workspaces/:wid/notification-rulesList rules. Query: resourceType, resourceId.
GET/api/workspaces/:wid/notification-rules/deliveriesList recent deliveries. Query: resourceType, resourceId, optional limit.
POST/api/workspaces/:wid/notification-rulesCreate a rule. Admin only.
PATCH/api/workspaces/:wid/notification-rules/:ruleIdUpdate triggers / channel / enabled flag. Admin only.
DELETE/api/workspaces/:wid/notification-rules/:ruleIdDelete a rule. Admin only.
POST/api/workspaces/:wid/notification-rules/testSend a test notification (saved rule by ruleId or ad-hoc channel).

Webhook deliveries include an X-Mako-Signature HMAC-SHA256 header. The signing secret is returned once as signingSecretOnce on create or rotation and is not retrievable later.

The Chat API enables programmatic access to Mako’s AI agent with streaming responses.

MethodEndpointDescription
POST/api/agent/chatSend messages, receive streaming AI response
GET/api/agent/modelsList available AI models
Terminal window
curl -X POST https://app.mako.ai/api/agent/chat \
-H "Authorization: Bearer revops_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "Show me top 10 customers by revenue"}],
"chatId": "optional-session-id",
"workspaceId": "your-workspace-id",
"model": "claude-sonnet-4-20250514"
}'

The response is a Server-Sent Events (SSE) stream:

Event TypeDescription
startStream started, contains messageId
text-deltaIncremental text chunk from assistant
tool-input-availableTool call with full input (e.g., SQL query)
tool-resultTool execution result (e.g., query results)
finishStream complete, contains finishReason
StatusDescription
400Missing or invalid messages, chatId, or workspaceId
401Unauthorized (missing or invalid API key)
403API key not authorized for the workspace
404Agent not found (invalid agentId)
MethodEndpointDescription
GET/api/workspaces/:wid/chatsList chat sessions
POST/api/workspaces/:wid/chatsCreate a new chat
GET/api/workspaces/:wid/chats/:idGet chat details
PUT/api/workspaces/:wid/chats/:idUpdate chat title
DELETE/api/workspaces/:wid/chats/:idDelete a chat
GET/api/workspaces/:wid/chat-images/:attachmentIdFetch a stored chat image attachment (authenticated proxy)

Workspace skills — named playbooks the agent can author and load on demand. See Skills for the conceptual model.

MethodEndpointDescription
GET/api/workspaces/:wid/skillsList every skill in the workspace
GET/api/workspaces/:wid/skills/:idGet a single skill with full body
PUT/api/workspaces/:wid/skills/:idEdit loadWhen, body, or entities
POST/api/workspaces/:wid/skills/:id/suppressToggle the suppressed flag
DELETE/api/workspaces/:wid/skills/:idPermanently delete a skill

All endpoints require authentication and workspace access. Agent-side CRUD is available through the save_skill, delete_skill, load_skill, and search_skills tools — see AI Agent.

{
"success": true,
"skill": {
"id": "6620...",
"name": "mrr_walkthrough_fr",
"loadWhen": "Building a sales report or answering questions about MRR in France",
"body": "...",
"entities": ["mrr", "france", "subscriptions"],
"suppressed": false,
"useCount": 12,
"createdBy": "6612...",
"createdAt": "2026-04-23T12:36:00.000Z",
"updatedAt": "2026-04-23T12:36:00.000Z"
}
}
MethodEndpointDescription
GET/api/workspaces/:wid/dashboardsList dashboards
POST/api/workspaces/:wid/dashboardsCreate a dashboard
GET/api/workspaces/:wid/dashboards/:didGet dashboard details
PUT/api/workspaces/:wid/dashboards/:didUpdate dashboard
DELETE/api/workspaces/:wid/dashboards/:didDelete dashboard
POST/api/workspaces/:wid/dashboards/:did/duplicateDuplicate a dashboard
GET/api/workspaces/:wid/dashboards/:did/versionsList dashboard version history
GET/api/workspaces/:wid/dashboards/:did/versions/:versionGet a specific dashboard version
POST/api/workspaces/:wid/dashboards/:did/versions/:version/restoreRestore dashboard to a past version
POST/api/workspaces/:wid/dashboards/:did/version-commentAI-suggested commit message for pending changes
GET/api/workspaces/:wid/dashboards/:did/collaboratorsList per-user collaborators
POST/api/workspaces/:wid/dashboards/:did/collaboratorsAdd/update a collaborator ({ userId, role }, role viewer|editor; owner/admin only)
PATCH/api/workspaces/:wid/dashboards/:did/collaborators/:userIdChange a collaborator’s role (owner/admin only)
DELETE/api/workspaces/:wid/dashboards/:did/collaborators/:userIdRemove a collaborator (owner/admin only)
PATCH/api/workspaces/:wid/dashboards/:did/sharingUpdate general access ({ access, workspaceRole }; owner/admin only)
POST/api/workspaces/:wid/dashboards/:did/public-shareEnable/create a public link ({ password? }; owner/admin only)
GET/api/workspaces/:wid/dashboards/:did/public-share/passwordReveal the public-link password (owner/admin only)
PATCH/api/workspaces/:wid/dashboards/:did/public-shareUpdate password / rotate token / rename slug (owner/admin only)
DELETE/api/workspaces/:wid/dashboards/:did/public-shareDisable the public link (owner/admin only)
MethodEndpointDescription
GET/api/workspaces/:wid/dashboard-foldersList dashboard folders
POST/api/workspaces/:wid/dashboard-foldersCreate a folder
PUT/api/workspaces/:wid/dashboard-folders/:fidUpdate a folder
DELETE/api/workspaces/:wid/dashboard-folders/:fidDelete a folder
MethodEndpointDescription
GET/api/workspaces/:wid/dashboards/:did/materialization/statusGet materialization status for all data sources
POST/api/workspaces/:wid/dashboards/:did/materialization/triggerTrigger materialization for a data source
POST/api/workspaces/:wid/dashboards/:did/materialization/trigger-allTrigger materialization for all data sources
GET/api/workspaces/:wid/dashboards/:did/materialization/stream/:dataSourceIdStream Parquet artifact (supports range requests)

Git-backed React apps built inside the workspace (Apps). Private apps are owner-only — admins and API keys cannot access another member’s private app. The workspace repo itself is served over git HTTP at /api/apps-git/:workspaceId.git (scoped git token).

MethodEndpointDescription
GET/api/workspaces/:wid/appsList app projects visible to the caller
POST/api/workspaces/:wid/appsCreate an app (scaffolds a Vite + React project)
GET/api/workspaces/:wid/apps/:idGet an app project (metadata, branch, publish state)
DELETE/api/workspaces/:wid/apps/:idDelete an app
GET/api/workspaces/:wid/apps/:id/files / …/fileList / read files on the working branch
PUT/api/workspaces/:wid/apps/:id/fileWrite a file to the working branch
POST/api/workspaces/:wid/apps/:id/execRun a shell command in the app’s sandbox
GET/api/workspaces/:wid/apps/:id/status / …/history / …/branchesWorking-tree status, commit history, branches
POST/api/workspaces/:wid/apps/:id/commit / …/merge / …/checkout / …/discardGit operations on the working branch
GET/api/workspaces/:wid/apps/:id/bindingsList data bindings (bindings/*.sql)
POST/api/workspaces/:wid/apps/:id/bindings/:name/materializeBuild/rebuild a binding’s Parquet artifact
GET/api/workspaces/:wid/apps/:id/bindings/:name/artifactStream the materialized Parquet artifact
POST/api/workspaces/:wid/apps/:id/publish / …/rollbackBuild & publish a main commit / repoint the deployment
POST/api/workspaces/:wid/apps/:id/preview / …/dev-previewPublished-build preview / live dev server preview
POST/api/workspaces/:wid/apps/:id/public-shareManage the anonymous public link (also PATCH/DELETE)
GET/api/workspaces/:wid/apps/:id/sandboxSandbox status (also POST …/sandbox/recycle)

Notebook CRUD, kernel sessions, executions, versions, presence, and the kernel’s read-only data plane live under /api/workspaces/:workspaceId/notebooks and …/notebook/*. See Notebooks for the route table and the OpenAPI spec for full schemas.

Token-gated, read-only endpoints for published dashboard/app links. These are intentionally unauthenticated (no session or API key) and serve only materialized snapshots.

MethodEndpointDescription
GET/api/share/:tokenGet public-share metadata (title, whether a password is required)
POST/api/share/:token/unlockExchange a password for access to a protected link
GET/api/share/:token/contentGet the shared resource’s materialized content
GET/api/share/:token/artifacts/:artifactIdStream a materialized Parquet artifact (supports range requests)
POST/api/share/:token/refreshThrottled anonymous re-materialization of the snapshot
MethodEndpointDescription
POST/api/inngestInngest webhook handler (internal)

Subscription management endpoints. All require workspace membership. When BILLING_ENABLED is false (self-hosted default), all endpoints return { "billingEnabled": false }.

MethodEndpointDescription
GET/api/workspaces/:wid/billing/statusGet plan, usage quota, and subscription status
POST/api/workspaces/:wid/billing/checkoutCreate a Stripe Checkout session (returns { url })
POST/api/workspaces/:wid/billing/portalCreate a Stripe Customer Portal session (returns { url })
{
"billingEnabled": true,
"plan": "free",
"subscriptionStatus": null,
"usageQuotaUsd": 5,
"hardLimitUsd": 5,
"currentUsageUsd": 1.23,
"modelTier": "free",
"maxDatabases": 3,
"maxMembers": 3
}
StatusDescription
403Not a workspace owner or admin
409Active subscription already exists (on checkout)