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

# Bulk Import

> Create hundreds of submissions at once by uploading a CSV file with submitter data.

## Overview

Bulk import lets you create many submissions from a single CSV file. Upload a CSV with submitter information, preview the parsed data, and create all submissions in one request. For files with more than 100 rows, processing runs in the background with status polling.

## CSV Format

The CSV file must include a header row. Column names are matched to template field names (case-insensitive). The `email` column is required for each submitter role.

```csv theme={null}
email,name,phone,company
jane@example.com,Jane Doe,+15551234567,Acme Corp
bob@example.com,Bob Smith,+15559876543,Widget Inc
maria@example.com,Maria Garcia,+15555551234,TechStart LLC
david@example.com,David Park,+15558887777,Global Solutions
lisa@example.com,Lisa Chen,+15552223333,Bright Ideas Co
```

For templates with multiple submitter roles, prefix columns with the role name:

```csv theme={null}
signer_email,signer_name,witness_email,witness_name
jane@example.com,Jane Doe,bob@example.com,Bob Smith
maria@example.com,Maria Garcia,david@example.com,David Park
lisa@example.com,Lisa Chen,alex@example.com,Alex Rivera
```

## Preview CSV

Upload a CSV to validate and preview the parsed data before creating submissions. This endpoint does not create any records.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://spitshake.io/api/templates/{template_id}/bulk/preview" \
    -H "X-Auth-Token: YOUR_API_TOKEN" \
    -F "csv=@/path/to/submitters.csv"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "valid": true,
    "total_rows": 5,
    "columns": ["email", "name", "phone", "company"],
    "column_mappings": {
      "email": "email",
      "name": "Full Name",
      "phone": "Phone Number",
      "company": "Company"
    },
    "preview_rows": [
      {
        "row_number": 1,
        "valid": true,
        "errors": [],
        "data": {
          "email": "jane@example.com",
          "name": "Jane Doe",
          "phone": "+15551234567",
          "company": "Acme Corp"
        }
      },
      {
        "row_number": 2,
        "valid": true,
        "errors": [],
        "data": {
          "email": "bob@example.com",
          "name": "Bob Smith",
          "phone": "+15559876543",
          "company": "Widget Inc"
        }
      },
      {
        "row_number": 3,
        "valid": true,
        "errors": [],
        "data": {
          "email": "maria@example.com",
          "name": "Maria Garcia",
          "phone": "+15555551234",
          "company": "TechStart LLC"
        }
      },
      {
        "row_number": 4,
        "valid": true,
        "errors": [],
        "data": {
          "email": "david@example.com",
          "name": "David Park",
          "phone": "+15558887777",
          "company": "Global Solutions"
        }
      },
      {
        "row_number": 5,
        "valid": true,
        "errors": [],
        "data": {
          "email": "lisa@example.com",
          "name": "Lisa Chen",
          "phone": "+15552223333",
          "company": "Bright Ideas Co"
        }
      }
    ],
    "unmapped_columns": [],
    "warnings": []
  }
  ```

  ```json 200 — With Errors theme={null}
  {
    "valid": false,
    "total_rows": 3,
    "columns": ["email", "name", "phone", "company"],
    "column_mappings": {
      "email": "email",
      "name": "Full Name",
      "phone": "Phone Number",
      "company": "Company"
    },
    "preview_rows": [
      {
        "row_number": 1,
        "valid": true,
        "errors": [],
        "data": {
          "email": "jane@example.com",
          "name": "Jane Doe",
          "phone": "+15551234567",
          "company": "Acme Corp"
        }
      },
      {
        "row_number": 2,
        "valid": false,
        "errors": ["Missing required field: email"],
        "data": {
          "email": "",
          "name": "Bob Smith",
          "phone": "+15559876543",
          "company": "Widget Inc"
        }
      },
      {
        "row_number": 3,
        "valid": true,
        "errors": [],
        "data": {
          "email": "maria@example.com",
          "name": "Maria Garcia",
          "phone": "+15555551234",
          "company": "TechStart LLC"
        }
      }
    ],
    "unmapped_columns": [],
    "warnings": ["1 row has validation errors and will be skipped during import."]
  }
  ```

  ```json 422 — Invalid CSV theme={null}
  {
    "error": "Unable to parse CSV file. Please ensure the file uses comma delimiters and includes a header row."
  }
  ```
</ResponseExample>

## Create Bulk Submissions

Create submissions for all valid rows in the CSV. For files with 100 or fewer rows, submissions are created synchronously. For larger files, processing runs in the background.

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://spitshake.io/api/templates/{template_id}/bulk/create" \
    -H "X-Auth-Token: YOUR_API_TOKEN" \
    -F "csv=@/path/to/submitters.csv" \
    -F "send_emails=true" \
    -F "message=Please review and sign the attached document at your earliest convenience."
  ```
</RequestExample>

