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

# Uploading conversations

> Send recorded calls to Rulebase with the presigned URL workflow or a direct upload, and package each archive the way its source expects.

This guide describes how to programmatically upload recorded conversations so that Rulebase can ingest and review them.

## Upload methods

Rulebase supports two methods for uploading conversations:

1. **Presigned URL workflow** (recommended for large files) - Two-step process using presigned URLs
2. **Direct upload** (simpler for smaller files) - Single request with multipart form data

***

## Method 1: presigned URL workflow

The presigned URL workflow consists of **two HTTP requests** and is recommended for larger files:

1. Generate a presigned upload URL (HTTP `POST`).
2. Upload the ZIP archive to the returned URL (HTTP `PUT`).

### 1 · Generate a presigned URL

Send a `POST /conversations/upload/presign` request, passing the **filename** and **source** that describe the ZIP archive you intend to upload.

```bash theme={null}
curl -X POST https://api.rulebase.co/conversations/upload/presign \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "upload": {
      "filename": "your-filename.zip",
      "source": "[source]"
    }
  }'
```

Successful responses contain the upload **id** and a time-limited **url** to which you must upload the archive:

```json theme={null}
{
  "upload": {
    "id": "unique_upload_id",
    "url": "https://presigned-url-to-upload"
  }
}
```

For the full REST spec see [Generate a presigned URL for conversation upload](/api-reference/conversations/generate-a-presigned-url-for-conversation-upload).

### 2 · Upload the archive

Upload the ZIP archive with an HTTP `PUT` request to the `url` from step 1. The request **must** use `Content-Type: application/octet-stream`.

```bash theme={null}
curl -X PUT "https://presigned-url-to-upload" \
  -H "Content-Type: application/octet-stream" \
  --data-binary "@your-filename.zip"
```

⚠️ The presigned URL expires **30 minutes** after it is issued.

***

## Method 2: direct upload

For simpler integration and smaller files, you can upload conversations directly using a single `POST` request with multipart form data.

### Upload a conversation directly

Send a `POST /conversations/upload` request with the source, metadata, and call recording as multipart form data.

```bash theme={null}
curl -X POST https://api.rulebase.co/conversations/upload \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "upload[source]=xcally" \
  -F "upload[metadata][unique_id]=abc123" \
  -F "upload[metadata][type]=inbound" \
  -F "upload[metadata][caller]=+2348012345678" \
  -F "upload[metadata][called]=+2349098765432" \
  -F "upload[metadata][recorded_at]=2025-07-02T12:00:00Z" \
  -F "upload[file]=@call-abc123.wav"
```

Successful responses contain the upload **id** and processing status:

```json theme={null}
{
  "data": {
    "id": "unique_upload_id",
    "status": "processing",
    "created_at": "2025-07-02T12:00:00Z",
    "updated_at": "2025-07-02T12:00:00Z"
  }
}
```

### Direct upload requirements

* **Content-Type:** `multipart/form-data`
* **Maximum file size:** 100MB
* **Supported audio formats:** `.wav`, `.mp3`, `.m4a`
* **Metadata format:** Individual form fields for each metadata attribute

### Supported sources for direct upload

| Source key | Description             |
| ---------- | ----------------------- |
| `xcally`   | XCALLY voice recordings |

⚠️ Direct upload currently supports XCALLY sources only. For other sources, use the presigned URL workflow.

***

## Supported sources

The `source` attribute defines how Rulebase should interpret the contents of the archive. All sources follow the same two-step upload flow shown above, but each imposes its own file-naming and payload requirements.

| Source key      | Description                        |
| --------------- | ---------------------------------- |
| `outreach_kaia` | Outreach Kaia conversation exports |
| `xcally`        | XCALLY voice recordings            |

Detailed requirements for each source are provided below.

***

### Outreach Kaia (`outreach_kaia`)

#### 1 · Presign request example

```bash theme={null}
curl -X POST https://api.rulebase.co/conversations/upload/presign \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "upload": {
      "filename": "KAIA-2024-03-20T10:00:00Z+instance123.zip",
      "source": "outreach_kaia"
    }
  }'
```

#### 2 · ZIP file requirements

* **Filename convention:** `KAIA-<RFC3339 DateTime>+<InstanceID>.zip`
* **Contents:**
  | File                | Naming convention                   |
  | ------------------- | ----------------------------------- |
  | Transcript (`.txt`) | `KAIA-<DateTime>+<InstanceID>.txt`  |
  | Media (`.mp4`)      | `KAIA-<DateTime>+<InstanceID>.mp4`  |
  | Metadata (`.json`)  | `KAIA-<DateTime>+<InstanceID>.json` |

#### 3 · Example ZIP structure

```
KAIA-2024-03-20T10:00:00Z+instance123.mp4
KAIA-2024-03-20T10:00:00Z+instance123.txt
KAIA-2024-03-20T10:00:00Z+instance123.json
```

For a complete description of the export schema, refer to the official [Outreach Kaia export documentation](https://support.outreach.io/hc/en-us/articles/28005562346395-Exporting-Data-in-Kaia-using-Daily-Export).

***

### XCALLY (`xcally`)

#### 1 · Presign request example

```bash theme={null}
curl -X POST https://api.rulebase.co/conversations/upload/presign \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "upload": {
      "filename": "xcally-2025-07-02-call-abc123.zip",
      "source": "xcally"
    }
  }'
```

#### 2 · ZIP file requirements

* **Contents:**
  | Required file            | Notes                       |
  | ------------------------ | --------------------------- |
  | Audio (`.wav` or `.mp3`) | Recording of the call       |
  | Metadata (`.json`)       | Call attributes (see below) |
* **Filename convention:** none. Any archive name is accepted as long as exactly one audio file and one JSON file are present.

#### 3 · Example ZIP structure

```
call-abc123.wav
call-abc123.json
```

#### 4 · Metadata JSON schema (example)

```json theme={null}
{
  "unique_id": "abc123",
  "type": "inbound",
  "caller": "+2348012345678",
  "called": "+2349098765432",
  "connected": "ext-1001",
  "queue": "customer_support",
  "disposition": "resolved",
  "recorded_at": "2025-07-02T12:00:00Z"
}
```

| Field         | Description                                                |
| ------------- | ---------------------------------------------------------- |
| `unique_id`   | Unique identifier of the call                              |
| `type`        | Call type (`inbound`, `outbound`, `internal`, or `dialer`) |
| `caller`      | Caller phone number                                        |
| `called`      | Callee phone number                                        |
| `connected`   | Extension/agent that handled the call                      |
| `queue`       | Queue name                                                 |
| `disposition` | Call disposition label                                     |
| `recorded_at` | ISO 8601 timestamp when the call was recorded              |

For additional reference see the [XCALLY voice recordings documentation](https://helpdesk.xcallyusa.com/dt_articles/voice-recordings/).

To confirm Rulebase received uploads after they are processed, see [Confirm received uploads](/guides/uploads/confirm-received-uploads).
