Skip to content
Signal
Dashboard

Errors

HTTP status codes, error codes and validation detail types.

Every error response of the V2 HTTP API, has this envelope:

{
  "error": {
    "code": "not_found",
    "message": "The campaign 0190a4e2-0000-7000-8000-000000000001 does not exist.",
    "details": {
      "resource": "campaign",
      "id": "0190a4e2-0000-7000-8000-000000000001"
    }
  }
}
  • code is a stable snake_case value. Use it in your code.
  • message is text for a person. It can change.
  • details holds extra data, or null.

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

StatuscodeCause
401unauthorizedThe API key is missing or not valid. Read Authentication.
402insufficient_creditsThe 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.
403access_deniedEffective permissions lack a required resource level. details identifies the resource, action and operation. See Permission errors.
403access_unclassifiedThe operation has no registered access rule and cannot execute. Contact support with the request ID.
404not_foundThe resource does not exist in the organization of the key. A resource of another organization also gives 404.
409conflictA permanent conflict with the current resource state, for example canceling a finished run. details.retryable is false. See the transient codes below.
422validation_error or a specific codeThe request is not valid. idempotency_key_reused means that the Idempotency-Key belongs to a request with another body.
429rate_limit_exceededThe API key sent more requests than the limit allows. The envelope includes details.retry_after. Read Rate limit.
500internal_errorThe server failed. The message does not contain internal detail.
503service_unavailableSignal 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.

{
  "error": {
    "code": "access_denied",
    "message": "The operation requires monitor.write.",
    "details": {
      "resource": "monitor",
      "action": "write",
      "operation_id": "update_monitor"
    }
  }
}

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:

{
  "error": {
    "code": "validation_error",
    "message": "The request is not valid: body.name: Field required",
    "details": {
      "errors": [
        { "loc": ["body", "name"], "message": "Field required", "type": "missing" }
      ]
    }
  }
}

Some operations give a 422 response with a specific code:

codeOperationsCause
invalid_cursorList and search operationsThe cursor value did not come from next_cursor.
campaign_id_requiredsearch_accounts, search_peoplereview_state was sent without campaign_id.
invalid_entity_typeMembership add, start_import, upload_import, start_exportThe campaign does not have the record type of an add, an import or an export.
missing_namestart_importAn import row has no name.
unsupported_file_typeupload_importThe uploaded file is not a CSV file.
invalid_csvupload_importThe CSV file has no header row, no data row, or a row that the parser cannot read.
missing_name_columnupload_importThe CSV file has no name column.
discovery_schedule_requiredupdate_campaignA 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.

TypeOperationsMeaning
field_reservedupdate_campaignA custom field uses a default name or the criteria_ prefix.
field_repeatedupdate_campaignA field name repeats in the requested change.
field_not_foundupdate_campaignA removed custom field does not exist.
entity_not_in_campaignupdate_campaignA field change addresses a record type absent from the campaign.
missing, extra_forbiddenTyped request operationsA 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:

CodeRetryableAction
concurrent_updatetrueAnother request changed discovery state. Re-read the campaign and retry the same intent.
idempotency_in_progresstrueWait, then retry with the same key and request body.
monitor_run_in_progresstrueWait for the active run to finish, or explicitly cancel it. details.run_id identifies the run.
import_rows_pendingtrueWait for the import to publish its row outcomes, then read them again.
import_rows_unavailablefalseHistorical row outcomes are unavailable; retrying cannot reconstruct them.
conflictfalseChange 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.

On this page