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 URL | https://partners.meerkats.ai/api/public/v1 |
| Format | JSON over HTTPS |
| Authentication | An API key for your app, plus a signed-in user's token on data calls |
| Rate limit | 120 requests a minute per key by default; configurable per key |
| Spec | openapi.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.
- 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.
- 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.
- 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.
| Credential | Header | Identifies | Where you get it |
|---|---|---|---|
| API key | X-API-Key: mk_live_… | Your app: allowed workspaces, scope, branding | Apps, in your account menu |
| End-user token | Authorization: Bearer <jwt> | The logged-in end user | Returned by /auth/signup and /auth/login |
| Workspace | X-Workspace-Id: <uuid> | Which workspace to read or write | One 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#
- Log a user incurl
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": { … } } - List the workspaces the key can seecurl
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 } ] } - Query a metriccurl
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#
| Method | Path | What it does | Scope |
|---|---|---|---|
GET | /branding | App name, logo, colours, tagline and support email for your login screen. API key only. | — |
POST | /auth/signup | Register an end user of your app; returns a session token. | — |
POST | /auth/login | Log an end user in; returns a session token. | — |
POST | /auth/forgot-password | Send a branded reset email with a one-hour, single-use token. Always returns success. | — |
POST | /auth/reset-password | Set a new password with the token from the email. | — |
GET | /auth/me | The current end user. | read |
GET | /workspaces | The workspaces this key may access: id, name, is_default. | read |
GET | /workspaces/sync-status | When the workspace last synced. | read |
GET | /workspaces/sync-history | Every sync run, newest first. | read |
GET | /metrics/catalog | Every metric and the dimensions it can be grouped by. | read |
POST | /metrics/query | Run a query: metrics, groupBy, date range, order, limit. | read |
GET | /metrics/product-revenue | Per-product revenue for one platform (shopify, flipkart, amazon), sorted by revenue. | read |
GET | /automations | List rules, enabled first, newest first. | read |
POST | /automations | Create a rule. | write |
PATCH | /automations/{id} | Update a rule (send the full body). | write |
DELETE | /automations/{id} | Delete a rule. | write |
POST | /automations/{id}/toggle | Enable or disable a rule. | write |
GET | /automations/{id}/runs | A rule's last evaluation, recent staged and fired actions, and audit trail. | read |
GET | /automations/staged | Proposals awaiting approval. | read |
POST | /automations/staged/{id}/approve | Approve and run a proposal. | write |
POST | /automations/staged/{id}/reject | Reject a proposal; nothing runs. | write |
GET | /agents | The workspace's agents, built-in and custom. | read |
GET | /agents/run-history | Recent runs across agents. | read |
GET | /agents/{agentKey} | One agent. | read |
POST | /agents/{agentKey}/run | Run an agent now (uses credits). | write |
POST | /agents/{agentKey}/enable | Enable an agent. | write |
POST | /agents/{agentKey}/disable | Disable 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#
| Field | Description |
|---|---|
| metricsstring[]required | One or more metric names from the catalog. |
| groupBystring[] | Dimension names to group by, from the metric's list in the catalog. |
| dateRangestring | A 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-DD | A custom range. Overrides dateRange. |
| orderBystring[] | Sort keys; prefix with - for descending, for example -campaign_spend. |
| limitinteger | Maximum 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:
{
"success": false,
"error": "Unknown metric: real_roas_7d",
"statusCode": 400,
"timestamp": "2026-10-02T09:14:03.000Z"
}| Status | Meaning |
|---|---|
400 | Bad request: an unknown metric or dimension, a malformed date, a missing required field |
401 | Missing or expired token, or an invalid API key |
403 | The key lacks the scope, or the workspace isn't in its allowed list |
404 | No such rule, proposal or agent in this workspace |
429 | Over 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-Idon 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_daysto custom dates; they follow the workspace time zone. - Record the
timestampfrom 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.