API
Errors
The OnePageCRM API success and error envelopes, error fields, and the HTTP status codes with fixes.
Last updated Jul 8, 2026
Success and error responses use two different JSON envelopes.
Check the HTTP status code first, then branch on error_name.
The envelopes
A successful response:
{
"status": 0,
"message": "OK",
"timestamp": 1765456800,
"data": { "...": "..." }
}
An error response drops timestamp and data and carries error fields
instead:
{
"status": 400,
"message": "Invalid request data",
"error_name": "invalid_request_data",
"error_message": "A validation error has occurred",
"errors": { "...": "..." }
}
| Field | Type | Appears in | Description |
|---|---|---|---|
status | integer | both | 0 on success. On errors, an application status code — it can differ from the HTTP status (see below) |
message | string | both | Short human-readable summary |
timestamp | integer | success only | Unix time in seconds |
data | object | success only | The payload |
error_name | string | errors only | Machine identifier, e.g. invalid_auth_token. Branch on this, not on error_message |
error_message | string | errors only | Human explanation of what went wrong |
errors | object | errors only | Field-level details on validation failures; {} otherwise |
Exact error_message text can change. Match on error_name in code;
log error_message for debugging.
One trap: the body’s status does not always match the HTTP status.
Bad credentials, for example, return HTTP 401 with "status": 400 in
the body. Trust the HTTP status code and error_name.
HTTP status codes
| HTTP | Meaning | error_name examples | Fix |
|---|---|---|---|
400 | Invalid or incomplete request data. Also the default for unclassified errors — including duplicate records (duplicated_entity, resource_already_exists) | invalid_request_data, duplicated_entity, resource_already_exists | Inspect errors for the offending fields; check the request shape against the API reference |
401 | Authentication missing or invalid | invalid_auth_token (API key), invalid_access_token (OAuth), invalid_login, authorization_data_not_found (no auth sent) | Re-check credentials; refresh an expired OAuth token. See Authentication |
402 | Payment required | trial_expired, subscription_canceled | The account’s subscription has lapsed — the account owner needs to update billing |
403 | Forbidden, including OAuth scope errors | no_permission_to_complete_action | Check the user’s permissions and your token’s scope (below) |
404 | Resource not found | resource_not_found | Check the path and record ID against the API reference |
405 | HTTP method not allowed | method_not_allowed | Use the verb the endpoint documents |
429 | Too many concurrent connections | — | Back off and retry. Note: the request-rate throttle returns 403 with a plain-text Rate Limit Exceeded body instead. See Rate limits |
500 | Internal server error | internal_server_error | Retry; if it persists, contact support |
503 | Maintenance or temporary unavailability | service_unavailable | Retry later. See the maintenance note |
Worked examples
401 — bad credentials
curl -u "USER_ID:WRONG_KEY" \
https://app.onepagecrm.com/api/v3/contacts.json
{
"status": 400,
"message": "Invalid auth token",
"error_name": "invalid_auth_token",
"error_message": "Authorization token is invalid",
"errors": {}
}
Note the mismatch: the HTTP status is 401, but the body says
"status": 400. This is expected — branch on the HTTP status and
error_name, not the body’s status field.
Re-copy your user_id and api_key from the
API settings page. OAuth requests
fail the same way but with error_name: invalid_access_token — that
usually means the access token expired. Refresh it and retry.
403 — insufficient OAuth scope
A crm.readonly token attempting a write:
curl -X POST \
-H "Authorization: Bearer READONLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"last_name": "Lovelace"}' \
https://app.onepagecrm.com/api/v3/contacts.json
{
"status": 403,
"message": "You have no permission to complete this action",
"error_name": "no_permission_to_complete_action",
"error_message": "Insufficient OAuth scope. Required: crm",
"errors": {}
}
Write endpoints require the crm scope. Request it during
authorization — see Authentication for the
scope rules, and note that some endpoints reject OAuth tokens entirely
with This endpoint is not available for OAuth applications.
400 — validation failure
Creating a contact with incomplete data:
curl -u "USER_ID:API_KEY" \
-X POST \
-H "Content-Type: application/json" \
-d '{}' \
https://app.onepagecrm.com/api/v3/contacts.json
{
"status": 400,
"message": "Invalid request data",
"error_name": "invalid_request_data",
"error_message": "A validation error has occurred",
"errors": {
"last_name": "Required field last_name is missing"
}
}
The errors object is keyed by field name; the exact message varies by
field. Fix each listed field and resend the request.
Handling errors in code
- Branch on the HTTP status first, then on
error_name. - On
401, refresh credentials or re-authenticate — don’t retry blindly. - On
429, a plain-textRate Limit Exceeded403, and503, retry with backoff — see Rate limits. - On
400, fix the request — retrying the same payload returns the same error. - Log
error_messageanderrors— they tell you exactly what to fix.
Common questions
Why does the body say status 400 when the HTTP status is 401?
The body’s status is an application code and doesn’t always match
the HTTP status — bad credentials return HTTP 401 with
"status": 400 in the body. Trust the HTTP status code and
error_name.
Which field should my code branch on?
error_name — it’s the stable machine identifier. The
error_message text can change, so log it for debugging, but never
match on it.
What to read next
- Rate limits — what triggers a throttle and how to back off.
- Authentication — both auth methods and the OAuth scope rules.
- API reference — per-endpoint parameters and response shapes.