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

# Initiate AI Call

> Triggers direct AI calls to candidates for a RIA campaign project. Each candidate receives an outbound AI call with the configured script. Candidates are created on-the-fly if they do not already exist.

<Tip>
  Use the same `ats_job_id` across multiple requests to call additional candidates on an existing campaign project.
</Tip>

## Dynamic Variables

Both `first_message` and `instructions` support variable substitution using the `{{variable_name}}` syntax.

`first_message` is optional and defaults to `"Hello"` if not provided.

### Built-in Variables

These are automatically resolved from the candidate, project, and sender context:

| Variable                   | Description                               |
| -------------------------- | ----------------------------------------- |
| `{{candidate_first_name}}` | Candidate's first name                    |
| `{{candidate_last_name}}`  | Candidate's last name                     |
| `{{candidate_full_name}}`  | Candidate's full name                     |
| `{{candidate_email}}`      | Candidate's email                         |
| `{{candidate_phone}}`      | Candidate's phone number                  |
| `{{sender_first_name}}`    | Sender's first name                       |
| `{{sender_last_name}}`     | Sender's last name                        |
| `{{sender_full_name}}`     | Sender's full name                        |
| `{{sender_company}}`       | Company name (from job or sender profile) |

## WhatsApp Template Variables

When using `whatsapp_notifications`, the `template_variables` object accepts two value types:

1. **Built-in resolver reference** — `{"body_1": "{{candidate_first_name}}"}` resolves automatically using candidate/job/sender data.
2. **Literal text** — `{"body_2": "Thursday, 21 May 2026, 6:00 PM..."}` is passed through as-is.

## Candidate Custom Fields

Each candidate object accepts an optional `custom_fields` object containing key-value pairs. These fields are stored on the candidate record.

## Working Hours

When `schedule_at` is not provided, calls are scheduled immediately. Use `call_settings.working_hours` to restrict when calls can be placed.

* `enabled`: `true` (default) or `false` to bypass working-hours checks.
* Each day is a list of shifts with `start_minute` and `end_minute` in minutes from midnight UTC.
* If the current time is outside all configured shifts, the call is delayed until the start of the next available shift.
* `schedule_at` is always respected as-is and skips working-hours adjustment.

## Example Request

```json theme={null}
{
  "ats_job_id": "ats-job-12345",
  "candidates": [
    {
      "id": "ats-candidate-001",
      "name": "John Doe",
      "email": "john.doe@example.com",
      "phone": "+917873476062",
      "custom_fields": {
        "years_of_experience": "5",
        "current_company": "Acme Corp"
      }
    }
  ],
  "instructions": "You are a recruiter for {{sender_company}}. Greet the candidate and screen them about their experience with distributed systems.",
  "extract_variables": [
    {
      "label": "Years of Experience",
      "type": "integer",
      "description": "How many years of professional experience does the candidate have?"
    }
  ],
  "call_settings": {
    "retry_policy": {
      "conditions": ["missed", "declined"],
      "intervals": [
        {
          "type": "delay",
          "duration": 15,
          "unit": "minutes"
        }
      ]
    },
    "working_hours": {
      "enabled": true,
      "monday": [{ "start_minute": 540, "end_minute": 1020 }],
      "tuesday": [{ "start_minute": 540, "end_minute": 1020 }],
      "wednesday": [{ "start_minute": 540, "end_minute": 1020 }],
      "thursday": [{ "start_minute": 540, "end_minute": 1020 }],
      "friday": [{ "start_minute": 540, "end_minute": 1020 }],
      "saturday": [],
      "sunday": []
    },
    "whatsapp_notifications": {
      "pre_call": {
        "template_name": "interview_reminder",
        "template_variables": {
          "body_1": "{{candidate_first_name}}",
          "body_2": "Thursday, 21 May 2026, 6:00 PM – 8:45 PM (Networking Dinner included)",
          "body_3": "Citymax Business Bay, Dubai",
          "button_Yes": "Awesome! Here's the registration link to complete your payment and confirm your seat: https://luma.com/al5h68ce",
          "button_No": "Thanks for letting us know. We'll miss you this time, but we'll keep you updated on future events."
        }
      },
      "fallback": {
        "template_name": "call_fallback",
        "template_variables": {
          "body_1": "{{candidate_first_name}}",
          "body_2": "We tried calling you about the position but couldn't reach you. Please reply with your availability."
        }
      }
    }
  },
  "schedule_at": "2026-05-27T10:00:00Z"
}
```

## Example Response

