Skip to content

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.

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
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})`);
}
}