> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kataven.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a campaign

> Multipart form upload — `contacts` is a CSV file, every other field is a form value. The CSV must contain at least a `phone_number` column. The campaign is created in `draft` state and dispatch starts only after `start`.



## OpenAPI

````yaml /api-spec/openapi.yaml post /api/v1/campaigns
openapi: 3.1.0
info:
  contact:
    name: Kataven
    url: https://kataven.ai
  description: |
    The Kataven Hub API is the management surface for the Kataven voice AI
    platform. Use it to create and configure voice agents, manage tools and
    knowledge, wire up telephony, run outbound campaigns, embed the chat
    widget, and read account-level settings.

    ## Authentication

    Two credential shapes are accepted on every protected endpoint:

    - **`sk_live_<account>_<rest>`** — long-lived API key. The token
      self-identifies the account, so `X-Account-ID` is not required.
      Recommended for SDK / MCP / CI / any server-to-server use. Mint via
      Hub UI → **Settings → API Keys**.
    - **Zitadel JWT** (`eyJ…`, ~1h TTL) — interactive admin sessions from
      the Hub UI. Requires the `X-Account-ID` header for tenant resolution.

    Public endpoints (`/api/accounts/*`, `/api/login`, the widget auth
    endpoints under `/api/v1/widget/auth/*`) require no Authorization
    header.

    ## Multi-tenancy

    Every protected request operates on the per-account PostgreSQL database
    identified by `X-Account-ID` (or by the `sk_live_` prefix). There is no
    cross-tenant surface; an account is a hard isolation boundary. The
    reserved account `kataven-admin` is rejected with `403`.

    ## Base URLs

    Routes are mounted at both `/` and `/hub-api/` for compatibility. SDKs
    default to the `/hub-api/` prefix on `hub.kataven.ai`, or `/v1/` on
    `api.kataven.ai`.
  license:
    name: Proprietary
  title: Kataven Hub API
  version: 0.2.0
servers:
  - url: https://api.kataven.ai/v1
    description: Production (recommended for SDKs)
  - url: https://hub.kataven.ai/hub-api/api
    description: Production (legacy path, kept for back-compat)
  - url: http://localhost:8081
    description: Local development (api-server only)
security:
  - bearerAuth: []
tags:
  - name: Agents
    description: >-
      CRUD for voice agents — the configurable units that hold a system prompt,
      voice, model, and tool/playbook/FAQ associations.
  - name: Tools
    description: Built-in and custom tools an agent can call during a conversation.
  - name: Playbooks
    description: >-
      Reusable knowledge bundles (system prompt fragments + a list of tool
      names) that can be attached to one or more agents.
  - name: FAQs
    description: Question/answer entries surfaced to agents as quick-lookup knowledge.
  - name: Marketplace
    description: Browse and install agent templates.
  - name: Integrations
    description: >-
      Third-party integrations (Stripe, Shopify, etc.) — credentials stored
      encrypted via the Secret Encryptor service.
  - name: Telephony
    description: Carrier credentials and phone-number assignment.
  - name: Calls
    description: Outbound call origination.
  - name: Recordings
    description: Call recording retrieval (presigned URL).
  - name: Call Limits
    description: >-
      Per-tenant cost caps (read-only via SDK — set by the platform team based
      on plan tier).
  - name: Campaigns
    description: Bulk-dial outbound campaigns from CSV.
  - name: API Keys
    description: >-
      sk_live_ server-to-server credentials. CRUD is gated to Hub UI auth (a
      leaked sk_live_ cannot mint another).
  - name: Widget Keys
    description: pk_live_ public identifiers used by the embeddable widget bootstrap.
  - name: Widget Admin
    description: Branding + per-agent widget policy.
  - name: Widget Auth
    description: >-
      Public cross-origin auth endpoints called from customer-page widgets (used
      by `@kataven/client`, not the server SDK).
externalDocs:
  description: ''
  url: ''
paths:
  /api/v1/campaigns:
    post:
      tags:
        - Campaigns
      summary: Create a campaign
      description: >-
        Multipart form upload — `contacts` is a CSV file, every other field is a
        form value. The CSV must contain at least a `phone_number` column. The
        campaign is created in `draft` state and dispatch starts only after
        `start`.
      operationId: postApiV1Campaigns
      parameters:
        - description: Tenant database. Required when using a Zitadel JWT.
          in: header
          name: X-Account-ID
          schema:
            type: string
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                name:
                  type: string
                agent_id:
                  type: string
                phone_number_id:
                  type: string
                max_concurrent_calls:
                  type: integer
                retries_per_contact:
                  type: integer
                retry_delay_seconds:
                  type: integer
                scheduled_at:
                  type: string
                contacts:
                  type: string
                  format: binary
          multipart/form-data:
            schema:
              type: object
        description: >-
          Campaign name | Agent uuid | Phone number uuid | 1-100 (default 5) |
          0-5 (default 0) | ≥60 (default 300) | RFC3339 timestamp; rejected if
          in the past | CSV file
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/data.Campaign'
          description: Created
        '400':
          content:
            application/json:
              schema:
                type: string
          description: Invalid form / CSV
        '500':
          content:
            application/json:
              schema:
                type: string
          description: Database error
      security:
        - bearerAuth: []
components:
  schemas:
    data.Campaign:
      properties:
        agent_id:
          type: string
        completed_at:
          type: string
        created_at:
          type: string
        created_by:
          type: string
        id:
          type: string
        max_concurrent_calls:
          type: integer
        name:
          type: string
        phone_number_id:
          type: string
        retries_per_contact:
          type: integer
        retry_delay_seconds:
          type: integer
        scheduled_at:
          type: string
        started_at:
          type: string
        status:
          type: string
      type: object
  securitySchemes:
    bearerAuth:
      in: header
      name: Authorization
      type: apiKey

````