# Create Hosted Session

**POST** `/hosted-sessions`

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

Creates a hosted session: an authenticated, time-limited, single-use URL for a Sail-rendered UI flow. Three flows are supported. `connect_account` is the sole way to establish Sail-managed connections (`card`, `store`, `benefit_account`). `reconnect` re-authenticates a Sail-managed connection when credentials go stale. `upload_receipt` lets users submit itemized receipts (optionally against a specific `needs_review` expense). Experiences beyond these flows belong in your own UI, built on the API.

## Authorization

- PartnerKey (http, bearer)

## Body

Content type: `application/json`

- `user_id` (string, required)
  The Sail user this session is for.
- `flow` ("connect_account" | "reconnect" | "upload_receipt", required)
  Which hosted UI flow to render.
- `options` (object)
  Flow-specific options:
  - `connect_account` requires `connection_type` (`card`, `store`, or `benefit_account`); accepts `modal`.
  - `reconnect` requires `connection_id` (a Sail-managed connection; `external` connections have no credentials and return `409 connection_not_reconnectable`).
  - `upload_receipt` accepts an optional `expense_id` to attach the receipt to a specific `needs_review` expense.
  - `connection_type` ("card" | "store" | "benefit_account")
    Required for `connect_account`.
  - `merchant_id` (string)
    For `connect_account` with `connection_type: store`. Skips merchant selection and goes directly to the login screen for this merchant.
  - `administrator_id` (string)
    For `connect_account` with `connection_type: benefit_account`. Skips administrator selection and goes directly to the login screen for this administrator.
  - `connection_id` (string)
    Required for `reconnect`. The existing connection to re-authenticate.
  - `modal` (boolean)
    For `connect_account` and `reconnect`. Renders as an overlay when true.
  - `expense_id` (string)
    For `upload_receipt`. Attaches the uploaded receipt to this expense and triggers re-adjudication.

Example:

```json
{
  "user_id": "string",
  "flow": "connect_account",
  "options": {
    "connection_type": "card",
    "merchant_id": "string",
    "administrator_id": "string",
    "connection_id": "string",
    "modal": true,
    "expense_id": "string"
  }
}
```

## Responses

### 200

URL generated.

- `url` (string<uri>)
  The single-use hosted session URL to embed or redirect the user to.
- `expires_at` (string<date-time>)
  When the URL expires and can no longer be opened.
- `flow` (string)
  The flow this session was created for.

Example:

```json
{
  "url": "string",
  "expires_at": "1970-01-01T00:00:00.000Z",
  "flow": "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"
  }
}
```