# API Documentation

## Overview

The HeyMilo API provides programmatic access to the HeyMilo recruitment and interview platform, empowering developers to seamlessly integrate with our AI-powered hiring system. With this API, you can:

* Retrieve and manage candidate information
* Oversee and update job postings
* Set up webhooks for real-time event notifications
* Access detailed interview data and transcripts
* Ingest candidate data for processing

## Base URL

All API endpoints use the following base URL:

```
https://api.heymilo.network
```

## Authentication

**Important**: All API requests require authentication using the `X-API-KEY` header.

```http
X-API-KEY: your_api_key_here
```

This header must be included in every request to the API. Requests without a valid API key will receive a 401 Unauthorized response.

## Rate Limiting

The API implements rate limiting to ensure fair usage:

* **Default Rate Limit**: 300 requests per minute per API key
* Rate limit headers are included in responses to help you track usage
* If you exceed the rate limit, you'll receive a 429 Too Many Requests response

## Response Codes

The API uses standard HTTP status codes:

* `200` - Success
* `401` - Unauthorized (missing or invalid API key)
* `404` - Not Found
* `422` - Validation Error
* `429` - Too Many Requests (rate limit exceeded)
* `500` - Internal Server Error

***

## API Endpoints

### 1. Health Check

**GET** `/health`

Check the health status of the API Gateway.

#### Response

```json
{
  "message": "API Gateway is running successfully",
  "status": 200
}
```

#### Response Schema

| Field     | Type    | Description      |
| --------- | ------- | ---------------- |
| `message` | string  | Status message   |
| `status`  | integer | HTTP status code |

***

### 2. Get Job Postings

**GET** `/postings`

Retrieve job postings with pagination support.

#### Query Parameters

| Parameter | Type    | Required | Default | Description                |
| --------- | ------- | -------- | ------- | -------------------------- |
| `page`    | integer | No       | 1       | Page number for pagination |
| `limit`   | integer | No       | 10      | Number of results per page |

#### Example Request

```bash
curl -X GET "https://api.heymilo.network/api/postings?page=1&limit=10" \
  -H "X-API-KEY: your_api_key_here"
```

#### Response

```json
{
  "postings": [
    {
      "posting_id": "posting_123",
      "title": "Software Engineer",
      "name": "software-engineer",
      "description": "We are looking for a talented software engineer to join our team...",
      "company_id": "comp_67890",
      "created_at": 1652345678,
      "last_updated": 1652345678,
      "archived": false,
      "deadline": 1662345678,
      "finalized": true,
      "phone_number_id": "pn_12345",
      "root_level_configs": {
        "instructions": "General instructions for all agents in this posting",
        "company_overview": "Our company is a leading tech firm specializing in AI solutions",
        "job_overview": "This role involves developing backend services using Python and FastAPI",
        "interview_process_overview": "The interview process consists of resume screening, technical interview, and culture fit assessment",
        "language": "en",
        "interviewer_name": "Alex Johnson"
      },
      "agentic_workflow": [
        {
          "type": "resume",
          "unique_id": "resume_screen_1",
          "config": {
            "instructions": "Evaluate resumes based on technical skills and experience",
            "knockout_enabled": true,
            "min_evaluation_score": 0.7,
            "mandatory": true
          }
        },
        {
          "type": "web_interview",
          "unique_id": "tech_interview_1",
          "config": {
            "instructions": "Conduct a technical interview focusing on Python and system design",
            "interviewer_name": "Alex Johnson",
            "video": true,
            "voice_id": "voice-2",
            "web_interview_config": {
              "backdrop_image_url": "https://example.com/backdrop.jpg",
              "avatar_image_url": "https://example.com/avatar.jpg",
              "show_transcript": true,
              "vapi_call_config": {
                "end_call_message": "Thank you for your time. The interview is now complete.",
                "idle_message_max_spoken_count": 3,
                "idle_timeout_seconds": 10,
                "wait_seconds": 2.4,
                "backoff_seconds": 2
              }
            }
          }
        },
        {
          "type": "conversational_sms",
          "unique_id": "sms_screen_1",
          "config": {
            "instructions": "Ask preliminary questions about availability and salary expectations",
            "knockout_enabled": true
          }
        }
      ],
      "url_key": "unique_url_key_for_posting"
    },
    {
      "posting_id": "post_67890",
      "title": "Product Manager",
      "name": "product-manager",
      "description": "Join our product team to help shape the future of our platform...",
      "company_id": "comp_67890",
      "created_at": 1652345679,
      "last_updated": 1652345679,
      "archived": false,
      "deadline": 1662345679,
      "finalized": true,
      "phone_number_id": "pn_67890",
      "root_level_configs": {
        "instructions": "General instructions for all agents in this posting",
        "company_overview": "Our company is a leading tech firm specializing in AI solutions",
        "job_overview": "This role involves product management for our AI platform",
        "language": "en"
      },
      "agentic_workflow": [
        {
          "type": "resume",
          "unique_id": "resume_screen_1",
          "config": {
            "instructions": "Evaluate resumes based on product management experience",
            "knockout_enabled": true,
            "min_evaluation_score": 0.7,
            "mandatory": true
          }
        }
      ],
      "url_key": "unique_url_key_for_posting"
    }
  ],
  "total": 42,
  "page": 1,
  "limit": 10,
  "total_pages": 5
}
```

