Skip to content

Response & Error Conventions

This page describes the conventions that apply to the standardized response format (API version 2026-06-12).

Which version am I on?

Consumers select the response format using the request header:

  • X-API-Version: 2026-06-12 -> standardized format
  • missing/unknown version -> legacy format

If you are unsure which format you receive, see Legacy & Migration.

Datetimes

All timestamps are returned in RFC 3339 / ISO-8601, UTC:

json
{ "created_at": "2024-06-15T10:00:00Z" }
  • Timestamps always carry a timezone designator (Z for UTC).
  • Pure date fields (for example activation_date) remain date-only: "2024-06-15".
  • Do not assume the legacy space-separated format ("2024-06-15 10:00:00").

Booleans

Fields representing a true/false state are returned as real JSON booleans (true / false), never as 1/0, "1"/"0", or "true"/"false".

Boolean fields are identified by these name prefixes:

is_, has_, can_, show_, enable_, skip_

json
{ "is_active": true, "can_send_deletion_request": false }

Errors

Every error response — validation, authentication, authorization, not-found, conflict, rate-limit, and server errors — uses a single canonical envelope:

json
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The given data was invalid.",
    "details": [
      { "field": "email", "issue": "The email field is required." }
    ]
  }
}
FieldDescription
codeStable, non-localized machine-readable string. Branch on this.
messageHuman-readable, localized message. For display only — do not parse it.
detailsArray of field-level errors. Present only for validation errors.
  • The error Content-Type is always application/json.
  • Branch your logic on error.code (and the HTTP status), never on the message text.

Error codes

HTTP statuserror.codeMeaning
400BAD_REQUESTMalformed request.
401UNAUTHENTICATEDAuthentication required or failed.
403FORBIDDENAuthenticated but not permitted.
404NOT_FOUNDResource does not exist.
405METHOD_NOT_ALLOWEDHTTP method not allowed for the route.
406NOT_ACCEPTABLECannot satisfy the Accept header.
409CONFLICTState conflict.
410GONEResource permanently removed.
422VALIDATION_ERRORField-level validation failed.
428PRECONDITION_REQUIREDA required precondition was missing.
429RATE_LIMITEDToo many requests — back off and retry.
500INTERNAL_ERRORUnexpected server error.
503SERVICE_UNAVAILABLETemporarily unavailable.

Rate limiting

Throttled requests return HTTP 429 with code: RATE_LIMITED. (In the legacy format this was incorrectly returned as 409 Conflict.)

HTTP status codes

The API uses standard HTTP semantics: 2xx for success, 4xx for client errors, and 5xx for server errors. The status code and the error.code together fully describe an error condition.

Known differences not yet standardized

For transparency, a few values are not yet normalized:

  • Field-name casing: some upstream-sourced fields remain PascalCase (e.g. EventTime) rather than snake_case.
  • Sweetpay subscription created_at is date-only (YYYY-MM-DD).
  • Statistics endpoints return period labels (e.g. "Jun-2024") that are intentionally not ISO-8601 timestamps.

For API access and technical questions, contact Defentry through your account manager.