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.