#### Response Schema

| Field         | Type    | Description                 |
| ------------- | ------- | --------------------------- |
| `postings`    | array   | List of job posting objects |
| `total`       | integer | Total number of postings    |
| `page`        | integer | Current page number         |
| `limit`       | integer | Number of postings per page |
| `total_pages` | integer | Total number of pages       |

**Posting Object Schema:**

| Field                | Type    | Description                                                   |
| -------------------- | ------- | ------------------------------------------------------------- |
| `posting_id`         | string  | Unique identifier for the posting                             |
| `title`              | string  | Job title                                                     |
| `name`               | string  | URL-friendly name for the posting                             |
| `description`        | string  | Job description                                               |
| `company_id`         | string  | Company identifier                                            |
| `created_at`         | float   | Timestamp when posting was created                            |
| `last_updated`       | float   | Timestamp when posting was last updated                       |
| `archived`           | boolean | Whether the posting is archived                               |
| `deadline`           | float   | Deadline for the posting (optional)                           |
| `finalized`          | boolean | Whether the posting is finalized                              |
| `phone_number_id`    | string  | Associated phone number ID                                    |
| `root_level_configs` | object  | Top-level settings like instructions and company/job overview |
| `agentic_workflow`   | array   | List of agent-driven steps (e.g., resume, web interview)      |
| `url_key`            | string  | Unique URL key for candidate ingestion                        |

**Root Level Configs Schema:**

| Field                        | Type   | Description                           |
| ---------------------------- | ------ | ------------------------------------- |
| `instructions`               | string | General instructions for agents       |
| `company_overview`           | string | Overview of the company (optional)    |
| `job_overview`               | string | Overview of the job (optional)        |
| `interview_process_overview` | string | Interview process overview (optional) |
| `language`                   | string | Communication language                |
| `interviewer_name`           | string | Name of the interviewer (optional)    |

**Agentic Workflow Configs Schema:**

| Field       | Type   | Description                                                   |
| ----------- | ------ | ------------------------------------------------------------- |
| `type`      | string | Step type (e.g., resume, web\_interview, conversational\_sms) |
| `unique_id` | string | Unique ID for the workflow step                               |
| `config`    | object | Configuration specific to the workflow type                   |

### 3. Get Interview Details by Interview ID

**GET** `/interview/{interview_id}`

Retrieve detailed information about a specific interview, including candidate details, scores, and recordings.

#### Path Parameters

| Parameter      | Type   | Required | Description                             |
| -------------- | ------ | -------- | --------------------------------------- |
| `interview_id` | string | Yes      | The unique identifier for the interview |

#### Example Request

```bash
curl -X GET "https://api.heymilo.network/api/interview/{interview_id}" \
  -H "X-API-KEY: your_api_key_here"
```

#### Response

