CoreDash Agency API: Manage Projects and Pull Data Across Accounts
Manage many projects from one account. Mint a master key once, create and delete projects through REST, and pull Core Web Vitals data across all of them with a single key.

One key for every project on your account
The Agency API is for accounts that manage many projects. Agencies, in-house teams running a dozen brands, anyone who does not want to log into the dashboard every time a new client comes on board. Mint a master key once, then create projects, update them, delete them, and read Core Web Vitals data across all of them with that one credential.
Looking for the per-project API instead? The CoreDash API page covers a single project with a project-scoped key. Same data tools, narrower scope, simpler setup.
The Agency API does two things:
- Project CRUD: a small REST surface at
/api/agency/projectsfor creating, listing, updating, and deleting projects. - Cross-project data reads: the same JSON-RPC tools as the per-project API (
get_metrics,get_timeseries,get_histogram) at/api/mcp. With a master key you passproject_idin the arguments to pick which project you want.
Two kinds of API keys
CoreDash issues two key tiers. Each one has a different job.
| Key | Prefix | Scope | What it does |
|---|---|---|---|
| Project key | cdk_ | One project | Reads RUM data for that project through the JSON-RPC endpoint. See /api. |
| Master key | cdk_master_ | Every project on the account | Creates, lists, updates, and deletes projects through REST. Also reads data for any project on the account by passing project_id in the data tools. |
Master keys are only available on agency-flagged accounts. If you do not see the Agency API tab described below, talk to support.
Get a master key
Master keys are minted from the web UI, not from the API.
- Log in at app.coredash.app.
- Open My Account and click the Agency API tab.
- Click Generate master key, give it a name, and copy the value. It is shown once.
Keys start with cdk_master_. They let the holder manage every project that belongs to your user account, and read data for any of them. Treat them like passwords. You can revoke any master key from the same tab.
Authentication
Every Agency API request needs a master key in the Authorization header:
Authorization: Bearer cdk_master_YOUR_MASTER_KEY
The same header works for both the REST project CRUD endpoints and the JSON-RPC data endpoint. Nothing else changes.
Project CRUD: the REST surface
Base URL for project management:
https://app.coredash.app/api/agency/projects
These are plain REST calls. Not JSON-RPC.
POST /api/agency/projects: create a project
Creates a new project owned by the master key's user. By default the project starts as a 10-day trial. Pass agencyplan to start it on a paid plan instead, with a 33-day billing period.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Project name shown in the dashboard. |
url | string | no | The site URL the project tracks. |
agencyplan | string | no | Plan id (for example starter). When set, the project starts on the matching paid plan instead of a trial. |
curl -X POST https://app.coredash.app/api/agency/projects \
-H "Content-Type: application/json" \
-H "Authorization: Bearer cdk_master_YOUR_MASTER_KEY" \
-d '{
"name": "Acme client",
"url": "https://acme.example",
"agencyplan": "starter"
}' Response on success is 201:
{
"status": 201,
"project": {
"_id": "655f1f77bcf86cd799439011",
"name": "Acme client",
"url": "https://acme.example",
"status": "paid",
"users": ["644..."],
"expires": "2026-06-28T12:00:00.000Z",
"alerts": { "ai": true },
"created": { "date": "2026-05-26T12:00:00.000Z" }
}
} The _id is what you put in the tracking snippet on the client's site. It is also the project_id you pass to the data tools below.
GET /api/agency/projects: list projects
Returns the projects your user owns, sorted by creation date (newest first). Paginated with limit (max 500, default 100) and offset.
curl "https://app.coredash.app/api/agency/projects?limit=50" \ -H "Authorization: Bearer cdk_master_YOUR_MASTER_KEY"
{
"status": 200,
"projects": [
{ "_id": "...", "name": "Acme client", "url": "https://acme.example", "status": "paid" },
{ "_id": "...", "name": "Beta client", "url": "https://beta.example", "status": "trial" }
]
} GET /api/agency/projects/:id: fetch one project
Returns a single project document. Returns 404 if your user does not own the project. We deliberately do not differentiate "not found" from "not yours" so project IDs cannot be enumerated across accounts.
curl https://app.coredash.app/api/agency/projects/655f1f77bcf86cd799439011 \ -H "Authorization: Bearer cdk_master_YOUR_MASTER_KEY"
PATCH /api/agency/projects/:id: update name or URL
Updates name and/or url. Both fields are optional. Omitted fields are left as they were. Anything else in the body is ignored. Status, billing, expiry, and alerts are managed through the dashboard.
curl -X PATCH https://app.coredash.app/api/agency/projects/655f1f77bcf86cd799439011 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer cdk_master_YOUR_MASTER_KEY" \
-d '{ "name": "Acme client renamed" }' DELETE /api/agency/projects/:id: hard-delete a project
Deletes the project and everything attached to it: Lighthouse runs, CrUX data, alerts, snapshots, and snapshot configs.
RUM data in the backing data store is not deleted in this call. It stays keyed on the old project ID but becomes orphaned. There is no recovery path. The project ID is retired.
curl -X DELETE https://app.coredash.app/api/agency/projects/655f1f77bcf86cd799439011 \ -H "Authorization: Bearer cdk_master_YOUR_MASTER_KEY"
{ "status": 200, "deleted": true } Reading data with a master key
To pull Core Web Vitals data for one of your projects, hit the same JSON-RPC endpoint the per-project API uses:
https://app.coredash.app/api/mcp
The three tools are unchanged: get_metrics, get_timeseries, get_histogram. The only difference compared to the per-project flow is that you pass project_id in arguments so the call knows which project to look at. Project keys do not need this because each project key is already scoped to one project. Master keys cover many projects, so the request has to name one.
Example: get_metrics for a specific project
curl -X POST https://app.coredash.app/api/mcp \
-H "Content-Type: application/json" \
-H "Authorization: Bearer cdk_master_YOUR_MASTER_KEY" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_metrics",
"arguments": {
"project_id": "655f1f77bcf86cd799439011",
"metrics": "LCP,INP,CLS",
"date": "-7d"
}
}
}' The response is the same JSON-RPC wrapper as the per-project API, with the parsed payload in result.content[0].text. The shape of the inner JSON, the distribution object, the summary field on timeseries, the bucket structure on histograms, all behave the same way as with a project key. The only extra requirement is the project_id argument.
Same applies to get_timeseries and get_histogram. Pass project_id, then the usual arguments.
All other parameters work the same way: filters, group, percentile, date, granularity, and so on. The dimensions reference (d, cc, ff, lcpel, inpel, all of them), the metrics thresholds, and the percentile semantics are all documented on the CoreDash API page. Read that for the full parameter and dimension surface. This page only covers what is different when you authenticate with a master key.
Onboarding a new client project
The typical flow for an agency adding a new client:
- Mint a master key once at My Account → Agency API tab and store it securely.
POST /api/agency/projectswith the client's name and URL. The response contains the new_id.- Embed the tracking snippet on the client's site with that
_id. - Read RUM data for that project at any time via
POST /api/mcpwith the same master key and"project_id": "<the _id>"in the arguments. No separate project key needed.
That is the whole onboarding loop. One key, one POST, one snippet embed, and you can already query data for the new project.
Errors
Project CRUD endpoints return plain REST status codes:
| Status | Meaning |
|---|---|
400 | Missing required field on create, or unknown plan id. |
401 | Missing, bad, or revoked master key. |
404 | Project not found, or not owned by your user. |
500 | Database error. |
Data reads at /api/mcp return JSON-RPC error objects, same as with a project key. The error code table is on the CoreDash API page. If you get -32001, double-check that your key starts with cdk_master_ and that you included project_id in the arguments.
Rate limits
Per-project daily limits still apply when you read data: a master key calling get_metrics for project A counts against project A's daily quota, and a call for project B counts against project B's. See the rate limits table on the CoreDash API page. Project CRUD calls are not rate-limited in the same way.

