> ## Documentation Index
> Fetch the complete documentation index at: https://developer.9squid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bulk Loan Upload

Bulk upload lets you submit multiple loan tapes in a single job. Each deal gets its own upload URL and tracks status independently — useful when you need to onboard several loan pools at once.

## Overview

```
1. POST /originator/loans/bulk            → create bulk job, get per-deal upload URLs
2. PUT  <upload_url>                      → upload each file directly (one per deal)
3. POST /originator/loans/bulk/complete   → mark the job complete, trigger processing
4. GET  /originator/loans/bulk/:jobId     → poll bulk job status
```

***

## Step 1 — Initiate a Bulk Upload Job

Send an array of loan entries — each with a `type` and an optional `reference` you can use to correlate results.

```bash theme={null}
curl -X POST https://api.9squid.com/v1/api/originator/loans/bulk \
  -H "Authorization: Bearer <your_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "loans": [
      { "type": "Auto",     "reference": "pool-auto-q2" },
      { "type": "Mortgage", "reference": "pool-mtg-q2" }
    ]
  }'
```

**Supported loan types:** `Auto`, `Personal`, `Mortgage`, `Student`, `Business`, `Credit Card`

**Response**

```json theme={null}
{
  "success": true,
  "data": {
    "bulk_job_id": "clxbulk987654",
    "deals": [
      {
        "reference": "pool-auto-q2",
        "deal_id": "clx1a2b3c4d5e6f7g8h9",
        "upload_url": "https://...",
        "file_name": "loan-tape-abc123.upload",
        "expires_in": 3600
      },
      {
        "reference": "pool-mtg-q2",
        "deal_id": "clx9z8y7x6w5v4u3t2s1",
        "upload_url": "https://...",
        "file_name": "loan-tape-def456.upload",
        "expires_in": 3600
      }
    ]
  }
}
```

Each deal is created in `DRAFT` status. Upload URLs expire in **1 hour**.

***

## Step 2 — Upload Each File

Use each deal's `upload_url` to upload the corresponding loan tape. Do this for every deal in the response. No auth header needed — URLs are pre-authorized.

```bash theme={null}
# Upload auto loan tape
curl -X PUT "<upload_url_for_auto>" \
  -H "Content-Type: text/csv" \
  --data-binary @auto-loans-q2.csv

# Upload mortgage loan tape
curl -X PUT "<upload_url_for_mortgage>" \
  -H "Content-Type: text/csv" \
  --data-binary @mortgage-loans-q2.csv
```

For XLSX files use `Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`.

> Upload all files before calling complete. Any deal without an uploaded file will fail validation.

***

## Step 3 — Complete the Bulk Job

Once all files are uploaded, notify the platform. Pass each deal's `deal_id` and `file_name` from Step 1.

```bash theme={null}
curl -X POST https://api.9squid.com/v1/api/originator/loans/bulk/complete \
  -H "Authorization: Bearer <your_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "bulk_job_id": "clxbulk987654",
    "deals": [
      {
        "deal_id": "clx1a2b3c4d5e6f7g8h9",
        "file_name": "loan-tape-abc123.upload"
      },
      {
        "deal_id": "clx9z8y7x6w5v4u3t2s1",
        "file_name": "loan-tape-def456.upload"
      }
    ]
  }'
```

**Response**

```json theme={null}
{
  "success": true,
  "data": {
    "bulk_job_id": "clxbulk987654",
    "status": "PROCESSING",
    "deals": [
      { "deal_id": "clx1a2b3c4d5e6f7g8h9", "status": "IN_REVIEW" },
      { "deal_id": "clx9z8y7x6w5v4u3t2s1", "status": "IN_REVIEW" }
    ]
  }
}
```

***

## Step 4 — Poll Bulk Job Status

Track the overall job and per-deal progress.

```bash theme={null}
curl https://api.9squid.com/v1/api/originator/loans/bulk/clxbulk987654 \
  -H "Authorization: Bearer <your_token>"
```

**Response**

```json theme={null}
{
  "success": true,
  "data": {
    "bulk_job_id": "clxbulk987654",
    "status": "COMPLETED",
    "deals": [
      {
        "deal_id": "clx1a2b3c4d5e6f7g8h9",
        "reference": "pool-auto-q2",
        "status": "QC_COMPLETED"
      },
      {
        "deal_id": "clx9z8y7x6w5v4u3t2s1",
        "reference": "pool-mtg-q2",
        "status": "IN_REVIEW"
      }
    ]
  }
}
```

**Bulk job statuses:**

| Status       | Meaning                                              |
| ------------ | ---------------------------------------------------- |
| `PROCESSING` | Files submitted, deals being validated               |
| `COMPLETED`  | All deals processed (check individual deal statuses) |
| `PARTIAL`    | Some deals failed validation — see per-deal status   |

***

## Regenerate Expired Upload URLs

If an upload URL expires before you finish uploading, regenerate it for a specific deal:

```bash theme={null}
curl -X PATCH https://api.9squid.com/v1/api/originator/loans/clx1a2b3c4d5e6f7g8h9 \
  -H "Authorization: Bearer <your_token>"
```

Returns a fresh `upload_url` and `file_name`. The deal stays in `DRAFT`.

***

## What's Next

* [Run Selection Criteria](/workflows/run-selection-criteria) — validate each deal against eligibility rules
* [Create a Single Deal](/workflows/create-a-deal) — single deal upload flow
* [View Your Pools](/api-reference/originator-pools/poolscontroller_listpools) — inspect the securitization pools your deals belong to