<ResponseExample>
  ```json 200 — Synchronous (100 rows or fewer) theme={null}
  {
    "status": "completed",
    "batch_id": "batch_a1b2c3d4e5f6",
    "total_rows": 5,
    "created": 5,
    "skipped": 0,
    "failed": 0,
    "submissions": [
      {
        "id": 1001,
        "slug": "aB3cD4eF",
        "status": "sent",
        "submitter_email": "jane@example.com",
        "submitter_name": "Jane Doe",
        "signing_url": "https://spitshake.io/s/aB3cD4eF",
        "created_at": "2026-04-08T15:00:00Z"
      },
      {
        "id": 1002,
        "slug": "gH5iJ6kL",
        "status": "sent",
        "submitter_email": "bob@example.com",
        "submitter_name": "Bob Smith",
        "signing_url": "https://spitshake.io/s/gH5iJ6kL",
        "created_at": "2026-04-08T15:00:01Z"
      },
      {
        "id": 1003,
        "slug": "mN7oP8qR",
        "status": "sent",
        "submitter_email": "maria@example.com",
        "submitter_name": "Maria Garcia",
        "signing_url": "https://spitshake.io/s/mN7oP8qR",
        "created_at": "2026-04-08T15:00:02Z"
      },
      {
        "id": 1004,
        "slug": "sT9uV0wX",
        "status": "sent",
        "submitter_email": "david@example.com",
        "submitter_name": "David Park",
        "signing_url": "https://spitshake.io/s/sT9uV0wX",
        "created_at": "2026-04-08T15:00:03Z"
      },
      {
        "id": 1005,
        "slug": "yZ1aB2cD",
        "status": "sent",
        "submitter_email": "lisa@example.com",
        "submitter_name": "Lisa Chen",
        "signing_url": "https://spitshake.io/s/yZ1aB2cD",
        "created_at": "2026-04-08T15:00:04Z"
      }
    ],
    "created_at": "2026-04-08T15:00:00Z",
    "completed_at": "2026-04-08T15:00:05Z"
  }
  ```

  ```json 202 — Background Processing (more than 100 rows) theme={null}
  {
    "status": "processing",
    "batch_id": "batch_x9y8z7w6v5u4",
    "total_rows": 350,
    "created": 0,
    "skipped": 0,
    "failed": 0,
    "submissions": [],
    "created_at": "2026-04-08T15:00:00Z",
    "completed_at": null
  }
  ```
</ResponseExample>

## Check Batch Status

Poll the status of a background bulk import job.

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://spitshake.io/api/templates/{template_id}/bulk/status/{batch_id}" \
    -H "X-Auth-Token: YOUR_API_TOKEN"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 — In Progress theme={null}
  {
    "status": "processing",
    "batch_id": "batch_x9y8z7w6v5u4",
    "total_rows": 350,
    "created": 142,
    "skipped": 3,
    "failed": 0,
    "progress_percent": 41,
    "created_at": "2026-04-08T15:00:00Z",
    "completed_at": null
  }
  ```

  ```json 200 — Completed theme={null}
  {
    "status": "completed",
    "batch_id": "batch_x9y8z7w6v5u4",
    "total_rows": 350,
    "created": 345,
    "skipped": 3,
    "failed": 2,
    "progress_percent": 100,
    "created_at": "2026-04-08T15:00:00Z",
    "completed_at": "2026-04-08T15:03:45Z"
  }
  ```
</ResponseExample>

## Export Submissions as CSV

Download all submissions for a template as a CSV file, useful for reconciliation after a bulk import.

<RequestExample>
  ```bash cURL theme={null}
  curl -X GET "https://spitshake.io/api/templates/{template_id}/bulk/export" \
    -H "X-Auth-Token: YOUR_API_TOKEN" \
    -o submissions_export.csv
  ```
</RequestExample>

<ResponseExample>
  ```csv 200 OK theme={null}
  submission_id,slug,status,email,name,phone,company,sent_at,completed_at,signing_url
  1001,aB3cD4eF,completed,jane@example.com,Jane Doe,+15551234567,Acme Corp,2026-04-08T15:00:00Z,2026-04-08T16:30:00Z,https://spitshake.io/s/aB3cD4eF
  1002,gH5iJ6kL,sent,bob@example.com,Bob Smith,+15559876543,Widget Inc,2026-04-08T15:00:01Z,,https://spitshake.io/s/gH5iJ6kL
  1003,mN7oP8qR,opened,maria@example.com,Maria Garcia,+15555551234,TechStart LLC,2026-04-08T15:00:02Z,,https://spitshake.io/s/mN7oP8qR
  1004,sT9uV0wX,sent,david@example.com,David Park,+15558887777,Global Solutions,2026-04-08T15:00:03Z,,https://spitshake.io/s/sT9uV0wX
  1005,yZ1aB2cD,completed,lisa@example.com,Lisa Chen,+15552223333,Bright Ideas Co,2026-04-08T15:00:04Z,2026-04-08T17:15:00Z,https://spitshake.io/s/yZ1aB2cD
  ```
</ResponseExample>

## Limits and Performance

| Metric                           | Value                           |
| -------------------------------- | ------------------------------- |
| Maximum CSV file size            | 10 MB                           |
| Maximum rows per import          | 5,000                           |
| Synchronous processing threshold | 100 rows                        |
| Background processing rate       | \~100 submissions per minute    |
| Email send rate                  | Throttled to avoid spam filters |

<Note>
  For imports larger than 5,000 rows, split your CSV into multiple files and run separate bulk imports. Each batch is assigned a unique `batch_id` for independent tracking.
</Note>
