# Sessions API
Create hosted intake sessions and redirect applicants to signed Klarefi intake URLs
Source: https://www.klarefi.com/docs/api/sessions

Use sessions for Hosted Intake integrations where Klarefi owns the hosted
applicant intake flow.

> **Use your workspace API base URL**
>
> Set `KLAREFI_API_BASE_URL` to the value in **Settings → Developer** before
> using the examples. Current workspaces may use a
> `https://<deployment>.convex.site` URL.

## POST /api/v1/sessions

Required scope: `intake:sessions:create`

```bash
curl -X POST "$KLAREFI_API_BASE_URL/api/v1/sessions" \
  -H "Authorization: Bearer $KLAREFI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "case_type_id": "motor_claim",
    "idempotency_key": "session_claim_12345",
    "external_case_id": "claim_12345",
    "external_applicant_id": "applicant_789",
    "external_customer_id": "customer_456",
    "trace_id": "trace_claim_12345",
    "ttl_hours": 168,
    "return_url": "https://claims.example.com/claim_12345",
    "locale": "nl",
    "prefill": {
      "field_values": {
        "claimant_name": "Ada Lovelace",
        "prior_reference": null
      }
    }
  }'
```

## Request Body

| Field                   | Required | Description                                        |
| ----------------------- | -------- | -------------------------------------------------- |
| `case_type_id`          | Yes      | Case type configured in Klarefi                    |
| `idempotency_key`       | Yes      | Retry-safe key, unless sent as a header            |
| `ttl_hours`             | No       | Link lifetime in hours, default `168`              |
| `return_url`            | No       | Destination after the applicant completes intake   |
| `locale`                | No       | BCP 47 locale hint for hosted intake               |
| `external_case_id`      | No       | Your source-system case identifier                 |
| `external_applicant_id` | No       | Your applicant identifier                          |
| `external_customer_id`  | No       | Your customer or account identifier                |
| `trace_id`              | No       | Correlation ID included in events and reads        |
| `prefill.field_values`  | No       | Form field IDs mapped to `string` or `null` values |

Prefill keys must identify fields in the configured form. Unknown fields reject
the request. Compliance and consent fields cannot be prefilled. Klarefi applies
accepted values to the session draft and returns their IDs in
`prefill.applied_field_ids`.

## Response

`201` means a new session was created. `200` means an idempotent replay.

Test API keys can create up to 50 new sessions per workspace per UTC calendar
month. Idempotent replays do not count again. When the cap is reached, this
endpoint returns `429 test_usage_cap_exceeded`.

```json
{
  "session_id": "550e8400-e29b-41d4-a716-446655440000",
  "signed_url": "https://app.klarefi.com/s/550e8400-e29b-41d4-a716-446655440000?token=...",
  "access_token": "1751879000.9f2c4e...",
  "access_token_expires_at": "2026-01-22T10:30:00.000Z",
  "expires_at": "2026-01-22T10:30:00.000Z",
  "agent": {
    "api_base": "https://your-deployment.convex.site/api/v1",
    "manifest_url": "https://your-deployment.convex.site/api/v1/sessions/550e8400-e29b-41d4-a716-446655440000/manifest",
    "access_token": "1751879000.9f2c4e..."
  },
  "snippet": "<script>window.location.href=\"https://app.klarefi.com/s/...\";</script>",
  "idempotent_replay": false,
  "prefill": {
    "applied_field_ids": ["claimant_name", "prior_reference"]
  }
}
```

An idempotent replay returns the same session with `idempotent_replay: true`.
Prefill values in the replay request are not applied again. When the replay
includes them, the response contains `prefill.applied_field_ids: []` and
`prefill_ignored_on_replay: true`.

Redirect the applicant to `signed_url`. Do not construct session URLs in the
browser.

`snippet` is a redirect helper, not an embed: injecting it sends the browser
to `signed_url`. To render an intake inside your own site, use the
[embed script](/docs/guides/embed) instead.
