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

# Upload Documents

> Upload one or more documents for a lead. Uses the same pipeline as the in-app Document Vault: S3 storage, action logs, Mastra memory, and document workflow.

This endpoint uploads documents for a lead. Behavior matches the in-app Document Vault: files are stored in S3, a SYSTEM\_NOTE and DOCUMENT\_UPLOAD action log are created, documents are saved to Mastra memory, and the document workflow runs (validation, extraction, etc.). You can optionally associate uploads with a checklist item via `leadChecklistItemId`. Maximum 10 files per request; each file up to 100MB.

## Authentication

Requires the `x-api-key` header with a valid workspace API key.

## Request Body (multipart/form-data)

<ParamField path="leadId" type="string" required>
  The Omni lead ID. The lead must exist and belong to your workspace.
</ParamField>

<ParamField path="files" type="file" required>
  One or more files to upload. Use the form field name `files`. Up to 10 files;
  each file up to 100MB.
</ParamField>

<ParamField path="leadChecklistItemId" type="string" required={false}>
  Optional. Omni lead checklist item ID to associate the uploaded documents
  with. The item must belong to the lead.
</ParamField>

<ParamField path="metadata" type="object[]" required={false}>
  Optional. Per-file metadata, index-aligned with `files`. When provided, its
  length must match the number of files. With `multipart/form-data`,
  send as a JSON-stringified form field.

  Each entry supports:

  * `externalId` (string, optional): your own identifier to persist on the
    document. Returned on the response.
  * `name` (string, optional): overrides the uploaded filename.
</ParamField>

## Response

<ResponseField name="success" type="boolean">
  Whether the request succeeded
</ResponseField>

<ResponseField name="documents" type="array">
  Array of uploaded document objects: id, externalId, filename, size, url
  (presigned), mimeType, uploadedAt, associatedChecklistItemId.
</ResponseField>

<ResponseField name="actionLogId" type="string">
  The ID of the DOCUMENT\_UPLOAD action log entry for this upload
</ResponseField>

<RequestExample>
  ```javascript Node.js theme={null}
  const formData = new FormData();
  formData.append("leadId", "a9d0a790-201b-47e9-84ed-cc7eed1270c5");
  formData.append("files", file1); // File or Blob
  formData.append("files", file2);
  // Optional: formData.append('leadChecklistItemId', '<lead-checklist-item-id>');
  // Optional: per-file metadata (must match the number of files)
  formData.append(
    "metadata",
    JSON.stringify([
      { externalId: "doc-1", name: "document.pdf" },
      { externalId: "doc-2", name: "statement.xlsx" },
    ]),
  );

  const response = await fetch("https://api-v2.getomni.ai/api/v1/documents", {
    method: "POST",
    headers: {
      "x-api-key": "<your-api-key>",
    },
    body: formData,
  });
  const data = await response.json();
  console.log(data);
  ```

  ```python Python theme={null}
  import requests

  import json

  url = "https://api-v2.getomni.ai/api/v1/documents"
  headers = {"x-api-key": "<your-api-key>"}
  data = {
      "leadId": "a9d0a790-201b-47e9-84ed-cc7eed1270c5",
      # Optional: per-file metadata (must match the number of files)
      "metadata": json.dumps([
          {"externalId": "doc-1", "name": "document.pdf"},
          {"externalId": "doc-2", "name": "statement.xlsx"},
      ]),
  }
  # Optional: data["leadChecklistItemId"] = "<lead-checklist-item-id>"
  files = [
      ("files", ("document.pdf", open("document.pdf", "rb"), "application/pdf")),
      ("files", ("statement.xlsx", open("statement.xlsx", "rb"), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")),
  ]
  response = requests.post(url, headers=headers, data=data, files=files)
  print(response.json())
  ```

  ```bash cURL theme={null}
  curl --request POST \
    --url 'https://api-v2.getomni.ai/api/v1/documents' \
    --header 'x-api-key: <your-api-key>' \
    --form 'leadId=a9d0a790-201b-47e9-84ed-cc7eed1270c5' \
    --form 'files=@/path/to/document.pdf' \
    --form 'files=@/path/to/statement.xlsx' \
    --form 'metadata=[{"externalId":"doc-1","name":"document.pdf"},{"externalId":"doc-2","name":"statement.xlsx"}]'
  # Optional: --form 'leadChecklistItemId=<lead-checklist-item-id>'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "success": true,
    "documents": [
      {
        "id": "b1e2c3d4-5f6a-7890-bcde-f12345678901",
        "externalId": "doc-1",
        "filename": "document.pdf",
        "size": 102400,
        "url": "https://...",
        "mimeType": "application/pdf",
        "uploadedAt": "2026-01-30T02:00:00.000Z",
        "associatedChecklistItemId": null
      },
      {
        "id": "c2d3e4f5-6a7b-8901-cdef-23456789012a",
        "externalId": "doc-2",
        "filename": "statement.xlsx",
        "size": 204800,
        "url": "https://...",
        "mimeType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "uploadedAt": "2026-01-30T02:00:00.000Z",
        "associatedChecklistItemId": null
      }
    ],
    "actionLogId": "7de43760-d12d-4bcc-931a-f728ef1a3e3b"
  }
  ```
</ResponseExample>
