API reference
Notes, funnels and site settings API
These endpoints manage one website's configuration. Use the site secret key, or an account token with site=WEBSITE_ID (the examples use a token). Changes need the write scope and an admin or owner role; share links can't use them.
| Request | Token scope |
|---|---|
| GET /notes, GET /commits, GET /funnels | read |
| GET /segments, GET /site | visitors |
| POST, PUT and DELETE on /notes, /funnels, /segments; PUT /site | write |
| Every /site/keys request (admins and the owner; never the site secret key) | write |
Chart notes
Notes are short, dated annotations such as “Launched on Product Hunt”, shown on the traffic chart. They are private to the website's team. To add them in the dashboard, see Chart notes.
List notes
GET /notes returns notes oldest first. Optional from and to are inclusive YYYY-MM-DD dates; invalid dates return 400 invalid_range.
curl --request GET 'https://metricraven.com/api/v1/notes?site=WEBSITE_ID&from=2026-10-01&to=2026-10-31' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN"{
"notes": [
{
"id": "note_c7924fbf9cef42447f69d344",
"date": "2026-10-14",
"text": "Launched on Product Hunt",
"createdAt": "2026-10-14T09:12:03.045Z",
"updatedAt": "2026-10-14T09:12:03.045Z"
}
]
}Create, change and delete a note
| Field | Type | Required | Description |
|---|---|---|---|
| date | string | Yes | Calendar date YYYY-MM-DD, from 2000-01-01 up to tomorrow, in your reporting time zone. |
| text | string | Yes | 1–280 characters. Line breaks and repeated spaces become one space. |
curl --request POST 'https://metricraven.com/api/v1/notes?site=WEBSITE_ID' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"date": "2026-10-14",
"text": "Launched on Product Hunt"
}'| Request | Result |
|---|---|
| POST /notes | 201 with the note. 400 invalid_note for a bad date or text; 409 note_limit at 1,000 notes. |
| PUT /notes/NOTE_ID | The same body replaces date and text; returns the note, or 404 not_found. |
| DELETE /notes/NOTE_ID | 204 No Content, or 404 not_found. |
GitHub commits
GET /commits lists commits from the website's connected repository in the period, newest first, up to 500. It takes the usual from/to or range=all and timezone, and optional type values (comma separated or repeated): feat, fix, perf, refactor, docs, style, test, build, ci, chore or revert. Unknown types are ignored.
curl --request GET 'https://metricraven.com/api/v1/commits?site=WEBSITE_ID&range=all&type=feat,fix' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN"{
"commits": [
{
"sha": "3541888878c4d303a8bc2ad61815f4e048f55a5d",
"title": "feat: annual pricing",
"message": "feat: annual pricing\n\nAdds a yearly toggle to /pricing.",
"type": "feat",
"author": { "name": "Ana", "login": "ana", "avatarUrl": "https://avatars.githubusercontent.com/u/1?v=4" },
"committedAt": "2026-10-09T06:20:11Z",
"url": "https://github.com/acme/web/commit/3541888878c4d303a8bc2ad61815f4e048f55a5d",
"branch": "main",
"additions": 120,
"deletions": 14
}
]
}type is null for messages without a conventional-commit prefix; additions and deletions are null until their statistics are imported.
Funnels
Saved funnels appear in the dashboard and can be reported with /stats/conversions?funnel=FUNNEL_ID.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | 1–80 characters. |
| steps | string | Yes | 1–8 comma-separated steps: visit, page:/path, event:goal_name, identify, payment. Steps count only in this order. |
curl --request POST 'https://metricraven.com/api/v1/funnels?site=WEBSITE_ID' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"name": "Pricing to paid",
"steps": "visit,page:/pricing,event:signup,payment"
}'{
"id": "pricing-to-paid-3fa2b1",
"name": "Pricing to paid",
"steps": "visit,page:/pricing,event:signup,payment",
"position": 0
}| Request | Result |
|---|---|
| GET /funnels | { funnels: [...] } in display order (position). |
| POST /funnels | 201 with the funnel. 400 invalid_funnel with details. |
| PUT /funnels/FUNNEL_ID | Changes name, steps or both; returns the funnel, or 404 not_found. |
| DELETE /funnels/FUNNEL_ID | { ok: true }, or 404 not_found. |
Segments
A segment is a named set of report filters, as in Save a segment. Each one has a revision: send the current one when changing or deleting it, so two people can't overwrite each other.
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | 1–64 characters, unique per website ignoring case. |
| filters | array | Yes | 1–6 report filters. |
| revision | integer | PUT, DELETE | The segment's current revision. |
curl --request POST 'https://metricraven.com/api/v1/segments?site=WEBSITE_ID' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"name": "US organic",
"filters": [
{
"dim": "country",
"op": "is",
"values": [
"US"
]
},
{
"dim": "channel",
"op": "is",
"values": [
"Organic Search"
]
}
]
}'{
"id": "seg_0f1e2d3c4b5a69788796a5b4c3d2e1f0",
"name": "US organic",
"filters": [
{ "dim": "country", "op": "is", "values": ["US"] },
{ "dim": "channel", "op": "is", "values": ["Organic Search"] }
],
"revision": 1,
"createdAt": "2026-11-02T08:30:00.000Z",
"updatedAt": "2026-11-02T08:30:00.000Z"
}| Request | Result |
|---|---|
| GET /segments | { segments: [...] } sorted by name. |
| POST /segments | 201 with the segment. 409 duplicate_segment_name, or segment_limit at 50 segments. |
| PUT /segments/SEGMENT_ID | Body: revision, name and the full filters. Returns the segment with revision + 1. |
| DELETE /segments/SEGMENT_ID | Body: revision. Returns { ok: true }. |
A stale revision returns 409 segment_changed: read the list again and retry. An invalid body or ID returns 400 invalid_segment, and a missing segment 404 not_found.
Site settings
GET /site returns the website's settings. PUT /site changes any subset of them and returns the updated settings.
{
"id": "ana_pub_1a2b3c4d5e6f7a8b",
"name": "Acme",
"domains": ["acme.com", "app.acme.com"],
"appIds": ["com.acme.app"],
"exclusions": { "paths": ["/admin/*"], "ips": ["203.0.113.7"], "countries": [], "hostnames": ["staging.acme.com"] },
"gscProperty": "sc-domain:acme.com",
"appearance": null,
"primaryGoal": "signup"
}| Field | Type | Description |
|---|---|---|
| name | string | 1–80 characters. |
| domains | string[] | 1–20 domains. URLs are reduced to their host and www. is removed; an invalid one returns 400 invalid_domain. |
| appIds | string[] | Up to 20 native app bundle or package IDs, such as com.acme.app, accepted from the mobile SDKs. Stored lowercase. |
| exclusions | object | All four lists, which replace the current ones: paths (up to 100, starting with /), ips (up to 100), countries (up to 250 two-letter codes) and hostnames (up to 50). See Exclude visits. |
| gscProperty | string or null | Search Console property: sc-domain:acme.com or https://acme.com/ (with the trailing slash). null unlinks it. |
| primaryGoal | string or null | Goal name shown as the headline KPI (primary goal); null restores the default. |
| appearance | object or null | Dashboard colors: light and dark, each with background, surface and eight graphs colors as #RRGGBB. null restores the default theme. See Appearance. |
curl --request PUT 'https://metricraven.com/api/v1/site?site=WEBSITE_ID' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"primaryGoal": "signup",
"gscProperty": "sc-domain:acme.com"
}'Fields you leave out are unchanged. Invalid JSON returns 400 invalid_json; invalid fields return 400 invalid_settings with details.
Secret keys
Besides its default secret key, a website can have up to 10 named keys, for example one per server or integration. Every key has the same access; named keys let you see where each is used and revoke one without touching the others. These endpoints need an account token with the write scope (or a dashboard session) of an admin or the owner. A site secret key can't call them, so a leaked key can't create more keys.
| Request | Does |
|---|---|
| GET /site/keys | Lists the keys: id (default for the default key, else key_…), name, hint, createdAt, lastUsedAt, plus previous (replaced values still accepted) and maxNamedKeys. |
| POST /site/keys | Body { name } (1–60 characters, unique). Returns 201 with key and secretKey, shown once. |
| PATCH /site/keys/{id} | Body { name }: renames a key, the default key included. |
| DELETE /site/keys/{id} | Revokes a named key at once. The default key returns 400 default_key: roll it instead. |
| POST /site/keys/{id}/roll | Body { grace: none | 24h | 7d } (default none): a new value, returned once; the old value keeps working for the grace period. |
curl --request POST 'https://metricraven.com/api/v1/site/keys?site=WEBSITE_ID' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"name": "Billing worker"
}'{
"key": {
"id": "key_3f9a1c0b7d2e4a51",
"name": "Billing worker",
"hint": "ana_sec_Q2xv…",
"createdAt": "2026-11-02T10:00:00.000Z",
"lastUsedAt": null,
"default": false
},
"secretKey": "ana_sec_Q2xv…full key, shown once"
}curl --request POST 'https://metricraven.com/api/v1/site/keys/default/roll?site=WEBSITE_ID' \
--header "Authorization: Bearer $METRICRAVEN_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"grace": "24h"
}'Errors: 400 too_many_keys at the limit, 409 duplicate_name, 404 not_found for an unknown ID, 403 forbidden with a site secret key, 429 too_many_attempts after 30 new or rolled keys in an hour. Only the default key can be used to add an existing website to another account.
Details
- Note dates are calendar days, not instants: a note dated 2026-10-14 shows on that day in any report time zone.
- Funnel IDs are made from the name plus a random suffix and don't change when you rename the funnel.
- Segment names are compared after Unicode normalization, ignoring case and repeated spaces; filters are stored normalized, with duplicate values removed.
- The share link stays in the dashboard. Owners delete a website in Settings or with DELETE /api/v1/websites/WEBSITE_ID.