Skip to content

Errors

When a request fails, the response includes "ok": false and an error object with a machine-readable code and a human-readable message.

{
"ok": false,
"error": {
"code": "contacts.not_found",
"message": "Contact not found"
}
}
StatusMeaning
200Success
400Bad request — invalid parameters
401Unauthorized — missing or invalid token
403Forbidden — account locked or insufficient permissions
404Not found
429Rate limit exceeded
500Internal server error
CodeDescription
auth.requiredNo Authorization header provided
auth.invalid_requestMalformed request body
auth.invalid_credentialsWrong email or password
auth.email_takenEmail already registered
auth.invalid_tokenExpired or invalid token
auth.deactivatedUser account has been deactivated
auth.internalServer error during authentication
CodeDescription
contacts.invalid_requestMalformed request body
contacts.invalid_idInvalid UUID format
contacts.not_foundContact does not exist
contacts.first_name_requiredFirst name is required for creation
contacts.invalid_company_idReferenced company does not exist
contacts.invalid_source_idReferenced source does not exist
contacts.invalid_custom_fieldsCustom field values don’t match definitions
contacts.internalServer error
CodeDescription
companies.invalid_requestMalformed request body
companies.invalid_idInvalid UUID format
companies.not_foundCompany does not exist
companies.invalid_custom_fieldsCustom field values don’t match definitions
companies.internalServer error
CodeDescription
projects.invalid_requestMalformed request body
projects.invalid_idInvalid UUID format
projects.not_foundProject does not exist
projects.name_requiredName is required for creation
projects.invalid_stageStage must be: proposal, active, review, complete, archived
projects.invalid_company_idReferenced company does not exist
projects.invalid_assigned_toReferenced user does not exist
projects.invalid_custom_fieldsCustom field values don’t match definitions
projects.internalServer error
CodeDescription
activities.invalid_requestMalformed request body
activities.invalid_idInvalid UUID format
activities.invalid_typeType must be: call, email, meeting
activities.entity_requiredMust provide at least one of contact_id, company_id, or project_id
activities.invalid_metadataMetadata doesn’t match schema for the activity type
activities.not_foundActivity does not exist
activities.internalServer error
CodeDescription
sources.invalid_requestMalformed request body
sources.invalid_idInvalid UUID format
sources.not_foundSource does not exist
sources.name_requiredName is required
sources.internalServer error
CodeDescription
webhooks.invalid_requestMalformed request body
webhooks.invalid_idInvalid UUID format
webhooks.not_foundWebhook endpoint does not exist
webhooks.url_requiredURL is required
webhooks.invalid_urlURL must be a valid HTTPS URL
webhooks.internalServer error
CodeDescription
custom_fields.invalid_requestMalformed request body
custom_fields.invalid_idInvalid UUID format
custom_fields.not_foundCustom field definition does not exist
custom_fields.invalid_entity_typeEntity type must be: contact, company
custom_fields.label_requiredLabel is required
custom_fields.invalid_field_typeField type must be: text, number, date, boolean, enum
custom_fields.options_requiredEnum fields require an options array
custom_fields.internalServer error
CodeDescription
oauth.invalid_requestMalformed request body
oauth.unsupported_grant_typeOnly client_credentials is supported
oauth.missing_credentialsMissing client_id or client_secret
oauth.invalid_clientInvalid credentials or app has been revoked
oauth.internalServer error
CodeDescription
oauth_apps.invalid_requestMalformed request body
oauth_apps.invalid_idInvalid UUID format
oauth_apps.not_foundOAuth app does not exist
oauth_apps.name_requiredName is required
oauth_apps.internalServer error
CodeDescription
imports.invalid_requestMalformed request body
imports.invalid_idInvalid UUID format
imports.not_foundImport job does not exist
imports.model_type_requiredModel type is required
imports.file_name_requiredFile name is required
imports.invalid_model_typeModel type must be: contacts, companies, sources
imports.internalServer error
  1. Always check ok — don’t assume success based on HTTP status alone
  2. Use the code for logic — error codes are stable; messages may change
  3. Handle auth.invalid_token — refresh your token and retry the request once
  4. Retry transient failures — back off and retry on network errors and 5xx responses (see Retrying requests)
  5. Log the full error — include both code and message for debugging

Some failures are transient and safe to retry; others are deterministic and will fail again until you fix the request.

Safe to retry (with backoff):

  • Network/connection errors and timeouts
  • 500 responses (*.internal) — a transient server-side error

Do not retry as-is — fix the request first:

  • 400 (validation), 403 (forbidden), 404 (not found) — deterministic; the same request will fail again
  • 401 (auth.invalid_token) — refresh your access token, then retry once

Use exponential backoff with jitter and cap the number of attempts:

import time, random
def with_retry(call, max_attempts=4):
for attempt in range(max_attempts):
resp = call()
if resp.status_code < 500:
return resp # success or a deterministic error
if attempt == max_attempts - 1:
return resp
time.sleep(min(2 ** attempt, 8) + random.random()) # 1s, 2s, 4s … + jitter

Write operations are not guaranteed idempotent. If a create/update times out, verify whether it applied (e.g. via a -list or -get) before retrying so you don’t create duplicates.