```json
{
    "interview_id": "int_abc123",
    "details": {
        "interview_id": "int_abc123",
        "candidate_id": "cand_xyz789",
        "interviewed_on": 1676452800,
        "score": 85.5,
        "name": "John Smith",
        "email": "john.smith@example.com",
        "actions": {
            "can_view": true,
            "can_download": true
        },
        "status": "completed",
        "workflow_status": {
            "interview_id": "int_abc123",
            "step_by_step": [
            {
                "complete": true,
                "required": true,
                "order": 1,
                "id": "resume_upload",
                "started": true,
                "details": {
                "details": "Resume uploaded and analyzed"
                },
                "last_updated_timestamp": 1676452800
            },
            {
                "complete": true,
                "required": true,
                "order": 2,
                "id": "web_interview",
                "started": true,
                "is_analyzing_call": false,
                "last_updated_timestamp": 1676456400
            }
            ],
            "all_complete": true,
            "last_engagement": 1676456400
        },
        "metadata": {
            "resume": {
            "file_link": "https://example.com/resumes/abc123.pdf"
            },
            "web_interview": {
            "final_score": 85.5,
            "skill_highlights": ["Communication", "Problem Solving"],
            "audio_recording_link": "https://example.com/recordings/abc123.mp3",
            "video_recording_link": "https://example.com/recordings/abc123.mp4"
            }
        }
        },
        "workflow": {
        "interview_id": "int_abc123",
        "step_by_step": [
            {
            "complete": true,
            "required": true,
            "order": 1,
            "id": "resume_upload",
            "started": true,
            "details": {
                "details": "Resume uploaded and analyzed"
            },
            "last_updated_timestamp": 1676452800
            },
            {
            "complete": true,
            "required": true,
            "order": 2,
            "id": "web_interview",
            "started": true,
            "is_analyzing_call": false,
            "last_updated_timestamp": 1676456400
            }
        ],
        "all_complete": true,
        "last_engagement": 1676456400
        },
        "agentic_data": {
        "web_interview_info": {
            "summary": {
            "interview_id": "int_abc123",
            "highlights": ["Strong communication skills", "Problem-solving abilities"],
            "lowlights": ["Limited experience with Python"],
            "match_score": 85
            },
            "scorecard": {
            "interview_id": "int_abc123",
            "match_details": ["Good fit for the role"],
            "questions": [
                {
                "question_id": "q1",
                "question": "Tell me about your experience with JavaScript",
                "evaluation_summary": "Strong experience with modern JavaScript frameworks",
                "evaluation_criteria": "JavaScript experience",
                "preview_timestamp": 1676453000,
                "evaluation_score": 4,
                "rank": 1,
                "chat_transcript": [
                    {
                    "speaker": "interviewer",
                    "text": "Tell me about your experience with JavaScript",
                    "timestamp": 1676453000,
                    "timestamp_str": "00:05:00"
                    },
                    {
                    "speaker": "candidate",
                    "text": "I've been working with JavaScript for 5 years...",
                    "timestamp": 1676453010,
                    "timestamp_str": "00:05:10"
                    }
                ],
                "score_weight": 2,
                "not_scored": false
                }
            ],
            "tags": ["JavaScript", "React", "Frontend"]
            },
            "communication": {
            "interview_id": "int_abc123",
            "speech_score": 4.2,
            "evaluations": [
                {
                "score": 4,
                "remarks": [
                    {
                    "details": "Clear and concise communication",
                    "transcript_reference": {
                        "speaker": "candidate",
                        "text": "I believe clear communication is essential...",
                        "timestamp": 1676453100,
                        "timestamp_str": "00:06:40"
                    }
                    }
                ]
                }
            ]
            },
            "transcript": {
            "interview_id": "int_abc123",
            "transcript": [
                {
                "speaker": "interviewer",
                "text": "Welcome to the interview. Can you introduce yourself?",
                "timestamp": 1676452800,
                "timestamp_str": "00:00:00"
                },
                {
                "speaker": "candidate",
                "text": "Hi, I'm John Smith, a software engineer with 5 years of experience...",
                "timestamp": 1676452810,
                "timestamp_str": "00:00:10"
                }
            ]
            },
            "audio_recording_link": "https://example.com/recordings/abc123.mp3",
            "video_recording_link": "https://example.com/recordings/abc123.mp4"
        },
        "resume_interview_info": {
            "score_criteria": {
            "interview_id": "int_abc123",
            "overall_score": 4.2,
            "confidence_score": 0.85,
            "criteria": [
                {
                "criteria_id": "c1",
                "criteria_text": "JavaScript Experience",
                "score": 4.5,
                "confidence_score": 0.9,
                "reasons": ["5 years of experience with JavaScript", "Experience with React and Vue"],
                "standout_parts": ["Led a team of 3 developers"]
                }
            ],
            "highlights": ["Strong JavaScript experience", "Team leadership"],
            "improvement_areas": ["Limited Python experience"]
            },
            "eligibility_criteria": {
            "interview_id": "int_abc123",
            "is_eligible": true,
            "confidence_score": 0.95,
            "criteria": [
                {
                "criteria_id": "e1",
                "criteria_text": "Minimum 3 years of experience",
                "pass_criteria": true,
                "confidence_score": 0.98,
                "reasons": ["5 years of experience as a software engineer"]
                }
            ],
            "skill_gaps": ["Python", "AWS"]
            },
            "resume_link": "https://example.com/resumes/abc123.pdf"
        }
    },
    "company_name": "Example Corp",
    "company_image": "https://example.com/logos/example-corp.png",
    "posting_title": "Senior Frontend Developer",
    "posting_interview_type": "web",
    "posting_id": "posting_123"
}
```

