Skip to content

Error Format

All error responses use RFC 7807 Problem Details with Content-Type: application/problem+json.

Response shape

json
{
  "type":     "https://docs.comprobify.com/errors/validation-error",
  "title":    "Validation Failed",
  "status":   400,
  "code":     "VALIDATION_FAILED",
  "detail":   "Validation failed",
  "instance": "/v1/documents"
}
FieldDescription
typeURL linking to the documentation page for this error type (this site)
titleShort, stable description of the error type
statusHTTP status code (same as the response status)
codeStable machine-readable key — use this for i18n and programmatic handling
detailHuman-readable explanation of this specific occurrence
instanceThe request path that produced the error

Using code for programmatic handling

The code field is the stable key your client application should switch on. It never changes for a given situation, regardless of changes to the human-readable detail text.

js
switch (error.code) {
  case 'CERTIFICATE_EXPIRED':
    return 'Your signing certificate has expired. Replace it in issuer settings.';
  case 'RESEND_COOLDOWN':
    return 'Please wait before requesting another email.';
  case 'QUOTA_EXCEEDED':
    return 'Monthly invoice limit reached. Upgrade your plan.';
  default:
    return error.detail;
}

Validation errors

When code is VALIDATION_FAILED, an additional errors array lists each field that failed:

json
{
  "type":   "https://docs.comprobify.com/errors/validation-error",
  "title":  "Validation Failed",
  "status": 400,
  "code":   "VALIDATION_FAILED",
  "detail": "Validation failed",
  "instance": "/v1/documents",
  "errors": [
    {
      "field":   "buyer.email",
      "message": "Buyer email is required and must be a valid email address",
      "code":    "buyer.email",
      "value":   ""
    }
  ]
}

Each entry in errors has:

FieldDescription
fieldThe request body path that failed (e.g. buyer.email, items[0].taxes[0].code)
messageEnglish description of the failure
codeField path with array indices stripped — stable key for field-level localization (e.g. items.taxes.code)
valueThe value that was submitted

SRI errors

POST /:accessKey/send and GET /:accessKey/authorize are asynchronous (see Send to SRI) — SRI_SUBMISSION_FAILED can no longer be returned as an HTTP response from either endpoint. A network failure now happens inside the background worker and is recorded as an ERROR document event instead; see SRI Submission Failed for details. The shape below is kept for reference:

When code is SRI_SUBMISSION_FAILED, an additional sriMessages array contains the raw messages returned by the SRI SOAP service:

json
{
  "type":   "https://docs.comprobify.com/errors/sri-error",
  "title":  "SRI Submission Failed",
  "status": 502,
  "code":   "SRI_SUBMISSION_FAILED",
  "detail": "SRI rejected the document",
  "instance": "/v1/documents/1503.../send",
  "sriMessages": [
    {
      "identifier": "35",
      "message":    "ARCHIVO NO CUMPLE ESTRUCTURA XML",
      "type":       "ERROR"
    }
  ]
}

All error codes

Most errors carry a specific code that is more precise than the HTTP status alone. Switch on code, not on status, to handle errors programmatically.

400 Bad Request

CodeWhen
VALIDATION_FAILEDOne or more request fields failed validation — see errors[]
CERTIFICATE_INVALIDP12 file is corrupted or not a valid PKCS#12 archive
CERTIFICATE_PASSWORD_INVALIDP12 password is incorrect
CERTIFICATE_KEY_NOT_FOUNDSigning key bag not found inside the P12
CERTIFICATE_EXPIREDCertificate notAfter date has passed
ISSUER_ID_REQUIREDX-Issuer-Id header is missing on a document endpoint
ISSUER_ID_INVALIDX-Issuer-Id is not a valid positive integer
INVALID_OR_EXPIRED_TOKENEmail verification token is invalid or has expired
DOCUMENT_TYPE_NOT_ENABLEDRequested document type is not active for this issuer
DOCUMENT_TYPE_NOT_SUPPORTEDDocument type code is not registered in the system
INVALID_STATE_TRANSITIONDocument operation is not valid for its current status
DOCUMENT_NOT_AUTHORIZEDOperation (RIDE, email) requires document status AUTHORIZED
SELF_REVOCATION_FORBIDDENCannot revoke the API key used to authenticate this request
INVALID_FILE_UPLOADUploaded file is missing, the wrong type, or exceeds the field's size limit (e.g. a logo over 500 KB)
PROOF_FILE_LIMIT_REACHEDPayment already has the maximum number of active proof files (10) — delete one before uploading more
VERSION_MISMATCHtermsVersion in POST /v1/tenants/agreements does not match the currently published TERMS document version — re-fetch GET /v1/agreements and present the current version before asking the user to accept again
LAST_ISSUER_CANNOT_BE_REMOVEDTenant has only one active issuer left — it cannot be removed
ISSUER_HAS_DOCUMENTSIssuer has issued documents (in either environment) and cannot be removed
SEQUENTIAL_CANNOT_DECREASEnextSequential is not greater than the counter's current value
TIER_CHANGE_NO_OPRequested tier and billing interval on Change Tier both match the subscription's current values
INVALID_BILLING_INTERVALbillingInterval on Create Subscription or Change Tier is not MONTHLY or YEARLY
BAD_REQUESTOther malformed request (fallback — read detail)

