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

# Enroll multiple contacts

> Schedule up to 1,000 contacts in a single request — the API equivalent of CSV import.

Validation is **per-contact**: valid contacts are scheduled, invalid ones are returned in `rejected[]` with a reason. The whole batch only fails when no contacts pass validation, the agent is misconfigured, or there aren't enough credits for the accepted contacts.

A `202` means the accepted contacts passed all upfront checks; sequence creation happens asynchronously in the background. Phone numbers are normalized before duplicate detection, so `+15551234567` and `+1 (555) 123-4567` collide — only the first occurrence is scheduled unless `allowDuplicates` is set.

**Contact chaining** (`groupByField`): contacts are grouped by the value of the named custom variable. Only the first valid contact in each group is scheduled immediately; the rest activate automatically when an earlier call in the same group does not reach a successful outcome.



## OpenAPI

````yaml /openapi.json post /agents/{agentId}/schedule/sequences
openapi: 3.1.0
info:
  title: Julian API
  version: 1.0.0
  description: >-
    API for Julian, 11x's AI calling platform. Programmatically enroll contacts
    into agent calling sequences, manage sequences, and track credit usage. All
    requests are authenticated with an organization API key in the `x-api-key`
    header and rate limited to 10 requests per second per key (HTTP 429 when
    exceeded).
servers:
  - url: https://julian.11x.ai/api/v1
security:
  - apiKeyAuth: []
tags:
  - name: Scheduling
    description: Enroll contacts into an agent's calling sequence.
  - name: Sequences
    description: Manage active sequences.
  - name: Agents
    description: Read agent configuration.
  - name: Conversation Meetings
    description: >-
      Manage the meeting booked during a conversation — list its attendees, add
      attendees before it starts, and cancel it. Every endpoint is addressed by
      an `entityId` that identifies the conversation. Today only voice calls are
      supported, with the form of the call prefix followed by the call ID (e.g.
      `call.abc123`). The meeting is resolved from the calendar booking created
      during the conversation, and the calendar provider remains the source of
      truth.
  - name: Conversation Metadata
    description: >-
      Retrieve completed conversation data asynchronously — designed for batch
      ingestion, backfills, and reconciliation jobs that pull conversation
      metadata instead of receiving it through a webhook.


      **Recommended batch ingestion flow:**


      1. Call `GET /conversations/search/{agentId}` with the time window you
      want to ingest (e.g. yesterday or the last seven days).

      2. Iterate through the returned `sequenceIds`.

      3. For each sequence ID, call `GET /conversations/metadata/{sequenceId}`.

      4. Store the returned `metadata` array in your warehouse.

      5. Use `limit`, `offset`, and `hasMore` to paginate through larger
      backfills.
  - name: Credits
    description: Track credit utilization.
  - name: Webhooks
    description: Events Julian sends to your endpoint.
