Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.clarky.ai/llms.txt

Use this file to discover all available pages before exploring further.

Every Clarky API error — whether it’s an authentication failure, a validation problem, or an internal error — comes back in the same envelope. This makes it easy to write a single error handler that works across every endpoint.

Error envelope

{
  "error": {
    "code": "validation_error",
    "message": "first_name must be a string",
    "details": {
      "field": "first_name"
    }
  }
}
error.code
string
required
A short machine-readable identifier for the failure. Use this for branching logic — never the message.
error.message
string
required
A human-readable description of what went wrong. Safe to surface to developers, but not generally suitable for end users.
error.details
object
Optional structured context. The shape depends on the error code — for validation_error this often includes the offending field name, expected type, etc.

Error codes

CodeHTTPMeaning
unauthorized401Missing, malformed, or revoked API key
forbidden403Authenticated, but the key doesn’t have permission for this action
not_found404The resource doesn’t exist or isn’t visible to your workspace
bad_request400The request was malformed (bad JSON, unsupported parameter, etc.)
validation_error422The request was well-formed but a field failed validation
conflict409The request conflicts with the current state of a resource
rate_limited429Too many requests — see Rate Limits
internal_error500Something went wrong on our end. Retry with backoff

Examples

unauthorized (401)

Returned when the Authorization header is missing, the key has been revoked, or the key format is invalid.
{
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid API key"
  }
}

forbidden (403)

Returned when the key is valid but doesn’t have permission for the action — for example, a read-only key trying to POST.
{
  "error": {
    "code": "forbidden",
    "message": "This API key does not have the 'write' scope"
  }
}

not_found (404)

Returned when the resource doesn’t exist, or exists in a different workspace than the one your key belongs to.
{
  "error": {
    "code": "not_found",
    "message": "Contact not found"
  }
}

bad_request (400)

Returned for malformed requests — invalid JSON, unsupported query parameters, missing Content-Type, etc.
{
  "error": {
    "code": "bad_request",
    "message": "Request body must be valid JSON"
  }
}

validation_error (422)

Returned when the request is structurally valid but at least one field failed validation. The details object identifies the offending field.
{
  "error": {
    "code": "validation_error",
    "message": "deal_value must be a non-negative number",
    "details": {
      "field": "deal_value"
    }
  }
}

conflict (409)

Returned when the request would violate a uniqueness constraint or otherwise conflict with the current state.
{
  "error": {
    "code": "conflict",
    "message": "A contact with this primary email already exists",
    "details": {
      "field": "emails",
      "existing_contact_id": "c_01HXYZ..."
    }
  }
}

rate_limited (429)

Returned when you exceed the per-key request budget. The response includes Retry-After and X-RateLimit-* headers — see Rate Limits.
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry after 30 seconds."
  }
}

internal_error (500)

Returned when something unexpected happened server-side. These should be rare. Retry with exponential backoff.
{
  "error": {
    "code": "internal_error",
    "message": "An unexpected error occurred"
  }
}
Always branch on error.code, never on error.message. We may improve message wording over time, but codes are stable contract.