```json theme={null}
{
  "success": true,
  "data": {
    "project_id": "64a1b2c3d4e5f6a7b8c9d0e1",
    "project_url": "https://platform.tidyhire.app/app/projects/64a1b2c3d4e5f6a7b8c9d0e1",
    "calls": [
      {
        "id": "64a1b2c3d4e5f6a7b8c9d0e4",
        "candidate_id": "ats-candidate-001",
        "name": "John Doe",
        "email": "john.doe@example.com",
        "phone": "+917873476062",
        "status": "success",
        "message": "Call initiated"
      }
    ]
  }
}
```


## OpenAPI

````yaml POST /api/public/v1/call/initiate
openapi: 3.1.0
info:
  title: Tidyhire API
  description: Tidyhire Public API for ATS integrations
  version: 1.0.0
servers:
  - url: https://api.tidyhire.app
    description: Production
security:
  - apiKey: []
paths:
  /api/public/v1/call/initiate:
    post:
      tags:
        - Call
      summary: Initiate AI Call
      description: >-
        Triggers direct AI calls to candidates for a RIA campaign project. Each
        candidate receives an outbound AI call with the configured script.
        Candidates are created on-the-fly if they do not already exist.
      operationId: initiateCall
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CallRequest'
      responses:
        '200':
          description: Success.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CallSuccessResponse'
        '400':
          description: Validation Error or project not found / not a campaign project.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
        '401':
          description: Unauthorized.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UnauthorizedResponse'
        '500':
          description: Internal Error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalErrorResponse'
      security:
        - apiKey: []