***

### 4. Get Interviews by Posting

**GET** `/interviews/{posting_id}?page=1&limit=10`

Retrieve interview data filtered by posting ID and candidate ID.

#### Path Parameters

| Parameter    | Type   | Required | Description               |
| ------------ | ------ | -------- | ------------------------- |
| `posting_id` | string | Yes      | The ID of the job posting |

#### Query Parameters

| Parameter | Type    | Required | Description                                 |
| --------- | ------- | -------- | ------------------------------------------- |
| `page`    | integer | No       | Page number (default: 1)                    |
| `limit`   | integer | No       | Number of interviews per page (default: 10) |

#### Example Request

```bash
curl -X GET "https://api.heymilo.network/api/interviews/{posting_id}?page=1&limit=10" \
  -H "X-API-KEY: your_api_key_here"
```

#### Response Schema

| Field         | Type    | Description                         |
| ------------- | ------- | ----------------------------------- |
| `candidates`  | array   | List of candidate interview objects |
| `total`       | integer | Total number of interviews          |
| `page`        | integer | Current page number                 |
| `limit`       | integer | Number of items per page            |
| `total_pages` | integer | Total number of pages               |

**Candidate Object Schema**

| Field                    | Type   | Description                                |
| ------------------------ | ------ | ------------------------------------------ |
| `interview_id`           | string | Unique ID for the interview                |
| `details`                | object | Core interview details                     |
| `workflow`               | object | Workflow progress and status               |
| `agentic_data`           | object | AI-generated analysis of resume/interview  |
| `company_name`           | string | Name of the company                        |
| `company_image`          | string | Company logo URL                           |
| `posting_title`          | string | Title of the job posting                   |
| `posting_interview_type` | string | Interview type (e.g. `web`, `voice`, etc.) |
| `posting_id`             | string | Job posting ID                             |

#### Response

