Using the API
View as Markdown

Errors

The error response body, what each HTTP status means, how to read validation errors, and every error code the API returns.

Last updated

The API uses standard HTTP status codes, and every error response has the same JSON body.

The error body

{
  "success": false,
  "error": "VALIDATION_ERROR",
  "message": "Request validation failed. Check the errors for details.",
  "details": {
    "errors": [
      { "field": "lead.first_name", "message": "Field required", "type": "missing" }
    ]
  },
  "request_id": "3b0f6c1e-8a2d-4e7b-9c5a-2d1f0e9b8a7c"
}
FieldMeaning
successAlways false on an error.
errorA stable code for the kind of error. Branch on this.
messageA human-readable explanation. Its wording can change, so don't parse it.
detailsExtra context for some errors, such as the failing fields of a validation error. Not always present.
request_idThe request's ID, also sent as the X-Request-ID header. Quote it when you contact support.

Status codes

StatusMeaningRetry?
400The request is invalid.No. Fix the request first.
401The API key is missing, invalid, revoked or expired.No.
403The key lacks the required scope, or the organization is deactivated.No.
404The endpoint, or the resource in your organization, doesn't exist.No.
405The endpoint doesn't accept this HTTP method.No.
409A conflict: the resource already exists, or it changed since you read it.For IDEMPOTENCY_IN_PROGRESS, after Retry-After. For SEQUENCE_MODIFIED, after reading the campaign again.
413The request body is larger than 1 MB.No.
429You've hit a rate limit.Yes, after Retry-After. See Rate limits.
500Something failed on our side.Yes, with backoff. Send an Idempotency-Key on create requests so a retry is safe.
503A dependency timed out, or the key couldn't be checked.Yes, with backoff.

Validation errors

A request that doesn't match the endpoint's schema answers 400 VALIDATION_ERROR, and details.errors lists every problem. Each entry has:

  • field: the path to the field, with nested fields joined by dots, such as lead.first_name. It's request when the problem isn't tied to one field.
  • message: what's wrong with the value.
  • type: a short machine-readable reason, such as missing.

Common causes are a missing required field, a value of the wrong type, a string longer than 2,000 characters, and a number out of range, such as a limit above the endpoint's maximum.

IDs that don't exist

  • A path ID that isn't a valid UUID answers 404 NOT_FOUND.
  • An ID in a request body or query string that isn't a valid UUID, such as campaign_id or stage_id, answers 400 VALIDATION_ERROR.
  • A path ID for a resource that isn't in your organization answers that resource's not-found code, such as 404 CAMPAIGN_NOT_FOUND.
  • An ID in a request body that isn't in your organization answers 400, such as 400 INVALID_STAGE. This way a response never confirms an ID that belongs to another organization.

Error codes

Every code the API can return. Each endpoint's reference page lists the codes that endpoint can return.

CodeStatusMeaning
Request
VALIDATION_ERROR400

The request didn't match the endpoint's schema: a missing or malformed field, a bad query parameter, or a value out of range. details.errors lists each failing field with its field, message and type.

BAD_REQUEST400

The request was malformed in a way no more specific code covers.

NO_UPDATES400

The update request contained no fields to change.

NO_SEQUENCE400

The campaign has no sequence, so there's no step to update.

SEQUENCE_VALIDATION_FAILED400

The sequence breaks a structural rule, such as an unknown step type or a linkedin_connection step without a conditional after it. The message lists every rule that failed.

INVALID_WEBHOOK_URL400

The webhook URL must use https and resolve to a public address.

INVALID_DATE_FILTER400

date_filter must be a number of days such as 30d, or an ISO 8601 timestamp.

INVALID_VARIATION400

variation must be one of a, b, unassigned or all.

INVALID_LEAD400

The lead_id in the request body isn't a lead in your organization. This is a 400 rather than a 404 so the response never confirms an ID that belongs to another organization.

INVALID_STAGE400

The stage_id in the request body isn't a stage in your organization. This is a 400 rather than a 404 for the same reason as INVALID_LEAD.

INVALID_OWNER400

The owner_id in the request body isn't a member of your organization. This is a 400 rather than a 404 for the same reason as INVALID_LEAD.

INVALID_ACCOUNT400

A sender account ID in the request isn't a connected account in your organization. Answered when a connected assistant assigns sender accounts to a campaign. This is a 400 rather than a 404 for the same reason as INVALID_LEAD.

INVALID_WINDOW400

The daily-stats window is unparseable, has from after to, or spans more than 400 days.

INVALID_GROUP_BY400

group_by must be none, sender or variation.

PAYLOAD_TOO_LARGE413

The request body is larger than 1 MB.

Authentication
UNAUTHORIZED401

The Authorization header is missing or malformed, or the API key is unknown or has been deactivated.

API_KEY_EXPIRED401

The API key is past its expiry date. Create a new key in the Victoria AI app.

FORBIDDEN403

This API key isn't allowed to make the request.

INSUFFICIENT_SCOPE403

The API key doesn't have the scope this endpoint requires, such as leads:write.

ORGANIZATION_DEACTIVATED403

The organization that owns this API key has been deactivated.

NO_DEFAULT_ORGANIZATION403

You belong to more than one organization and none is set as the default for connected assistants. Pick one on the consent screen, in Settings → Connect your AI, or with the switch_organization tool.

NO_ACTIVE_SUBSCRIPTION403

The organization doesn't have an active subscription.