components:
  schemas:
    CallRequest:
      type: object
      required:
        - ats_job_id
        - candidates
        - instructions
      properties:
        ats_job_id:
          type: string
          minLength: 1
          maxLength: 200
          description: >-
            A unique job identifier from your ATS. Must match a RIA campaign
            project.
          example: ats-job-12345
        candidates:
          type: array
          items:
            $ref: '#/components/schemas/CallCandidate'
          minItems: 1
          maxItems: 50
          description: List of candidates to call. Minimum 1, maximum 50 per request.
        first_message:
          type: string
          minLength: 1
          default: Hello
          description: >-
            Opening message the AI speaks when the candidate answers. Optional —
            defaults to "Hello". Supports built-in variables like
            {{candidate_first_name}} and {{sender_company}}.
          example: Hello {{candidate_first_name}}, this is {{sender_company}} calling.
        instructions:
          type: string
          minLength: 1
          description: >-
            AI behavior instructions for the call. Supports the same built-in
            variable substitution as first_message.
          example: >-
            You are a recruiter for {{sender_company}}. Screen the candidate
            about their experience with distributed systems.
        assistant_settings:
          $ref: '#/components/schemas/AssistantSettings'
        extract_variables:
          type: array
          description: >-
            Optional data points to extract from the conversation. The AI will
            attempt to capture these values during the call.
          items:
            type: object
            required:
              - label
              - type
              - description
            properties:
              label:
                type: string
                minLength: 1
                description: Human-readable name for the variable.
                example: Years of Experience
              type:
                type: string
                enum:
                  - string
                  - single_select
                  - boolean
                  - integer
                  - number
                  - array
                  - date
                  - datetime
                description: Data type of the variable.
                example: integer
              description:
                type: string
                minLength: 1
                description: Prompt that tells the AI how to extract this value.
                example: >-
                  How many years of professional experience does the candidate
                  have?
              format_example:
                type: string
                description: Example of the expected output format.
                example: '5'
              choices:
                type: array
                items:
                  type: string
                description: Allowed values for single_select type.
                example:
                  - 1-3
                  - 4-6
                  - 7-10
                  - 10+
        call_settings:
          $ref: '#/components/schemas/CallSettings'
        schedule_at:
          type: string
          format: date-time
          description: >-
            ISO 8601 datetime to schedule the call for later. If omitted, the
            call is initiated immediately.
          example: '2026-05-27T10:00:00Z'
    CallSuccessResponse:
      type: object
      example:
        success: true
        data:
          project_id: 64a1b2c3d4e5f6a7b8c9d0e1
          project_url: https://platform.tidyhire.app/app/projects/64a1b2c3d4e5f6a7b8c9d0e1
          calls:
            - id: 64a1b2c3d4e5f6a7b8c9d0e4
              candidate_id: ats-candidate-001
              name: John Doe
              email: john.doe@example.com
              phone: '+917873476062'
              status: success
              message: Call initiated
      properties:
        success:
          type: boolean
          example: true
        data:
          type: object
          properties:
            project_id:
              type: string
              description: The project ID.
            project_url:
              type: string
              description: Dashboard URL for the project.
            calls:
              type: array
              description: Per-call results.
              items:
                $ref: '#/components/schemas/CallResult'
    ValidationErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        code:
          type: string
          example: VALIDATION_ERROR
        message:
          type: string
          example: Request validation failed
        errors:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
                example: candidates.0.name
              message:
                type: string
                example: Candidate name must be at least 3 characters
    UnauthorizedResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        message:
          type: string
          example: Unauthorized
        error:
          type: string
          example: INVALID_API_KEY
    InternalErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        code:
          type: string
          example: UNKNOWN_ERROR
        message:
          type: string
          example: Something went wrong.
    CallCandidate:
      type: object
      required:
        - id
        - name
        - email
        - phone
      properties:
        id:
          type: string
          minLength: 1
          description: >-
            A unique candidate identifier from your system (e.g. ATS candidate
            ID). Used to deduplicate candidates within a project.
          example: ats-candidate-001
        name:
          type: string
          minLength: 1
          description: Full name of the candidate. Auto-converted to Title Case.
          example: John Doe
        email:
          type: string
          format: email
          description: Email address of the candidate. Auto-converted to lowercase.
          example: john.doe@example.com
        phone:
          type: string
          description: Phone number of the candidate in E.164 format (e.g. +917873476062).
          example: '+917873476062'
    AssistantSettings:
      type: object
      properties:
        gender:
          type: string
          enum:
            - Male
            - Female
          description: Gender of the AI assistant voice.
        language:
          type: object
          properties:
            code:
              type: string
              description: Language code (e.g., "en").
            provider:
              type: string
              description: Speech-to-text provider.
            model:
              type: string
              description: Speech-to-text model (optional).
            label:
              type: string
              description: Human-readable language label (optional).
          required:
            - code
            - provider
        llm:
          type: object
          properties:
            provider:
              type: string
              description: LLM provider.
            model:
              type: string
              description: LLM model name.
            temperature:
              type: number
              description: Sampling temperature.
          required:
            - provider
            - model
            - temperature
        tts:
          type: object
          properties:
            provider:
              type: string
              description: Text-to-speech provider.
            model:
              type: string
              description: TTS model name.
            id:
              type: string
              description: TTS voice ID.
            speed:
              type: number
              description: Voice speed multiplier (optional).
            name:
              type: string
              description: Voice name.
            gender:
              type: string
              description: Voice gender.
            language:
              type: string
              description: Voice language code.
          required:
            - provider
            - model
            - id
            - name
            - gender
            - language
        effect:
          type: object
          properties:
            name:
              type: string
              enum:
                - Keyboard
                - Office
                - none
              description: Background effect name.
            volume:
              type: number
              description: Background effect volume (optional).
          required:
            - name
        tools:
          type: array
          items:
            type: string
          description: Optional list of tools the assistant can use.
        min_endpointing_delay:
          type: number
          description: Minimum endpointing delay in seconds (optional).
        max_endpointing_delay:
          type: number
          description: Maximum endpointing delay in seconds (optional).
      description: >-
        AI assistant configuration for the call. Defaults to a female English
        voice with standard recruiter behaviour. [Book a call with the
        team](https://cal.id/team/tidyhire/support-session) to customize.
    CallSettings:
      type: object
      description: >-
        Optional retry policy, working hours, and WhatsApp notification
        configuration.
      properties:
        retry_policy:
          type: object
          description: >-
            Conditions under which to retry a failed call and when to retry. No
            retries are attempted if omitted.
          properties:
            conditions:
              type: array
              items:
                type: string
                enum:
                  - missed
                  - declined
                  - sent_to_voicemail
                  - silenced
                  - abruptly_disconnected
              description: Call failure reasons that should trigger a retry.
              example:
                - missed
                - declined
            intervals:
              type: array
              items:
                type: object
                properties:
                  type:
                    type: string
                    enum:
                      - delay
                      - specific_datetime
                    description: Whether to retry after a delay or at a specific time.
                  duration:
                    type: number
                    description: Delay duration (used when type is "delay").
                    example: 15
                  unit:
                    type: string
                    enum:
                      - minutes
                      - hours
                      - days
                    description: Time unit for the delay (used when type is "delay").
                    example: minutes
                  datetime:
                    type: string
                    description: >-
                      ISO 8601 timestamp for the retry (used when type is
                      "specific_datetime").
                    example: '2026-05-27T10:15:00Z'
              description: >-
                Retry intervals. Each entry defines when a retry attempt should
                happen. If omitted, retries use default timing.
              example:
                - type: delay
                  duration: 15
                  unit: minutes
        working_hours:
          $ref: '#/components/schemas/WorkingHours'
        whatsapp_notifications:
          type: object
          description: WhatsApp template notifications sent around the AI call.
          properties:
            pre_call:
              type: object
              description: WhatsApp template sent to the candidate before the AI call.
              required:
                - template_name
              properties:
                template_name:
                  type: string
                  minLength: 1
                  description: Name of the approved WhatsApp template to send.
                  example: interview_reminder
                template_variables:
                  type: object
                  additionalProperties:
                    type: string
                  description: >-
                    Key-value variables to substitute into the WhatsApp
                    template. Values can be literal text or built-in resolver
                    references (e.g. {{candidate_first_name}}).
                  default: {}
                  example:
                    body_1: '{{candidate_first_name}}'
                    body_2: >-
                      Thursday, 21 May 2026, 6:00 PM – 8:45 PM (Networking
                      Dinner included)
                    body_3: Citymax Business Bay, Dubai
                    button_Yes: >-
                      Awesome! Here's the registration link to complete your
                      payment and confirm your seat: https://luma.com/al5h68ce
                    button_No: >-
                      Thanks for letting us know. We'll miss you this time, but
                      we'll keep you updated on future events.
            fallback:
              type: object
              description: >-
                WhatsApp template sent to the candidate if the AI call fails and
                cannot be retried.
              required:
                - template_name
              properties:
                template_name:
                  type: string
                  minLength: 1
                  description: Name of the approved WhatsApp template to send.
                  example: call_fallback
                template_variables:
                  type: object
                  additionalProperties:
                    type: string
                  description: >-
                    Key-value variables to substitute into the WhatsApp
                    template. Values can be literal text or built-in resolver
                    references (e.g. {{candidate_first_name}}).
                  default: {}
                  example:
                    body_1: '{{candidate_first_name}}'
                    body_2: >-
                      We tried calling you about the Senior Engineer position
                      but couldn't reach you. Please reply with your
                      availability.
    CallResult:
      type: object
      properties:
        id:
          type: string
          nullable: true
          description: Transaction ID for the scheduled call, or null if failed.
          example: 64a1b2c3d4e5f6a7b8c9d0e4
        candidate_id:
          type: string
          description: The candidate ID from your system.
          example: ats-candidate-001
        name:
          type: string
          description: Candidate name.
          example: John Doe
        email:
          type: string
          description: Candidate email.
          example: john.doe@example.com
        phone:
          type: string
          description: Candidate phone number.
          example: '+917873476062'
        status:
          type: string
          enum:
            - success
            - failed
          description: Candidate-level status.
          example: success
        message:
          type: string
          description: Human-readable status message.
          example: A call is scheduled for this candidate.
    WorkingHours:
      type: object
      properties:
        enabled:
          type: boolean
          default: true
          description: >-
            Whether to restrict call scheduling to the configured shifts. Set to
            false to bypass working-hours checks.
          example: true
        monday:
          type: array
          items:
            $ref: '#/components/schemas/WorkingHoursShift'
          description: >-
            Working shifts for Monday. Empty means no calls are placed on Monday
            unless an explicit schedule_at is provided.
          example:
            - start_minute: 540
              end_minute: 1020
        tuesday:
          type: array
          items:
            $ref: '#/components/schemas/WorkingHoursShift'
          description: Working shifts for Tuesday.
        wednesday:
          type: array
          items:
            $ref: '#/components/schemas/WorkingHoursShift'
          description: Working shifts for Wednesday.
        thursday:
          type: array
          items:
            $ref: '#/components/schemas/WorkingHoursShift'
          description: Working shifts for Thursday.
        friday:
          type: array
          items:
            $ref: '#/components/schemas/WorkingHoursShift'
          description: Working shifts for Friday.
        saturday:
          type: array
          items:
            $ref: '#/components/schemas/WorkingHoursShift'
          description: Working shifts for Saturday.
        sunday:
          type: array
          items:
            $ref: '#/components/schemas/WorkingHoursShift'
          description: Working shifts for Sunday.
    WorkingHoursShift:
      type: object
      required:
        - start_minute
        - end_minute
      properties:
        start_minute:
          type: integer
          minimum: 0
          maximum: 1439
          description: Start time of the shift in minutes from midnight UTC.
          example: 540
        end_minute:
          type: integer
          minimum: 1
          maximum: 1440
          description: >-
            End time of the shift in minutes from midnight UTC. This value is
            exclusive.
          example: 1020
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-tidyhire-api-key
      description: Your Tidyhire API key

````