Constaia
Endpoints

Analytics

Reference for GET /v1/analytics: analysis volume, share of valid, invalid and review results, p50 and p95 times, credits and most frequent rejection reasons, grouped by type, day, template or metadata, as JSON or CSV.

GET /v1/analytics summarises the analyses of a period: how many there were, what share came out valid, invalid or for review, how long they took, how many credits they spent and why they are most often rejected. It's the same information as the Analytics section of the dashboard, so you can take it to your own dashboard or a spreadsheet.

GET /v1/analytics?from=2026-09-01&to=2026-09-30&group_by=type
Authorization: Bearer ck_live_…

It uses a secret key and covers only the key's mode: with ck_live_… real analyses, with ck_test_… test ones.

Parameters

ParameterTypeDefaultDescription
fromdate YYYY-MM-DD29 days before toFirst day (included), in UTC.
todate YYYY-MM-DDtodayLast day (included), in UTC.
group_bytype | day | template | metadata.<key>typeHow analyses are grouped in groups.
formatjson | csvjsoncsv downloads a file instead of JSON.
group_bygroups[].keygroups[].labelOrder
typeDetected type (es_dni…)Type name in the Accept-Language languageMost analyses first
dayDay YYYY-MM-DD (UTC)The same dayChronological; days without analyses don't appear
templateTemplate id (tpl_…)Template nameMost analyses first
metadata.<key>Value of that metadata key (metadata.club_id)The same valueMost analyses first

Analyses with no value for the grouping (no type, no template or no such metadata key) are grouped under key: null with a label such as "No template". At most 500 groups.

Response

analytics
{
  "object": "analytics",
  "from": "2026-09-01",
  "to": "2026-09-30",
  "group_by": "type",
  "mode": "live",
  "totals": {
    "count": 1240, "completed": 1228, "failed": 12,
    "valid": 1015, "invalid": 131, "review": 82,
    "valid_rate": 0.8265, "invalid_rate": 0.1067, "review_rate": 0.0668,
    "avg_ms": 3120, "p50_ms": 2410, "p95_ms": 7800,
    "credits": 1412.4
  },
  "groups": [
    { "key": "es_dni", "label": "Spanish ID card (DNI)", "count": 802, "completed": 798, "failed": 4, "valid": 701, "invalid": 61, "review": 36, "valid_rate": 0.8784, "invalid_rate": 0.0764, "review_rate": 0.0451, "avg_ms": 2380, "p50_ms": 2100, "p95_ms": 4300, "credits": 802 }
  ],
  "top_reasons": [
    { "code": "not_expired", "severity": "error", "count": 58, "example": "The document expired on 03/02/2026." },
    { "code": "low_confidence", "severity": "warning", "count": 41, "example": "The document number could not be read reliably." }
  ]
}
FieldDescription
countAnalyses created in the period (including those still processing).
completed, failedFinished and failed. Failed ones are not charged.
valid, invalid, reviewCompleted with that verdict. If a person reviewed the analysis, their decision counts (verdict.final_status).
valid_rate, invalid_rate, review_rateShare from 0 to 1 of the completed analyses with a verdict (those without one, such as a generic without expect, don't count).
avg_ms, p50_ms, p95_msProcessing time (from start to end of the analysis) of completed ones: mean, median and 95th percentile. null if there is no data.
creditsCredits spent. In test, 0.
top_reasons[]The 10 most frequent warning and error reasons in verdict.reasons: code, severity, count and a real example message (example). The code values are in Verdicts.

Analyses whose results were already deleted by retention still count: the minimal record (type, verdict, credits, metadata) is kept for analytics.

CSV

With format=csv the response is an analytics-<mode>-<grouping>-<from>-<to>.csv file ready for Excel: ; separator, comma decimals, UTF-8 BOM, one row per group (key, group, totals, percentages, mean time, p95 and credits) and a final total row. Column headers follow the Accept-Language language.

curl -G https://api.constaia.com/v1/analytics \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  -H "Accept-Language: en" \
  --data-urlencode "from=2026-09-01" \
  --data-urlencode "to=2026-09-30" \
  --data-urlencode "group_by=metadata.club_id" \
  --data-urlencode "format=csv" \
  -o analytics-september.csv

Examples

curl -G https://api.constaia.com/v1/analytics \
  -H "Authorization: Bearer $CONSTAIA_API_KEY" \
  --data-urlencode "from=2026-09-01" \
  --data-urlencode "to=2026-09-30" \
  --data-urlencode "group_by=template"

Ideas

  • Compare templates: group_by=template shows which setup rejects more or sends more to review.
  • Per customer or event: store their id in metadata when analysing and group with group_by=metadata.<key>.
  • Watch quality: if review_rate goes up or low_quality shows up in top_reasons, review your capture instructions or use the widget, which warns about blurry photos before uploading.
  • Cost: credits per group, together with GET /v1/usage for the daily detail.

Errors

HTTPcodeWhen
422invalid_parameterA date isn't a valid YYYY-MM-DD or group_by isn't one of the accepted values (param says which).

Next steps

On this page