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

# Contract Upload

> Upload contracts via multipart form data or JSON with base64-encoded files.

Upload a contract PDF to a project. The file is stored and queued for processing. You can optionally request specific extractions to run automatically after upload.

<Note>
  Only PDF files are supported. Maximum file size is 50 MB.
</Note>

***

## Upload Contract

Creates a new contract record and uploads the file. Supports two content types: `multipart/form-data` for direct file upload, and `application/json` for base64-encoded files.

### Request

```
POST /v1/contracts
```

### Query Parameters

| Parameter   | Type | Required | Default | Description                           |
| ----------- | ---- | -------- | ------- | ------------------------------------- |
| `projectId` | UUID | Yes      | —       | The project to upload the contract to |

### Headers

| Header          | Required | Description                                                      |
| --------------- | -------- | ---------------------------------------------------------------- |
| `Authorization` | Yes      | `Bearer <token>` — must be scoped to the requested project       |
| `Content-Type`  | Yes      | `multipart/form-data` or `application/json`                      |
| `Accept`        | No       | Set to `text/event-stream` for real-time upload progress via SSE |

***

### Option A: Multipart Form Data

Upload a file directly using `multipart/form-data`.

| Field         | Type   | Required | Description                           |
| ------------- | ------ | -------- | ------------------------------------- |
| `file`        | File   | Yes      | The PDF file to upload                |
| `extractions` | string | No       | JSON array of extraction types to run |

#### Example

```bash theme={null}
curl -X POST "https://api.royaltyport.com/v1/contracts?projectId=a1b2c3d4-..." \
  -H "Authorization: Bearer rp_your_token_here" \
  -F "file=@contract.pdf" \
  -F 'extractions=["extract-royalties","extract-dates"]'
```

***

### Option B: JSON Body

Upload a base64-encoded file using `application/json`.

| Field         | Type   | Required | Default           | Description                         |
| ------------- | ------ | -------- | ----------------- | ----------------------------------- |
| `file`        | string | Yes      | —                 | Base64-encoded file content         |
| `fileName`    | string | Yes      | —                 | The file name (e.g. `contract.pdf`) |
| `fileType`    | string | No       | `application/pdf` | MIME type of the file               |
| `extractions` | array  | No       | —                 | Array of extraction types to run    |

#### Example

```bash theme={null}
curl -X POST "https://api.royaltyport.com/v1/contracts?projectId=a1b2c3d4-..." \
  -H "Authorization: Bearer rp_your_token_here" \
  -H "Content-Type: application/json" \
  -d '{
    "file": "JVBERi0xLjQK...",
    "fileName": "contract.pdf",
    "extractions": ["extract-royalties", "extract-dates"]
  }'
```

***

### Extraction Types

Pass any combination of the following extraction types to automatically process the contract after upload:

| Extraction                   | Description                              |
| ---------------------------- | ---------------------------------------- |
| `extract-accounting-period`  | Accounting period definitions            |
| `extract-assets`             | Asset references                         |
| `extract-commitments`        | Commitment clauses                       |
| `extract-compensations`      | Compensation terms                       |
| `extract-control-areas`      | Control area definitions                 |
| `extract-costs`              | Cost provisions                          |
| `extract-creative-approvals` | Creative approval clauses                |
| `extract-dates`              | Key dates (effective, termination, etc.) |
| `extract-royalties`          | Royalty terms                            |
| `extract-signatures`         | Signature information                    |
| `extract-splits`             | Revenue split information                |
| `extract-targets`            | Target and threshold clauses             |
| `extract-balances`           | Balance provisions and terms             |

### Response

| Field              | Type    | Description                                                              |
| ------------------ | ------- | ------------------------------------------------------------------------ |
| `staging_id`       | integer | Unique identifier for tracking processing progress                       |
| `staging_stage`    | string  | Current processing stage (`queued`, `processing`, `completed`, `failed`) |
| `staging_done`     | boolean | Whether staging (pre-processing) has completed                           |
| `extractions_done` | boolean | Whether all extractions have completed                                   |
| `created_at`       | string  | Upload timestamp (ISO 8601)                                              |

```json theme={null}
{
  "data": {
    "staging_id": 456,
    "staging_stage": "queued",
    "staging_done": false,
    "extractions_done": false,
    "created_at": "2025-03-01T12:00:00Z"
  }
}
```

### SSE Response

If the `Accept` header includes `text/event-stream`, the response is a server-sent event stream with upload progress:

```
event: progress
data: {"bytesUploaded":3145728,"bytesTotal":10485760,"percent":30}

event: progress
data: {"bytesUploaded":10485760,"bytesTotal":10485760,"percent":100}

event: complete
data: {"data":{"staging_id":456,"staging_stage":"queued","staging_done":false,"extractions_done":false,"created_at":"2025-03-01T12:00:00Z"}}
```

### Errors

| Status | Description                                                                     |
| ------ | ------------------------------------------------------------------------------- |
| `400`  | Missing file, invalid extractions, unsupported file type, or file exceeds 50 MB |
| `403`  | Token is not scoped to the requested project                                    |
| `429`  | Rate limit exceeded                                                             |
| `500`  | File upload or database error                                                   |
