Errors
Errors use HTTP status codes and an RFC 9457 body with
Content-Type: application/problem+json:
{ "type": "https://bonafide.republic.global/problems/validation-error", "title": "Validation failed", "status": 422, "detail": "The request is invalid.", "errors": [ { "pointer": "/recipients/0/email", "message": "Invalid email address" }, { "pointer": "/recipients", "message": "Missing recipient for role 'company'." }, { "pointer": "/recipients/1/role", "message": "Unknown role 'cfo'.", "hint": "Template roles: client, company" } ], "requestId": "req_V1StGXR8Z5jdHi6BmyT2"}| Member | Meaning |
|---|---|
type |
Stable identifier: https://bonafidesign.com/problems/<slug>. Branch on this (or on the slug), not on title or detail |
title |
Short summary of the type |
status |
The HTTP status |
detail |
Human-readable explanation of this occurrence |
errors |
Validation problems: pointer (a JSON Pointer into the request body, or into the query or variables), message, optional hint |
requestId |
Also in the x-request-id header. Quote it to support |
upgradeUrl |
On plan gates (402, 403 plan-upgrade-required): where to add a card or upgrade |
All validation problems of a request are reported at once, so a client can show every one of them next to the right field.
Error types
Section titled “Error types”| Status | Slug | When |
|---|---|---|
| 400 | bad-request |
Malformed request, such as a body that is not valid JSON |
| 401 | unauthorized |
Missing, malformed, revoked or expired credentials |
| 402 | payment-required |
A Free workspace has completed its included envelopes this period; add a card or upgrade (test mode is unaffected) |
| 403 | forbidden |
Authenticated but not allowed: a missing permission, an API key on a dashboard-only endpoint, a cross-site request |
| 403 | plan-upgrade-required |
The feature is not on the workspace’s plan |
| 403 | verification-required |
A signer submitted before verifying their one-time code |
| 404 | not-found |
The resource does not exist in your organization, or the route does not exist |
| 409 | invalid-state |
The action does not fit the current state, e.g. voiding a completed envelope or minting a session for a recipient who signed |
| 409 | not-your-turn |
A signer submitted before earlier routing groups finished |
| 409 | document-mismatch |
The document changed since the signer was shown it (viewedDocumentHash) |
| 409 | already-signed |
The email address already signed this always-on link |
| 409 | in-use |
Deleting a template that envelopes or signing links use |
| 409 | no-draft |
Publishing a template that has no draft |
| 409 | idempotency-in-progress |
A request with the same Idempotency-Key is still running |
| 409 | conflict |
Other conflicts |
| 410 | gone |
A signing session that was already used or has expired |
| 413 | payload-too-large |
An upload over its limit (25 MB for template files) |
| 415 | unsupported-media-type |
An upload of an unsupported type |
| 422 | validation-error |
The body, query or variables are invalid; see errors |
| 422 | idempotency-key-reused |
The same Idempotency-Key was used with a different request |
| 422 | conversion-failed |
A Word document could not be converted |
| 429 | rate-limited |
Too many requests; wait for Retry-After seconds when it is present |
| 500 | internal |
Unexpected error. Safe to retry with the same Idempotency-Key |
| 501 | not-implemented |
The capability exists in the schema but not yet (e.g. SMS codes) |
| 503 | converter-unavailable, billing-unavailable |
A dependency is temporarily unavailable; retry later |
Handling errors
Section titled “Handling errors”const res = await fetch('https://bonafide-api.republic.global/v1/envelopes', { method: 'POST', headers, body });if (!res.ok) { const problem = await res.json(); // application/problem+json const slug = problem.type.split('/').pop(); if (slug === 'validation-error') { for (const e of problem.errors) form.setError(e.pointer, e.message); } else if (slug === 'payment-required') { showUpgrade(problem.upgradeUrl); } else { throw new Error(`${problem.title} (${problem.requestId})`); }}