Appearance
Metrics
2 reads, no writes, on train 2026-11. Scopes: metrics:read.
| Operation | Method | Scope | Path |
|---|---|---|---|
| The metric dictionary | GET | metrics:read | /api/v1/metrics |
| Compile one query from the dictionary and answer with its rows | POST | metrics:read | /api/v1/metrics/query |
The metric dictionary
GET /api/v1/metrics
Scopes: metrics:read
Every metric and dimension the platform defines, each with one sentence saying what it is, how it rolls up, the grain it is held at, the record it is read from, and the day it entered the dictionary.
| Optional | In | What it is |
|---|---|---|
Tightly-Version | header | The date train to answer on. |
bash
curl "https://api.app.tightly.io/api/v1/metrics" \
-H "Authorization: Bearer $TIGHTLY_API_KEY"What it answers
json
{
"data": {
"domains": [
{
"data_source": "Sale orders",
"domain": "sales",
"grain": "One sale order line: a variant sold on one order.",
"grains": [
"daily",
"monthly",
"weekly"
],
"label": "Sales",
"supports_time_range": true
}
],
"metrics": [
{
"data_source": [
"Sale orders",
"Sale orders against the merchandise financial plan"
],
"definition": "Sales after discounts and returns, before tax.",
"domains": [
{
"data_source": "Sale orders",
"domain": "sales",
"grain": "One sale order line: a variant sold on one order.",
"label": "Sales",
"served": true,
"unsupported_reason": null
},
{
"data_source": "Sale orders against the merchandise financial plan",
"domain": "sales_plan",
"grain": "One month, category and sales channel, carrying the actual and the plan together.",
"label": "Sales vs plan",
"served": true,
"unsupported_reason": null
}
…
]
}
]
}
}What it refuses
- 401
key_invalid: "The API key is not valid." No usable key: malformed, unknown, revoked, expired or stopped. One refusal covers all five, telling a caller which is which maps the surface for them. A request with no Authorization header at all is refused 400 before any key is looked for. - 403
scope_missing: "This key cannot read Metrics." The key may not reach this operation.scope_missingwhen the key does not hold Metrics;organization_mismatchwhen the path names an organisation that is not the key's;ip_not_allowedwhen the caller's address is outside the key's allowlist. - 429
Compile one query from the dictionary and answer with its rows
POST /api/v1/metrics/query
Scopes: metrics:read
Hand this the query the dictionary describes and it answers with rows, the columns, the formats each figure prints in, the window it actually ran over and the query itself, echoed back.
| Optional | In | What it is |
|---|---|---|
Tightly-Version | header | The date train to answer on. |
Idempotency-Key | header | A string of your own, up to 255 characters, that makes this write safe to retry. |
bash
curl -X POST "https://api.app.tightly.io/api/v1/metrics/query" \
-H "Authorization: Bearer $TIGHTLY_API_KEY" \
-H "Content-Type: application/json" \
-d @body.jsonWhat to send, as body.json
json
{
"query": {
"dimensions": [
"sales_channel"
],
"domain": "sales",
"grain": "week",
"measures": [
"net_sales"
],
"time_range": {
"amount": 12,
"kind": "relative",
"unit": "week"
}
}
}What it answers
json
{
"data": {
"columns": [
"week",
"sales_channel",
"net_sales"
],
"explanation": "Net sales by sales channel, by week, over the last twelve weeks.",
"formats": {
"net_sales": "currency"
},
"query": {
"dimensions": [
"sales_channel"
],
"domain": "sales",
"grain": "week",
"measures": [
"net_sales"
],
"time_range": {
"amount": 12,
"kind": "relative",
"unit": "week"
}
},
"resolved_time_range": {
"end": "2026-09-05",
"start": "2026-06-14"
},
"row_count": 2,
"rows": [
{
"net_sales": 842100,
"sales_channel": "Online",
"week": "2026-08-30"
},
{
"net_sales": 342100,
"sales_channel": "Wholesale"
…
}
]
}
}What it refuses
- 400 The query is the caller's to fix.
fieldnames the control,keythe term that was wrong andallowedwhat may go there. - 401
key_invalid: "The API key is not valid." No usable key: malformed, unknown, revoked, expired or stopped. One refusal covers all five, telling a caller which is which maps the surface for them. A request with no Authorization header at all is refused 400 before any key is looked for. - 403
scope_missing: "This key cannot read Metrics." The key may not reach this operation.scope_missingwhen the key does not hold Metrics;organization_mismatchwhen the path names an organisation that is not the key's;ip_not_allowedwhen the caller's address is outside the key's allowlist. - 429