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

# Submit Call Recordings for AI Analysis with Shilo

> Learn how to POST call recordings to Shilo's API for AI processing, including required fields, optional metadata, and handling the async response.

Shilo's call submission endpoint accepts a recording URL and associated metadata, queues the call for AI processing, and returns a `call_event_id` you can use to poll for results. The entire pipeline is asynchronous—your system receives an immediate `202 Accepted` response, and Shilo handles the transcription, speaker resolution, and AI analysis in the background.

## Overview

**Endpoint:** `POST /api/v1/calls`\
**Authentication:** Read-write API key required\
**Response:** `202 Accepted` with `call_event_id` and `status: "QUEUED"`

<Steps>
  ### Prepare Your Recording URL

  Before submitting, make sure the audio file at `recording_url` is publicly accessible. Shilo's processing pipeline will attempt to download the file at analysis time. If the URL is behind authentication or expires before processing starts, the job will fail.

  <Note>
    Use a pre-signed URL with a sufficiently long expiry (at least 30 minutes) if your storage provider requires signed URLs for access.
  </Note>

  ### Build the Request Body

  Construct a JSON body with all required fields. Optional fields can be included to enrich the contact and user records associated with the call.

  **Required fields:**

  | Field | Type | Description |
  | - | - | - |
  | `recording_id` | string | Your unique external ID for this recording. Used for deduplication and as an identifier with the `external_recording_id:` prefix. |
  | `recording_url` | string | Publicly accessible URL to the audio file |
  | `duration_seconds` | number | Length of the recording in seconds |
  | `ai_category` | string | Analysis category (e.g. `"sales"`) |
  | `external_user_id` | string | Your system's ID for the agent on the call |
  | `user_name` | string | Agent display name |
  | `user_email` | string | Agent email address |
  | `external_contact_id` | string | Your system's ID for the contact or lead |
  | `contact_name` | string | Contact display name |

  **Optional fields:**

  | Field | Type | Description |
  | - | - | - |
  | `occurred_at` | string (ISO 8601) | When the call took place |
  | `from_number` | string | Caller phone number |
  | `to_number` | string | Recipient phone number |
  | `incoming` | boolean | `true` if the call was inbound |
  | `ai_models` | array | Override the AI models used for specific analysis types |
  | `user_timezone` | string | Agent's timezone (e.g. `"America/Denver"`) |
  | `user_picture` | string | URL to agent profile photo |
  | `contact_first_name` | string | Contact's first name |
  | `contact_last_name` | string | Contact's last name |
  | `contact_phone` | string | Contact's phone number |
  | `contact_emails` | string\[] | Contact's email addresses |
  | `contact_stage` | string | CRM stage name (e.g. `"Discovery"`) |
  | `contact_stage_id` | string | CRM stage ID |
  | `contact_source` | string | Lead source name (e.g. `"Broker"`) |
  | `contact_source_id` | string | Lead source ID |
  | `contact_tags` | string\[] | Tags to associate with the contact |

  ### Submit the Call

  Send the `POST` request with your API key and the JSON body:

  ```bash theme={null}
  curl -X POST https://api.shilo.ai/api/v1/calls \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "recording_id": "rec-001",
      "recording_url": "https://your-storage.example.com/recordings/rec-001.mp3",
      "duration_seconds": 187,
      "ai_category": "sales",
      "external_user_id": "agent-123",
      "user_name": "Alex Johnson",
      "user_email": "alex@example.com",
      "external_contact_id": "contact-456",
      "contact_name": "Jamie Rivera",
      "occurred_at": "2030-09-24T12:00:00Z",
      "from_number": "(555) 555-1234",
      "to_number": "(555) 555-5678",
      "incoming": false,
      "user_timezone": "America/Denver",
      "contact_first_name": "Jamie",
      "contact_last_name": "Rivera",
      "contact_stage": "Discovery",
      "contact_source": "Broker"
    }'
  ```

  ### Save the `call_event_id`

  A successful submission returns `202 Accepted`:

  ```json theme={null}
  {
    "call_event_id": "ee6f2136-b94a-4438-9335-3acf5b2a0d31",
    "status": "QUEUED"
  }
  ```

  Store the `call_event_id` in your system. You will use it immediately to poll for analysis using the `call_event_id:{uuid}` identifier pattern.

  ### Poll for Analysis

  Retrieve analysis once processing completes:

  ```bash theme={null}
  curl https://api.shilo.ai/api/v1/calls/call_event_id:ee6f2136-b94a-4438-9335-3acf5b2a0d31/analysis \
    -H "x-api-key: YOUR_API_KEY"
  ```

  Poll until the `progress` field in the response equals `100`. See the [Retrieve Analysis guide](/guides/retrieving-analysis) for the full polling pattern and a description of every analysis field.
</Steps>

## Error Responses

| Status | Meaning | Resolution |
| - | - | - |
| `400 Bad Request` | The request body is missing required fields or contains invalid values | Check the error message for which field failed validation |
| `403 Forbidden` | Your API key is read-only | Use a read-write API key for this endpoint |
| `401 Unauthorized` | The API key is missing or invalid | Verify the `x-api-key` header and key value |

## AI Model Overrides

If your Shilo plan supports custom AI models, you can override the model used for specific analysis types by including the `ai_models` array:

```json theme={null}
{
  "ai_models": [
    { "type": "coaching", "model": "custom_coaching_model_v2" }
  ]
}
```

Contact your Shilo account manager for available model identifiers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.