Skip to content

Error reference

truval.dev APIs return JSON error bodies with a consistent shape. Use the error field for branching in code; show message and action to humans.

Most errors use this structure (from the verify and management workers):

FieldTypePurpose
errorstringStable machine code (this page is the catalog).
messagestringShort human-readable explanation.
actionstringWhat the client or operator should do next.
docsstringDeep link into these docs or OpenAPI.

Optional fields depend on the error (rate limits, quota, spend cap). 402 payment_required on verify routes uses hard_cap_eur and current_overage_eur instead of always matching the full envelope (still includes error, message, action, docs).

OpenAPI: https://api.truval.dev/openapi.json documents many verify errors; management and some edge cases are listed here as the full catalog.

Dashboard usage_log.error_class vs response error

Section titled “Dashboard usage_log.error_class vs response error”

The developer dashboard Concrete logs table shows error_class from usage_log. For most verify failures it matches the JSON error field. Exceptions:

usage_log.error_classHTTP response errorNotes
rate_limitrate_limit_exceededSame event: per-minute cap. Always use error in API clients.
(varies, e.g. TypeError)(no synchronous body)Async webhook verification failed in the background. The row may show an exception name as error_class; error_snapshot typically includes "error": "internal".

Successful verifications use error_class: null.

The remote MCP server surfaces HTTP-style errors inside JSON-RPC error.data. See MCP Server for the mapping; the codes below are the same error strings.


Subsection titles match the error string for deep links (for example #rate_limit_exceeded).

HTTP401
APIsVerify (/v1/email/*), Management (/v1/management/*)
CauseNo Authorization header or not Bearer ….
FixSend Authorization: Bearer sk_live_… for verify, or sk_mgmt_… for management.
Extra fields
HTTP401
APIsVerify, Management
CauseKey hash not in KV (revoked, typo, wrong environment).
FixCreate a new key in the dashboard or rotate with your provisioning key.
Extra fields
HTTP403
APIsVerify (if sk_mgmt_… or provisioning key), Management (if not sk_mgmt_… provisioning key)
CauseKey type does not match the route family.
FixUse sk_live_… on verify routes; use sk_mgmt_… on /v1/management/* (except dashboard-only bootstrap).
Extra fields
HTTP413
APIsVerify (when Content-Length is present and over limit)
CauseRequest body exceeds the advertised limit (header guard; 2MB).
FixShrink the body; batch large workloads across requests.
Extra fields
HTTP400
APIsVerify (JSON shape, email/webhook validation), Management (JSON body rules)
CauseMalformed JSON, missing fields, invalid webhook URL, wrong batch/stream array bounds, etc.
FixFollow action and docs in the response; see Email verify (request / batch / stream sections).
Extra fields
usage_log error_classUsually invalid_request
HTTP503
APIsVerify
CauseTemporary failure while checking free-tier monthly quota (e.g. database).
FixRetry with backoff; contact support if persistent.
Extra fields
usage_log error_classquota_check_failed
HTTP429
APIsVerify
CauseFree tier: UTC calendar month verification unit cap would be exceeded.
FixWait until after reset_at (start of next UTC month) — add a small cushion for clock skew/latency — or upgrade. Do not tight-loop.
Extra fieldslimit, used, reset_at
usage_log error_classmonthly_quota_exceeded

Free-tier quota: Rows appear in Concrete logs but failed_check monthly_quota_exceeded is excluded from the monthly cap count (see monthly quota).

HTTP429
APIsVerify
CausePer-minute rate limit for the key’s tier exceeded (batch/stream count per email toward the limit).
FixWait until after reset_at (add a small cushion for clock skew/latency), throttle clients, or upgrade tier for higher limits.
Extra fieldslimit, window ("1m"), reset_at
usage_log error_classrate_limit (not rate_limit_exceeded)

Free-tier quota: Rows appear in Concrete logs but failed_check rate_limit_exceeded is excluded from the monthly cap count (see monthly quota).

HTTP402
APIsVerify
CauseHard EUR spend cap for the billing period would be exceeded (preflight uses worst-case email count for the request).
FixRaise or clear the hard cap under Billing & Limits, or upgrade.
Extra fieldshard_cap_eur, current_overage_eur (may be null for cap in edge cases)
usage_log error_classpayment_required
HTTP404
APIsVerify (unknown route), Management (unknown route; customer not found on provisioning bootstrap)
CauseWrong path, or (management internal bootstrap) invalid customerId.
FixUse documented paths and OpenAPI; check customer UUID for provisioning.
Extra fields
HTTP404
APIsManagement (DELETE /v1/management/keys/:id)
CauseNo active standard key with that id for the account.
FixList keys with GET /v1/management/keys and use a valid id.
Extra fields
HTTP429
APIsManagement (POST /v1/management/keys)
CauseActive standard keys already at plan maximum.
FixRevoke a key, then create a new one, or upgrade tier for higher max_keys.
Extra fields
HTTP402
APIsManagement (POST /v1/management/billing/portal)
CauseNo Stripe customer id on file for the account.
FixComplete billing setup in the dashboard, then retry.
Extra fields
HTTP500
APIsManagement (billing portal session creation)
CauseStripe API did not return a portal URL.
FixRetry later; if ongoing, check Stripe status and account configuration.
Extra fields
HTTP500 (most), 409 (provisioning key already exists)
APIsManagement
CauseSupabase request failed or conflict (e.g. provisioning key already present).
FixRetry for transient failures; for 409 on provisioning, revoke the existing provisioning key first per action text.
Extra fields