Errors
HTTP status codes, error codes and validation detail types.
Every error response of the V2 HTTP API, has this envelope:
codeis a stable snake_case value. Use it in your code.messageis text for a person. It can change.detailsholds extra data, ornull.
Request ID
Every V2 response has an X-Request-ID header. When you send an X-Request-ID of 1 to 128 characters (letters, digits, ., _ and -), the response uses your value. Otherwise Signal makes a new ID. Log the ID, and send it to support with a question about a request.
Status codes
| Status | code | Cause |
|---|---|---|
| 401 | unauthorized | The API key is missing or not valid. Read Authentication. |
| 402 | insufficient_credits | The organization has no credits for a run. details.available_credits gives the balance. The request starts no run. Add credits in the dashboard, then send the request again. |
| 403 | access_denied | Effective permissions lack a required resource level. details identifies the resource, action and operation. See Permission errors. |
| 403 | access_unclassified | The operation has no registered access rule and cannot execute. Contact support with the request ID. |
| 404 | not_found | The resource does not exist in the organization of the key. A resource of another organization also gives 404. |
| 409 | conflict | A permanent conflict with the current resource state, for example canceling a finished run. details.retryable is false. See the transient codes below. |
| 422 | validation_error or a specific code | The request is not valid. idempotency_key_reused means that the Idempotency-Key belongs to a request with another body. |
| 429 | rate_limit_exceeded | The API key sent more requests than the limit allows. The envelope includes details.retry_after. Read Rate limit. |
| 500 | internal_error | The server failed. The message does not contain internal detail. |
| 503 | service_unavailable | Signal cannot reach a backing service, for example the database during the API key check. An authentication database outage includes Retry-After: 1 and runs no operation. Other 503 causes may omit that header; do not assume every failure rolls back earlier writes. |
Other 4xx statuses use the same envelope. Their code names the status, for example method_not_allowed for 405.
Permission errors
Product operations check explicit Permissions. The organization role does not replace those checks. API keys use their assigned permissions within the owner's current access.
Handle code, resource, action and operation_id as structured values. The message text can change. Ask an Owner or Admin to review the owner's access and the key's assigned limit. Repeating the request does not repair a missing permission. A denied operation changes no product data, starts no work and spends no credits.
When only embedded data is restricted, a permitted read can return a partial representation with a restricted list. An explicitly requested resource without its required read permission gives 403. Read Restricted response data.
Validation errors
A request that does not match the schema gives 422 with the code validation_error. An ID that is not a UUID also gives this code. details.errors lists each problem:
Some operations give a 422 response with a specific code:
code | Operations | Cause |
|---|---|---|
invalid_cursor | List and search operations | The cursor value did not come from next_cursor. |
campaign_id_required | search_accounts, search_people | review_state was sent without campaign_id. |
invalid_entity_type | Membership add, start_import, upload_import, start_export | The campaign does not have the record type of an add, an import or an export. |
missing_name | start_import | An import row has no name. |
unsupported_file_type | upload_import | The uploaded file is not a CSV file. |
invalid_csv | upload_import | The CSV file has no header row, no data row, or a row that the parser cannot read. |
missing_name_column | upload_import | The CSV file has no name column. |
discovery_schedule_required | update_campaign | A discovery count or status change was sent for a campaign with no discovery schedule. |
| idempotency_key_reused | create_campaign, create_monitor, run_monitor, start_discovery, start_import, upload_import | The same key names another request body. |
Validation detail types
validation_error is the envelope code. error.details.errors[].type identifies an individual invalid field; it is not a second envelope code.
| Type | Operations | Meaning |
|---|---|---|
field_reserved | update_campaign | A custom field uses a default name or the criteria_ prefix. |
field_repeated | update_campaign | A field name repeats in the requested change. |
field_not_found | update_campaign | A removed custom field does not exist. |
entity_not_in_campaign | update_campaign | A field change addresses a record type absent from the campaign. |
missing, extra_forbidden | Typed request operations | A required field is absent or an unknown field is present. |
Schema validation also reports constraint types such as string_too_short, string_too_long, string_pattern_mismatch, greater_than_equal, less_than_equal, too_short, too_long, uuid_parsing, enum, literal_error, union_tag_invalid and union_tag_not_found. Their operations and limits come from the affected request schema. Inspect each loc to identify the field. See the operation schema for accepted values.
Conflict and retry
Every 409 includes details.retryable. Use the code to choose the next action:
| Code | Retryable | Action |
|---|---|---|
concurrent_update | true | Another request changed discovery state. Re-read the campaign and retry the same intent. |
idempotency_in_progress | true | Wait, then retry with the same key and request body. |
monitor_run_in_progress | true | Wait for the active run to finish, or explicitly cancel it. details.run_id identifies the run. |
import_rows_pending | true | Wait for the import to publish its row outcomes, then read them again. |
import_rows_unavailable | false | Historical row outcomes are unavailable; retrying cannot reconstruct them. |
conflict | false | Change the request or resource state before retrying. |
A discovery schedule that disappears during an update returns 404 not_found. A schedule validation failure returns 422 validation_error. These failures can follow earlier changes to campaign settings. Re-read the campaign before correcting and retrying; the update is not an atomic rollback.
Use bounded retries with increasing delays. See Retry safely.
422 idempotency_key_reused means the key belongs to another request body. Use a fresh key for a new request.