Create a campaign

POST/v1/campaigns
Scope: campaigns:writeIdempotent

Creates a campaign in draft, with is_active: false. Add its sequence, AI fields, senders and leads, check it with Get the activation preflight, then activate it with Update a campaign. Set up a campaign walks through the order.

An optional sequence can be sent now. A sequence is validated before it's saved:

  • variation_a is required and variation_b is optional. Each is a list of steps.
  • Step types are view_profile, linkedin_connection, conditional, linkedin_message and email.
  • A linkedin_connection step must be followed immediately by a conditional step with branches.yes and branches.no. Conditionals nest at most two deep.
  • linkedin_message steps are only allowed inside a yes branch.
  • email steps need subject and content.
  • delay is a number of days from 0 to 90.
  • Every step needs a unique integer id, and a sequence has at most 40 steps.

The easiest valid starting point is a sequence template.

Headers

  • AuthorizationstringRequired

    Bearer followed by a space and your API key, for example Bearer vk_….

  • Idempotency-Keystring

    Any unique string, such as a UUID, that makes retrying this request safe. A repeat with the same key for at least 24 hours returns the original response instead of doing the work again. Use a new key for each distinct request.

    at most 255 characters

Request body

  • namestringRequired

    Campaign name

    at most 2,000 charactersExample "Q3 Proof First Outreach"
  • descriptionstring or null

    Campaign description

    at most 2,000 charactersDefault ""
  • sequenceobject or null

    Optional full sequence object (variation_a / variation_b step arrays); validated against structural rules

Response

201

  • campaignobject or null

    The created campaign

    Show 14 child attributes
    • idstringRequired

      Campaign UUID

      Example "550e8400-e29b-41d4-a716-446655440000"
    • namestringRequired

      Campaign name

      Example "Q1 Enterprise Outreach"
    • is_activebooleanRequired

      Whether the campaign is currently active

      Example true
    • created_atstring · date-timeRequired

      When the campaign was created

      Example "2024-01-15T10:30:00+00:00"
    • updated_atstring · date-timeRequired

      When the campaign was last updated

      Example "2024-01-20T14:45:00+00:00"
    • ab_testing_enabledboolean or null

      Whether A/B testing is enabled for message variations

      Example true
    • custom_fieldsany or null

      Custom fields — object on newer campaigns, list on legacy ones

    • descriptionstring or null

      Campaign description

      Example "Targeting enterprise accounts in the tech sector"
    • enabled_accountsarray of strings or null

      List of connected account IDs used for outreach

    • lead_database_filtersobject or null

      Lead-database search filters defining this campaign's ICP (same shape the lead database search accepts)

    • refill_policyobject or null

      Automatic lead-refill settings for the campaign: enabled, min_backlog, target_backlog, max_add_per_run, max_tokens_per_run, cooldown_hours and mode.

    • responder_enabledboolean or null

      Whether AI auto-responder is enabled

      Example true
    • sequenceany or null

      Campaign sequence: an object with variation_a and variation_b message templates, or an empty list on a campaign with no sequence yet

    • traffic_splitinteger or null

      Traffic split percentage for A/B testing (0-100)

      Example 50
  • campaign_idstring or null

    UUID of the created campaign

  • messagestring
    Default "Campaign created in draft state"
  • successboolean
    Default true

Errors

Errors share one JSON body: success, error, message, optional details, and request_id.

StatusCodeMeaning
400VALIDATION_ERROR

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.

400SEQUENCE_VALIDATION_FAILED

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.

401UNAUTHORIZED

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

401API_KEY_EXPIRED

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

403INSUFFICIENT_SCOPE

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

403ORGANIZATION_DEACTIVATED

The organization that owns this API key has been deactivated.

409IDEMPOTENCY_KEY_REUSED

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

409IDEMPOTENCY_IN_PROGRESS

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

413PAYLOAD_TOO_LARGE

The request body is larger than 1 MB.

429RATE_LIMITED

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.

500ORG_HAS_NO_MEMBERS

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

500INTERNAL_ERROR

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

503UPSTREAM_TIMEOUT

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

503AUTH_UNAVAILABLE

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

Response headers

HeaderDescription
X-Request-ID

Correlation ID for the request, also returned as request_id in error bodies. Send your own X-Request-ID, up to 128 letters, digits, ., _, : or -, and it's used instead.

RateLimit-Limit

Requests allowed to this endpoint per minute.

RateLimit-Remaining

Requests you can still send to this endpoint right now.

RateLimit-Reset

Seconds until the endpoint's full limit is available again.

Retry-After

On a 429, and on 409 IDEMPOTENCY_IN_PROGRESS: seconds to wait before retrying.

Idempotent-Replay

true when the response is a stored replay of an earlier request with the same Idempotency-Key.