Meerkats AI

API overview

Keys, two-layer authentication, a first request, every endpoint, the query body, scopes, limits and errors.

The Meerkats API lets your own code and the apps you build on Meerkats read business context and manage automations: query any metric in the catalog, list and create rules, approve or reject proposals, run agents, and check sync status. It is the same surface the app uses, so anything you can see in Meerkats you can read over the API.

Base URLhttps://partners.meerkats.ai/api/public/v1
FormatJSON over HTTPS
AuthenticationAn API key for your app, plus a signed-in user's token on data calls
Rate limit120 requests a minute per key by default; configurable per key
Specopenapi.json

Create an API key#

Keys are issued under an app. An app is a product you build on your data, with its own branding and its own users; a key belongs to the app and is scoped to the workspaces you choose.

  1. Open Apps

    Select your name at the bottom of the sidebar, then Apps, then Create app. Give it a name; add a logo, colours and support email if your users will see a login screen.

  2. Create a key

    Inside the app, create a key. Choose read or write scope (write implies read) and tick the workspaces the key may access.

  3. Copy it once

    The key starts with mk_live_ and is shown once. Store it on your server. Never put it in a browser or a mobile app.

Authentication#

Every call carries your API key. Data calls also carry a token for the end user who is asking, so Meerkats knows which of your users it is and records their actions against them.

CredentialHeaderIdentifiesWhere you get it
API keyX-API-Key: mk_live_…Your app: allowed workspaces, scope, brandingApps, in your account menu
End-user tokenAuthorization: Bearer <jwt>The logged-in end userReturned by /auth/signup and /auth/login
WorkspaceX-Workspace-Id: <uuid>Which workspace to read or writeOne of the key's workspaces, from /workspaces

If you omit X-Workspace-Id, the key’s first workspace is used. Tokens are short-lived; there is no refresh endpoint, so log the user in again when a call returns 401.

Your own users, your branding

Your app’s users sign up and log in through the API, never through Meerkats’s own screens. GET /branding returns the name, logo, colours and tagline you set on the app, so you can render your login page before any user exists. Password-reset emails carry the same branding and link to the auth_redirect_base_url you configure.

A first request#

  1. Log a user in
    curl
    curl -X POST https://partners.meerkats.ai/api/public/v1/auth/login \
      -H "X-API-Key: $MEERKATS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{ "email": "user@example.com", "password": "…" }'
    
    → { "success": true, "token": "<jwt>", "user": { … } }
  2. List the workspaces the key can see
    curl
    curl https://partners.meerkats.ai/api/public/v1/workspaces \
      -H "X-API-Key: $MEERKATS_API_KEY" \
      -H "Authorization: Bearer $TOKEN"
    
    → { "success": true, "workspaces": [ { "id": "…", "name": "Northwind Growth", "is_default": true } ] }
  3. Query a metric
    curl
    curl -X POST https://partners.meerkats.ai/api/public/v1/metrics/query \
      -H "X-API-Key: $MEERKATS_API_KEY" \
      -H "Authorization: Bearer $TOKEN" \
      -H "X-Workspace-Id: $WORKSPACE_ID" \
      -H "Content-Type: application/json" \
      -d '{ "metrics": ["real_roas", "campaign_spend"], "groupBy": ["ad_row__platform"], "dateRange": "last_7_days" }'
    
    → { "success": true, "metrics": [...], "group_by": [...], "row_count": 2, "rows": [ { "ad_row__platform": "meta", "real_roas": 2.8, "campaign_spend": 3120 }, … ] }

Call GET /metrics/catalog first to learn which metric and dimension names your workspace accepts; unknown names return 400.

Endpoints#

