> This page is for API.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.spreadspace.app/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.spreadspace.app/_mcp/server.

# embed.session.created

POST 

Fires once when a signed iframe URL is exchanged for an embed session. `session_id` is the id `DELETE /api/embed/sessions/{session_id}` takes and `handle_id` is the handle your server recorded at the mint. The payload carries ids and times, never a token.

Reference: https://docs.spreadspace.app/api/api-reference/webhook-events/webhook-embed-session-created

## Request

### Headers

- `SpreadSpace-Signature` (string, required) — Signature over the exact request body: `t=<seconds since the Unix epoch>,v1=<lowercase hex HMAC-SHA256 of "{t}.{body}" keyed with your endpoint's signing secret>`. Verify it before trusting the body, and reject a `t` more than five minutes from your own clock. During a secret rotation both the new and the previous secret verify for 24 hours; each delivery is signed with exactly one.
- `SpreadSpace-Event-Id` (string, required) — The event id, identical to the body's `id`. Stable across retries and replays, and shared by every endpoint one event fans out to. Delivery is at-least-once, so dedupe on it.

### Payload

- `id` (string, required) — Event id: `evt_` plus 24 lowercase hex characters. Also sent as the `SpreadSpace-Event-Id` header. Stable across retries and replays, so dedupe on it.
- `type` (enum, required) — Always this event type on this body.
  - Allowed values: `embed.session.created`
- `created` (long, required) — Seconds since the Unix epoch at which the event was created server-side. Seconds, not milliseconds. Deliveries are not ordered; reconcile on this.
- `tenant_id` (string, required) — The workspace the event belongs to. Reject a delivery whose tenant does not match the endpoint you registered.
- `livemode` (boolean, required) — `true` for live activity, `false` for test mode (an `ss_test_` key or the sandbox simulator). Branch on it to route test deliveries to a staging handler.
- `data` (EmbedSessionCreatedPayload, required) — The `data` object on an `embed.session.created` delivery, sent once when a signed iframe URL is exchanged for an embed session. The frame that exchanged it is anonymous and your server never sees the exchange's answer, so this is how your backend learns the session the handle became. A pointer, not a payload: ids and two times only, never a token and never a name.

## Types

### EmbedSessionCreatedPayload

The `data` object on an `embed.session.created` delivery, sent once when a signed iframe URL is exchanged for an embed session. The frame that exchanged it is anonymous and your server never sees the exchange's answer, so this is how your backend learns the session the handle became. A pointer, not a payload: ids and two times only, never a token and never a name.

- `session_id` (string, required) — The embed session the exchange minted: the id `DELETE /api/embed/sessions/{session_id}` takes.
- `handle_id` (string, required) — The iframe handle your server recorded at the mint.
- `loan_id` (string, required) — The loan the session is bound to.
- `borrower_id` (string, required) — The borrower that owns the loan.
- `expires_at` (datetime, required) — When the session's token stops working on its own.
- `created_at` (datetime, required) — Server-side wall-clock time of the exchange.
- `external_user_id` (string, optional, nullable) — The `external_user_id` the mint named; null when it named none.