# Upload Receipt

**POST** `/users/{user_id}/expenses/{expense_id}/receipt`

Base URL: `https://live.savewithsail.com/api/v1`

Attach an itemized receipt to an expense to resolve an `itemization_required` classification (a mixed-basket transaction). Triggers asynchronous re-adjudication. The outcome arrives as a `receipt.processed` webhook (`receipt.failed` if unreadable). Alternative to an `upload_receipt` hosted session for customers who own the receipt UI themselves.

## Authorization

- PartnerKey (http, bearer)

## Path parameters

- `user_id` (string, required)
  The Sail user id.
- `expense_id` (string, required)
  The Sail expense id.

## Body

Content type: `multipart/form-data`

- `file` (string<binary>, required)
  Receipt image or PDF.

Example:

```json
{
  "file": "string"
}
```

## Responses

### 202

Receipt accepted. Re-adjudication queued.

- `status` (string)
  The job's current status.
- `job_id` (string)
  Identifier for tracking this asynchronous job.

Example:

```json
{
  "status": "processing",
  "job_id": "string"
}
```

### default

Standard error envelope covering 400, 401, 403, 404, 429, and 500.

- `error` (object)
  The error detail.
  - `code` (string)
    Machine-readable code, e.g. `not_found`, `token_scope_mismatch`, `product_not_enabled`, `insufficient_key_scope`, `insufficient_token_scope`, `user_token_required`, `user_token_expired`, `invalid_user_token`, `invalid_key_configuration`, `connection_not_reconnectable`, `rate_limited`.
  - `message` (string)
    Human-readable error message. May change, so match on `error.code` instead.
  - `param` (string)
    The request field that caused the error, when applicable. Null otherwise.

Example:

```json
{
  "error": {
    "code": "string",
    "message": "string",
    "param": "string"
  }
}
```