MethodPathWhat it doesScope
GET/brandingApp name, logo, colours, tagline and support email for your login screen. API key only.—
POST/auth/signupRegister an end user of your app; returns a session token.—
POST/auth/loginLog an end user in; returns a session token.—
POST/auth/forgot-passwordSend a branded reset email with a one-hour, single-use token. Always returns success.—
POST/auth/reset-passwordSet a new password with the token from the email.—
GET/auth/meThe current end user.read
GET/workspacesThe workspaces this key may access: id, name, is_default.read
GET/workspaces/sync-statusWhen the workspace last synced.read
GET/workspaces/sync-historyEvery sync run, newest first.read
GET/metrics/catalogEvery metric and the dimensions it can be grouped by.read
POST/metrics/queryRun a query: metrics, groupBy, date range, order, limit.read
GET/metrics/product-revenuePer-product revenue for one platform (shopify, flipkart, amazon), sorted by revenue.read
GET/automationsList rules, enabled first, newest first.read
POST/automationsCreate a rule.write
PATCH/automations/{id}Update a rule (send the full body).write
DELETE/automations/{id}Delete a rule.write
POST/automations/{id}/toggleEnable or disable a rule.write
GET/automations/{id}/runsA rule's last evaluation, recent staged and fired actions, and audit trail.read
GET/automations/stagedProposals awaiting approval.read
POST/automations/staged/{id}/approveApprove and run a proposal.write
POST/automations/staged/{id}/rejectReject a proposal; nothing runs.write
GET/agentsThe workspace's agents, built-in and custom.read
GET/agents/run-historyRecent runs across agents.read
GET/agents/{agentKey}One agent.read
POST/agents/{agentKey}/runRun an agent now (uses credits).write
POST/agents/{agentKey}/enableEnable an agent.write
POST/agents/{agentKey}/disableDisable an agent.write

Full request and response shapes are in the OpenAPI document. The pages on rules, approvals, agents and metrics show the bodies in context.

The query body#

FieldDescription
metricsstring[]requiredOne or more metric names from the catalog.
groupBystring[]Dimension names to group by, from the metric's list in the catalog.
dateRangestringA preset: today, yesterday, last_7_days, last_30_days, last_90_days, this_week, last_week, this_month, last_month, this_year, all, or a rolling last_N_days.
startDate, endDateYYYY-MM-DDA custom range. Overrides dateRange.
orderBystring[]Sort keys; prefix with - for descending, for example -campaign_spend.
limitintegerMaximum rows.

The workspace comes from the headers, never from the body. The response has metrics, group_by, row_count and rows; each row has one key per requested metric and dimension.

Scopes, limits and errors#

Scopes#

A key has read or write scope. Read endpoints need read; anything that creates, changes, approves, runs or deletes needs write. Write implies read. A call outside the key’s scope or workspaces returns 403.

Rate limits#

120 requests a minute per key by default, configurable per key. Over the limit returns 429; back off and retry.

Errors#

Every error has one shape:

Error
{
  "success": false,
  "error": "Unknown metric: real_roas_7d",
  "statusCode": 400,
  "timestamp": "2026-10-02T09:14:03.000Z"
}
StatusMeaning
400Bad request: an unknown metric or dimension, a malformed date, a missing required field
401Missing or expired token, or an invalid API key
403The key lacks the scope, or the workspace isn't in its allowed list
404No such rule, proposal or agent in this workspace
429Over the rate limit

Good practice#

  • Keep the API key on your server. Proxy calls from your front end through your own backend, so the key never reaches a browser.
  • Send X-Workspace-Id on every data call, even with one workspace. It makes the call explicit in the Activity log.
  • Cache /metrics/catalog; it changes only when definitions change.
  • Prefer presets like last_7_days to custom dates; they follow the workspace time zone.
  • Record the timestamp from error bodies when you report an issue.

Troubleshooting#

401 on every data call

Data calls need both the API key and a user token. Log a user in with /auth/login and send the token as Authorization: Bearer. Tokens expire; log in again on 401.

403 on a workspace I can see in the app

The key is scoped to workspaces when created. Open the app under Apps and add the workspace to the key, or create a new key.

400 Unknown metric

Names are validated against your workspace’s catalog. Call GET /metrics/catalog and use the names it returns.

The rule I created never fires

Check enabled is true, and read GET /automations/{id}/runs for the last evaluation: it shows the values seen and whether the condition was met.

Last updated October 2, 2026