401 Unauthorized

CodeWhen
API_KEY_ENV_MISMATCHAPI key environment (sandbox/production) does not match the tenant's current environment
UNAUTHORIZEDMissing, invalid, or revoked API key (fallback)

402 Payment Required

CodeWhen
QUOTA_EXCEEDEDMonthly document quota reached — upgrade plan
BRANCH_LIMIT_REACHEDTenant has reached the maximum number of branches for their plan
ISSUE_POINT_LIMIT_REACHEDBranch has reached the maximum number of issue points for this plan
WEBHOOK_ENDPOINT_LIMIT_REACHEDTenant has reached the maximum number of webhook endpoints for their plan
DOCUMENT_TYPE_NOT_IN_TIERDocument type isn't included in the tenant's current plan — upgrade to enable it

403 Forbidden

CodeWhen
ISSUER_FORBIDDENX-Issuer-Id names an issuer that belongs to a different tenant
ACCOUNT_SUSPENDEDTenant account is suspended — contact support
EMAIL_VERIFICATION_REQUIREDOperation requires a verified email address
AGREEMENT_ACCEPTANCE_REQUIREDPromotion blocked — one or more agreements are still PENDING (check GET /v1/tenants/agreements, view at GET /v1/tenants/agreements/:type, accept via POST /v1/tenants/agreements)
PRODUCTION_KEY_REQUIRES_PROMOTIONProduction API key cannot be created before promoting to production
FORBIDDENOther permission failure (fallback — read detail)

404 Not Found

CodeWhen
ISSUER_NOT_FOUNDIssuer ID in X-Issuer-Id or URL parameter does not exist
SOURCE_ISSUER_NOT_FOUNDsourceIssuerId not found or belongs to a different tenant
WEBHOOK_ENDPOINT_NOT_FOUNDWebhook endpoint not found or belongs to a different tenant
SUBSCRIPTION_NOT_FOUNDSubscription not found
PAYMENT_NOT_FOUNDPayment not found, or belongs to a different tenant
AGREEMENT_NOT_FOUNDNo document of the requested type (TERMS, PRIVACY, or DPA) has been published yet
NOT_FOUNDOther resource not found (document, API key — read detail)

409 Conflict

CodeWhen
ALREADY_VERIFIEDAttempting to resend verification to an already-verified account
SUBSCRIPTION_ALREADY_IN_FLIGHTTenant already has a subscription in progress (promotion with tier, or Admin's Create Subscription)
NO_ACTIVE_SUBSCRIPTIONCancel or Change Tier requested but the tenant has no ACTIVE subscription
TIER_CHANGE_ALREADY_PENDINGA tier/billing-interval change is already scheduled, or its payment is already in flight, for this subscription
CANCELLATION_ALREADY_PENDINGA cancellation (DELETE /v1/subscriptions) is already scheduled for this subscription
CONFLICTIdempotency key reused with a different payload, payment already decided, or other conflict

429 Too Many Requests

CodeWhen
RESEND_COOLDOWNResend verification requested again before the 60-second cooldown elapsed
TOO_MANY_REQUESTSAPI key rate limit exceeded

500 / 502

CodeWhen
SRI_SUBMISSION_FAILEDSRI SOAP service returned an error or unexpected HTTP status — no longer surfaced via any HTTP response (see SRI errors above); now recorded as a document ERROR event
INTERNAL_ERRORUnexpected server error

Comprobify API Documentation