paths:
  /agents/{agentId}/schedule/sequences:
    post:
      tags:
        - Scheduling
      summary: Enroll multiple contacts
      description: >-
        Schedule up to 1,000 contacts in a single request — the API equivalent
        of CSV import.


        Validation is **per-contact**: valid contacts are scheduled, invalid
        ones are returned in `rejected[]` with a reason. The whole batch only
        fails when no contacts pass validation, the agent is misconfigured, or
        there aren't enough credits for the accepted contacts.


        A `202` means the accepted contacts passed all upfront checks; sequence
        creation happens asynchronously in the background. Phone numbers are
        normalized before duplicate detection, so `+15551234567` and `+1 (555)
        123-4567` collide — only the first occurrence is scheduled unless
        `allowDuplicates` is set.


        **Contact chaining** (`groupByField`): contacts are grouped by the value
        of the named custom variable. Only the first valid contact in each group
        is scheduled immediately; the rest activate automatically when an
        earlier call in the same group does not reach a successful outcome.
      operationId: scheduleSequencesBulk
      parameters:
        - $ref: '#/components/parameters/AgentId'
        - name: Idempotency-Key
          in: header
          required: false
          description: >-
            Optional, max 255 characters. Retries with the same key won't
            re-schedule the same batch. The key dedupes on the key alone, not
            payload content — to resubmit fixed rows after a partial 202, use a
            **new** key.
          schema:
            type: string
            maxLength: 255
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BulkScheduleRequest'
      responses:
        '202':
          description: >-
            Batch accepted for asynchronous processing. Check `rejected[]` for
            per-contact validation failures — valid contacts are scheduled even
            when others fail.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkScheduleResponse'
        '400':
          description: >-
            Request rejected. `error` is one of: `INVALID_REQUEST_BODY` (body is
            not valid JSON), `INVALID_REQUEST` (schema violation — empty
            `contacts`, more than 1000 contacts, or `allowDuplicates` combined
            with `groupByField`), `INVALID_TIMEZONE` (top-level timezone
            invalid), `MISSING_TIMEZONE` (agent has no configured timezones),
            `INVALID_IDEMPOTENCY_KEY` (header exceeds 255 characters),
            `ALL_CONTACTS_REJECTED` (every contact failed validation — see
            `rejected[]`), `INSUFFICIENT_CREDITS` (not enough credits for the
            accepted contacts — top up and retry).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BulkScheduleError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/AgentNotFound'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  parameters:
    AgentId:
      name: agentId
      in: path
      required: true
      description: ID of the agent, e.g. `agent.abc123`.
      schema:
        type: string
  schemas:
    BulkScheduleRequest:
      type: object
      required:
        - contacts
      properties:
        contacts:
          type: array
          minItems: 1
          maxItems: 1000
          description: Contacts to enroll (1–1,000).
          items:
            $ref: '#/components/schemas/BulkContact'
        timezone:
          type: string
          description: >-
            Default IANA timezone applied to contacts that don't supply their
            own. If omitted, falls back to the agent's first configured
            timezone.
          example: America/New_York
        groupByField:
          type: string
          description: >-
            Group contacts by the value of a custom variable for contact
            chaining. Only the first valid contact per group is scheduled
            immediately. Cannot be combined with `allowDuplicates`.
          example: account_id
        normalizeFields:
          type: array
          items:
            type: string
          description: >-
            Custom variable names to title-case before scheduling (e.g. `"JOHN"`
            → `"John"`). Only applied for organizations in the normalization
            allowlist.
        allowDuplicates:
          type: boolean
          default: false
          description: >-
            Allow duplicate phone numbers within the batch. Cannot be combined
            with `groupByField`.
    BulkScheduleResponse:
      type: object
      required:
        - batchId
        - total
        - accepted
        - rejected
      properties:
        batchId:
          type: string
          format: uuid
          example: 550e8400-e29b-41d4-a716-446655440000
        total:
          type: integer
          description: Total contacts submitted.
          example: 100
        accepted:
          type: integer
          description: Contacts that passed validation and will be scheduled.
          example: 98
        rejected:
          type: array
          description: Per-contact validation failures (empty when all passed).
          items:
            $ref: '#/components/schemas/RejectedContact'
    BulkScheduleError:
      allOf:
        - $ref: '#/components/schemas/Error'
        - type: object
          properties:
            total:
              type: integer
              description: Present on `ALL_CONTACTS_REJECTED`.
            accepted:
              type: integer
              description: Present on `ALL_CONTACTS_REJECTED` (always 0).
            rejected:
              type: array
              description: Present on `ALL_CONTACTS_REJECTED` — per-contact reasons.
              items:
                $ref: '#/components/schemas/RejectedContact'
    BulkContact:
      type: object
      required:
        - name
        - phoneNumber
      description: >-
        In addition to the fields below, include every custom input variable
        required by the agent as a top-level string property.
      properties:
        name:
          type: string
          example: John Doe
        phoneNumber:
          type: string
          description: Phone number in E.164 format.
          example: '+15551234567'
        phoneNumberExt:
          type: string
          description: DTMF extension dialed after the call connects.
        timezone:
          type: string
          description: Per-contact IANA timezone override.
        scheduledAt:
          type: string
          format: date-time
          description: Per-contact scheduled time (ISO 8601, must be in the future).
        toEmailAddress:
          type: string
          format: email
          description: Required when the agent's sequence contains email steps.
      additionalProperties:
        type: string
        description: Custom input variables defined on the agent.
    RejectedContact:
      type: object
      properties:
        index:
          type: integer
          description: Zero-based index of the contact in the submitted `contacts` array.
          example: 3
        phoneNumber:
          type: string
          example: '+15551234567'
        reason:
          type: string
          description: Rejection reason code.
          enum:
            - MISSING_NAME
            - MISSING_PHONE_NUMBER
            - INVALID_PHONE_NUMBER
            - INVALID_EMAIL
            - INVALID_TIMEZONE
            - INVALID_SCHEDULED_AT
            - MISSING_CUSTOM_VARIABLES
            - DUPLICATE_PHONE_NUMBER
        error:
          type: string
          description: Human-readable explanation.
          example: 'Missing custom input variables: account_id.'
    Error:
      type: object
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: Machine-readable error code.
          example: INVALID_PHONE_NUMBER
        message:
          type: string
          description: Human-readable explanation.
  responses:
    Unauthorized:
      description: >-
        `UNAUTHORIZED` or `INVALID_API_KEY` — API key missing, invalid, or not
        authorized for this agent's organization.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missingApiKey:
              summary: Missing API key
              value:
                error: UNAUTHORIZED
                message: >-
                  API key is required. Please provide your API key in the
                  x-api-key header.
            invalidApiKey:
              summary: Invalid API key
              value:
                error: INVALID_API_KEY
                message: The provided API key is invalid.
    AgentNotFound:
      description: >-
        `AGENT_NOT_FOUND` — agent ID does not exist or is not owned by your
        organization.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    InternalServerError:
      description: >-
        `INTERNAL_SERVER_ERROR` — unexpected server error. Retry with backoff
        and contact the 11x team if it persists.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: INTERNAL_SERVER_ERROR
            message: Internal Server Error. Please contact 11x team.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: Organization API key. Get it from the 11x team or from the platform.

````