TRIAL_LEAD_CAP_REACHED403

The organization is on a free trial and has used up its lead quota, so the lead wasn't created. details carries the cap, the number used and the remaining count. Subscribe in the Victoria AI app to add more.

Not found
NOT_FOUND404

No endpoint matches the path. A resource ID in the path that isn't a valid UUID also answers NOT_FOUND.

CAMPAIGN_NOT_FOUND404

No campaign with this ID exists in your organization.

LEAD_NOT_FOUND404

No lead with this ID exists in your organization.

LEAD_NOT_IN_CAMPAIGN404

The lead isn't enrolled in the campaign given by campaign_id.

DEAL_NOT_FOUND404

No deal with this ID exists in your organization.

PIPELINE_NOT_FOUND404

No pipeline with this ID exists in your organization.

WEBHOOK_NOT_FOUND404

No webhook with this ID exists on the campaign.

STEP_NOT_FOUND404

No step with this ID exists in the campaign's sequence, including inside conditional branches.

CONVERSATION_NOT_FOUND404

No conversation with this ID exists in your organization.

AI_FIELD_NOT_FOUND404

No AI field with this ID exists on the campaign.

METHOD_NOT_ALLOWED405

The path exists but doesn't accept this HTTP method.

Conflict
LEAD_ALREADY_EXISTS409

A lead with the same email or LinkedIn URL already exists in your organization. From Create a lead, this means the request named no campaign_id to enrol the existing lead in, or raced an identical request. Changing a lead's email or LinkedIn URL to another lead's answers it too. When it's known, details.existing_lead_id identifies the existing lead.

LEAD_ALREADY_IN_CAMPAIGN409

The lead already exists in your organization and is already enrolled in the campaign given by campaign_id, so there's nothing to do. details carries the lead's existing_lead_id, the campaign_id and the enrolment's sequence_lead_id.

LEAD_SUPPRESSED409

The contact is on your organization's do-not-contact list, so the lead wasn't created, enrolled or updated. details.suppressed_by is email, domain or linkedin_url, and details.value is the entry that matched.

DUPLICATE_WEBHOOK409

An active webhook for this URL already exists on the campaign. details.webhook_id identifies it.

WEBHOOK_SLOT_TAKEN409

A campaign has one response webhook, and a different URL already holds this campaign's. details.webhook_id identifies it. Send replace: true to repoint that webhook at the new URL; the previous receiver then stops getting this campaign's events.

CAMPAIGN_NOT_READY409

The campaign can't be activated: at least one readiness check is blocking, such as a step missing content, a variable with no personalization field, an unassigned or unauthenticated sender, or no enrolled leads. details.checks lists every check with its status.

CAMPAIGN_ACTIVATION_WARNINGS409

The campaign's readiness checks passed with warnings only. details.checks lists them. Repeat the request with ack_warnings: true to activate anyway.

SEQUENCE_MODIFIED409

The sequence changed after it was read. Retrieve the campaign again and retry.

STEP_ID_AMBIGUOUS409

More than one step in the sequence has this ID, so the update can't tell which one to change.

VARIATION_B_MISSING409

The campaign's sequence has no variation_b with steps, so there's nothing to test against variation A. Write one with Replace a campaign's sequence before turning A/B testing on or promoting a winner.

AB_TESTING_DISABLED409

A/B testing is off for this campaign, so there's no test to promote a winner from. Turn it on with Turn A/B testing on or off first.

ACCOUNT_NOT_CONNECTED409

A sender account being assigned to the campaign has disconnected. Reconnect it in the Victoria AI app or with a reconnect link first. details.account_ids lists the accounts.

ACCOUNT_IN_USE409

A sender account sends for one active campaign at a time, and one being assigned is already used by another active campaign. details.conflicts names each account and the campaign holding it.

ACCOUNT_LIMIT_REACHED409

Connecting a new sender account would exceed the organization's seats for that platform. details carries the max and the number used. Free a seat, add one in the Victoria AI app, or reconnect an existing account instead.

AI_FIELD_EXISTS409

An active AI field with this name already exists on the campaign. Names are compared without regard to case.

IDEMPOTENCY_KEY_REUSED409

This Idempotency-Key was already used with a different request. Use a new key for each distinct request.

IDEMPOTENCY_IN_PROGRESS409

The first request with this Idempotency-Key is still running. Retry after the Retry-After interval.

Rate limits
RATE_LIMITED429

Too many requests for this API key: more than 100 a minute to one endpoint, or 600 a minute in total. Retry after the number of seconds in the Retry-After header. See Rate limits.

DAILY_SPEND_LIMIT429

Lead-database spend from this connection (an AI connector or API key) would pass the organization's rolling 24-hour limit (5,000 credits by default). details carry daily_limit_credits, spent_credits, remaining_credits and call_ceiling_credits. Ask for fewer leads or try later; the Lead Database page and the in-app Copilot are not limited.

Server
INTERNAL_ERROR500

Something failed on our side. The response never includes internal details; quote its request_id when you contact support.

ORG_HAS_NO_MEMBERS500

The organization has no members, so the campaign can't be created. Contact support.

UPSTREAM_TIMEOUT503

A service the API depends on timed out. The request is safe to retry.

AUTH_UNAVAILABLE503

The API key couldn't be checked because the authentication service was unavailable. The request is safe to retry.

HTTP_ERROR500

An HTTP error that no more specific code covers.