```json
{
  "candidates": [
    {
      "interview_id": "int_abc123",
      "details": {
        "interview_id": "int_abc123",
        "candidate_id": "cand_xyz789",
        "interviewed_on": 1676452800,
        "score": 85.5,
        "name": "John Smith",
        "email": "john.smith@example.com",
        "actions": {
          "can_view": true,
          "can_download": true
        },
        "status": "completed",
        "workflow_status": {
          "interview_id": "int_abc123",
          "step_by_step": [
            {
              "complete": true,
              "required": true,
              "order": 1,
              "id": "resume_upload",
              "started": true,
              "details": {
                "details": "Resume uploaded and analyzed"
              },
              "last_updated_timestamp": 1676452800
            },
            {
              "complete": true,
              "required": true,
              "order": 2,
              "id": "web_interview",
              "started": true,
              "is_analyzing_call": false,
              "last_updated_timestamp": 1676456400
            }
          ],
          "all_complete": true,
          "last_engagement": 1676456400
        },
        "metadata": {
          "resume": {
            "file_link": "https://example.com/resumes/abc123.pdf"
          },
          "web_interview": {
            "final_score": 85.5,
            "skill_highlights": ["Communication", "Problem Solving"],
            "audio_recording_link": "https://example.com/recordings/abc123.mp3",
            "video_recording_link": "https://example.com/recordings/abc123.mp4"
          }
        }
      },
      "workflow": {
        "interview_id": "int_abc123",
        "step_by_step": [
          {
            "complete": true,
            "required": true,
            "order": 1,
            "id": "resume_upload",
            "started": true,
            "details": {
              "details": "Resume uploaded and analyzed"
            },
            "last_updated_timestamp": 1676452800
          },
          {
            "complete": true,
            "required": true,
            "order": 2,
            "id": "web_interview",
            "started": true,
            "is_analyzing_call": false,
            "last_updated_timestamp": 1676456400
          }
        ],
        "all_complete": true,
        "last_engagement": 1676456400
      },
      "agentic_data": {
        "web_interview_info": {
          "summary": {
            "interview_id": "int_abc123",
            "highlights": ["Strong communication skills", "Problem-solving abilities"],
            "lowlights": ["Limited experience with Python"],
            "match_score": 85
          },
          "scorecard": {
            "interview_id": "int_abc123",
            "match_details": ["Good fit for the role"],
            "questions": [
              {
                "question_id": "q1",
                "question": "Tell me about your experience with JavaScript",
                "evaluation_summary": "Strong experience with modern JavaScript frameworks",
                "evaluation_criteria": "JavaScript experience",
                "preview_timestamp": 1676453000,
                "evaluation_score": 4,
                "rank": 1,
                "chat_transcript": [
                  {
                    "speaker": "interviewer",
                    "text": "Tell me about your experience with JavaScript",
                    "timestamp": 1676453000,
                    "timestamp_str": "00:05:00"
                  },
                  {
                    "speaker": "candidate",
                    "text": "I've been working with JavaScript for 5 years...",
                    "timestamp": 1676453010,
                    "timestamp_str": "00:05:10"
                  }
                ],
                "score_weight": 2,
                "not_scored": false
              }
            ],
            "tags": ["JavaScript", "React", "Frontend"]
          },
          "communication": {
            "interview_id": "int_abc123",
            "speech_score": 4.2,
            "evaluations": [
              {
                "score": 4,
                "remarks": [
                  {
                    "details": "Clear and concise communication",
                    "transcript_reference": {
                      "speaker": "candidate",
                      "text": "I believe clear communication is essential...",
                      "timestamp": 1676453100,
                      "timestamp_str": "00:06:40"
                    }
                  }
                ]
              }
            ]
          },
          "transcript": {
            "interview_id": "int_abc123",
            "transcript": [
              {
                "speaker": "interviewer",
                "text": "Welcome to the interview. Can you introduce yourself?",
                "timestamp": 1676452800,
                "timestamp_str": "00:00:00"
              },
              {
                "speaker": "candidate",
                "text": "Hi, I'm John Smith, a software engineer with 5 years of experience...",
                "timestamp": 1676452810,
                "timestamp_str": "00:00:10"
              }
            ]
          },
          "audio_recording_link": "https://example.com/recordings/abc123.mp3",
          "video_recording_link": "https://example.com/recordings/abc123.mp4"
        },
        "resume_interview_info": {
          "score_criteria": {
            "interview_id": "int_abc123",
            "overall_score": 4.2,
            "confidence_score": 0.85,
            "criteria": [
              {
                "criteria_id": "c1",
                "criteria_text": "JavaScript Experience",
                "score": 4.5,
                "confidence_score": 0.9,
                "reasons": ["5 years of experience with JavaScript", "Experience with React and Vue"],
                "standout_parts": ["Led a team of 3 developers"]
              }
            ],
            "highlights": ["Strong JavaScript experience", "Team leadership"],
            "improvement_areas": ["Limited Python experience"]
          },
          "eligibility_criteria": {
            "interview_id": "int_abc123",
            "is_eligible": true,
            "confidence_score": 0.95,
            "criteria": [
              {
                "criteria_id": "e1",
                "criteria_text": "Minimum 3 years of experience",
                "pass_criteria": true,
                "confidence_score": 0.98,
                "reasons": ["5 years of experience as a software engineer"]
              }
            ],
            "skill_gaps": ["Python", "AWS"]
          },
          "resume_link": "https://example.com/resumes/abc123.pdf"
        }
      },
      "company_name": "Example Corp",
      "company_image": "https://example.com/logos/example-corp.png",
      "posting_title": "Senior Frontend Developer",
      "posting_interview_type": "web",
      "posting_id": "posting_123"
    }
  ],
  "total": 42,
  "page": 1,
  "limit": 10,
  "total_pages": 5
}
```

***

### 5. Export Interviews

**GET** `interviews/export/json`

Retrieve JSON file of interviews

#### Path Parameters

| Field        | Type   | Required | Description                     |
| ------------ | ------ | -------- | ------------------------------- |
| `posting_id` | string | Yes      | ID of the job posting to export |

#### Example Request

