Skip to main content
HoundDog API Documentation

Errors

Every v2 error has one shape:

{
  "error": {
    "code": "validation_failed",
    "message": "Email address is not a valid email",
    "request_id": "9f3a2c8e-...",
    "details": [
      { "field": "email", "message": "is not a valid email" }
    ]
  }
}

details is present on validation errors (one entry per field) and on a feature_disabled caused by one field (the field your account cannot set), and omitted otherwise. Quote the request_id when you contact support; it ties your request to our logs.

Sending back what you read never causes feature_disabled: on every write, a field of a feature your account does not use is accepted and changes nothing when it carries the value the API serves for that record (null and an empty or whitespace-only string count as equal, in either direction). On a create, any empty value is accepted and ignored: null, "" (or whitespace only), [], {}, or false for an on/off field. Only a different value is 403 feature_disabled.

Status code When
400 validation_failed A required parameter is missing, a parameter has the wrong type, or per_page is above the cap
401 unauthorized See Authentication
403 forbidden The key may not perform this operation
403 account_deactivated, api_disabled, insufficient_scope, feature_disabled See Authentication. feature_disabled names the feature in its message
404 not_found No record with that id in your account. An id that belongs to another account is also 404, never 403
409 conflict The write would invalidate another open record; the conflict member names it. See below
409 conflict A party or project create or update raced another change storing the first value of the same custom field. Nothing was written; send the request again. This 409 carries no conflict member
409 idempotency_in_progress A request with the same Idempotency-Key is still running. See Idempotency
409 idempotency_not_replayable The Idempotency-Key cannot be replayed: what it created no longer exists, or the first response held a one-time value
422 validation_failed The record could not be saved; details names each field. Also used for an id in a body or query that is not in your account
422 signing_template_invalid The signing template cannot be sent as configured; the message names the template. See Document signing
422 idempotency_key_reused The Idempotency-Key was already used for a different request
429 rate_limited See Rate limits; carries a Retry-After header
500 internal_error Something failed on our side; we are alerted with the request_id. Safe to retry a read; check before retrying a write
501 not_implemented The endpoint exists in the reference but is not available yet
502 upstream_failed A service HoundDog depends on (the e-signature service, file storage) failed or timed out; nothing was kept. Retry with an Idempotency-Key

Each operation's page lists the codes it can return.

Error messages are plain sentences meant for logs and support tickets, not for display to your end users.

Conflicts

A 409 conflict carries the record it conflicts with in its own member; details is omitted:

{
  "error": {
    "code": "conflict",
    "message": "This party already has an open request for this template",
    "request_id": "9f3a2c8e-...",
    "conflict": { "resource": "signing_request", "id": 9012 }
  }
}

Read that record named by resource and id, then decide: each conflicting write accepts a flag to go ahead.

Order of checks on W-9 and document signing writes

On those writes, the checks run in this order and the first failure answers:

  1. Authentication and the account gates (401, 403), see Authentication.
  2. The feature gate (403 feature_disabled).
  3. Ids in the path (404).
  4. The body and query (400 for malformed parameters, then 422 validation_failed or signing_template_invalid for what is known without calling another service).
  5. Conflicts (409 conflict).
  6. Calls to another service (422 signing_template_invalid, 502 upstream_failed).

So a request that would fail validation never receives a conflict, and a conflict is reported before any call to another service is made.

One exception to the order: parameter validation (types, required parameters, allowed values) runs before the endpoint body, so a malformed parameter (400) can be reported before the feature gate (step 2) and before an unknown id in the path (step 3). This order is stated for those writes only; other endpoints follow the same layers but make no promise about their order.

A note on v1

v1 keeps its original string-shaped errors, {"error": "..."}, and will for as long as v1 is served. Only v2 uses the structured shape above.