```bash
curl --request POST \
  --url "https://api.heymilo.network/api/interviews/export/json" \
  --header 'X-API-KEY: your_api_key_here' \
  --data '{
    "posting_id": "A03EBF1A"
  }'

```

#### Response Schema

| Field      | Type   | Description                                   |
| ---------- | ------ | --------------------------------------------- |
| `job_id`   | string | ID of the export job (used for tracking)      |
| `status`   | string | Status of the export job (e.g., `success`)    |
| `file_url` | string | Direct URL to download the exported JSON file |

#### Response

```json
{
  "job_id": "1ce5b174-611f-4cec-b955-cd48da195fcb",
  "status": "success",
  "file_url": "https://cdn.heymilo.ai/exports/json/CFE6B6A30C63EF347F5E2BD67D171/B26029F7/candidates-B26029F7-2025-08-14-14-35.json"
}
```

***

### 6. Create Webhook

**POST** `/create`

Create a new webhook configuration to receive real-time notifications about interview events.

#### Request Body

```json
{
  "posting_id": "posting_123",
  "url": "https://your-domain.com/webhook-endpoint",
  "event_type": "interview_completed",
  "http_method": "post"
}
```

#### Example Request

```bash
curl -X POST "https://api.heymilo.network/api/webhook/create" \
  -H "X-API-KEY: your_api_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "posting_id": "posting_123",
    "url": "https://your-domain.com/webhook-endpoint",
    "event_type": "interview_completed",
    "http_method": "post"
  }'
```

#### Response

```json
{
  "webhook_id": "webhook_789",
  "posting_id": "posting_123",
  "url": "https://your-domain.com/webhook-endpoint",
  "event_type": "interview_completed",
  "http_method": "post",
  "is_active": true,
  "created_at": 1703097600.0,
  "updated_at": 1703097600.0
}
```

#### Request Schema

| Field         | Type         | Required | Description                                                                   |
| ------------- | ------------ | -------- | ----------------------------------------------------------------------------- |
| `posting_id`  | string       | Yes      | ID of the posting this webhook is for                                         |
| `url`         | string (URL) | Yes      | Destination URL for the webhook                                               |
| `event_type`  | string       | Yes      | Event type: "interview\_started", "interview\_completed", "report\_available" |
| `http_method` | string       | No       | HTTP method: "get" or "post" (default: "post")                                |

***

### 7. Get Webhook

**GET** `/fetch/{webhook_id}`

Retrieve a webhook configuration by its ID.

#### Path Parameters

| Parameter    | Type   | Required | Description    |
| ------------ | ------ | -------- | -------------- |
| `webhook_id` | string | Yes      | The webhook ID |

#### Example Request

```bash
curl -X GET "https://api.heymilo.network/api/webhook/fetch/webhook_789" \
  -H "X-API-KEY: your_api_key_here"
```

#### Response

```json
{
  "webhook_id": "webhook_789",
  "posting_id": "posting_123",
  "url": "https://your-domain.com/webhook-endpoint",
  "event_type": "interview_completed",
  "http_method": "post",
  "is_active": true,
  "created_at": 1703097600.0,
  "updated_at": 1703097600.0
}
```

***

### 8. Get All Webhooks

**GET** `/all`

Retrieve webhooks with optional filters.

#### Query Parameters

| Parameter    | Type   | Required | Description          |
| ------------ | ------ | -------- | -------------------- |
| `posting_id` | string | No       | Filter by posting ID |
| `event_type` | string | No       | Filter by event type |

### 9. Deactivate Webhook

**POST** `/deactivate/{webhook_id}`

Deactivate a webhook.

#### Path Parameters

| Parameter    | Type   | Required | Description    |
| ------------ | ------ | -------- | -------------- |
| `webhook_id` | string | Yes      | The webhook ID |

***

### 10. Ingest Single Candidate

**POST** `/ingest/x/{url_key}`

Ingest a single candidate into the system using a posting-specific url\_key.

#### Spectial Note

* `retake: false` (default) - Returns existing interview if candidate already has one for this posting
* `retake: true` - Always creates a new interview, even if candidate already has one

#### Path Parameters

| Field     | Type   | Required | Description                                |
| --------- | ------ | -------- | ------------------------------------------ |
| `url_key` | string | Yes      | Unique key identifying the target pipeline |

#### Example Request

```bash
curl --request POST \
  --url "https://api.heymilo.network/api/ingest/x/{url_key}" \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: your_api_key_here' \
  --data '{
    "name": "John Doe",
    "email": "john.doe@example.com",
    "phone_number": "+1234567890",
    "metadata": {
      "source": "careers_page",
      "job_id": "job123"
    },
    "data": {
      "experience": "5 years",
      "education": "Bachelor'\''s in Computer Science"
    },
    "retake" : true
  }'
```

#### Response Schema

| Field               | Type   | Description                                         |
| ------------------- | ------ | --------------------------------------------------- |
| `message`           | string | Confirmation message about ingestion initiation     |
| `ingestion_id`      | string | Unique ID for the ingestion process                 |
| `interview_details` | array  | List of interviews created/linked for the candidate |

#### Each interview details:

| Field            | Type   | Description                               |
| ---------------- | ------ | ----------------------------------------- |
| `interview_id`   | string | Unique identifier for the interview       |
| `interview_link` | string | URL link for candidate’s interview access |

#### Response

```json
{
  "message": "Data Ingestion initiated for john.doe@example.com",
  "ingestion_id": "550e8400-e29b-41d4-a716-446655440000",
  "interview_details": [
    {
      "interview_id": "int_id_78658707",
      "interview_link": "https://candidates.sample/heymiloai/i/interview_id"
    }
  ]
}
```

***

### 11. Bulk Ingest Candidates

**POST** `/ingest/x/bulk/{url_key}`

Ingest multiple candidates into the system in a single request, using a posting-specific url\_key.

#### Spectial Note

* `retake: false` (default) - Returns existing interview if candidate already has one for this posting
* `retake: true` - Always creates a new interview, even if candidate already has one

#### Path Parameters

| Field     | Type   | Required | Description                                |
| --------- | ------ | -------- | ------------------------------------------ |
| `url_key` | string | Yes      | Unique key identifying the target pipeline |

#### Example Request

```bash
curl --request POST \
  --url "https://api.heymilo.network/api/ingest/x/bulk/{url_key}" \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: your_api_key_here' \
  --data '{
    "data": [
      {
        "name": "John Doe",
        "email": "john.doe@example.com",
        "phone_number": "+1234567890",
        "metadata": {
          "source": "careers_page",
          "job_id": "job123"
        },
        "data": {
          "experience": "5 years",
          "education": "Bachelor'\''s in Computer Science"
        },
        "retake" : true
      },
      {
        "name": "Jane Smith",
        "email": "jane.smith@example.com",
        "phone_number": "+1987654321",
        "metadata": {},
        "data": {},
        "retake" : false
      }
    ]
  }'
```

#### Response Schema

| Field               | Type   | Description                                          |
| ------------------- | ------ | ---------------------------------------------------- |
| `message`           | string | Confirmation message about bulk ingestion initiation |
| `ingestion_id`      | string | Unique ID for the bulk ingestion process             |
| `interview_details` | array  | List of interviews created/linked for the candidates |

#### Each interview details:

| Field            | Type   | Description                               |
| ---------------- | ------ | ----------------------------------------- |
| `interview_id`   | string | Unique identifier for the interview       |
| `interview_link` | string | URL link for candidate’s interview access |

#### Response

```json
{
  "message": "Bulk candidate ingestion job created successfully",
  "ingestion_id": "ing_123456789",
  "interview_details": [
    {
      "interview_id": "int_id_78658707",
      "interview_link": "https://candidates.sample/heymiloai/i/interview_id"
    },
    {
      "interview_id": "int_id_78658703",
      "interview_link": "https://candidates.sample/heymiloai/i/interview_id"
    }
  ]
}
```

***

## Webhook Event Types

The API supports the following webhook event types:

| Event Type            | Description                                          |
| --------------------- | ---------------------------------------------------- |
| `interview_started`   | Triggered when a candidate starts an interview       |
| `interview_completed` | Triggered when a candidate completes an interview    |
| `report_available`    | Triggered when an interview report becomes available |

## Error Handling

All API endpoints return structured error responses:

```json
{
  "detail": "Error description",
  "status_code": 422,
  "error_type": "validation_error"
}
```

## Support

For API support and questions:

* Email: <support@heymilo.ai>
* Documentation: <https://docs.heymilo.cloud>
* Status Page: <https://status.heymilo.ai>

***

*Last updated: Sep 19, 2025*


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.admin.heymilo.ai/public-api/public-api-documentation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
