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

# Create a vault session

> Create a single-use link the user opens to store a card with Face ID.

Create the session, then deliver `url` to the user over the channel you already share with them. One link is one enrollment: send it to one person and bind the `user_id` you receive to them.

<ParamField body="user_id" type="string">
  Omit for a new user: the session is **open**, the user is created at enrollment, and their id arrives in `vault.session_linked` (or on the session read). Pass an id you already hold and the session is **connected**: opening the link sends a one-time code to the contact on that account and verifying it signs the user in.
</ParamField>

<ParamField body="phone" type="string">
  Connected sessions only, E.164. Used only when the account has no contact on file at all. Refused on open sessions.
</ParamField>

<ParamField body="expires_in" type="number">
  Lifetime in seconds, 60 to 172800. Default 24 hours. Sessions are single use.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.agentcard.sh/api/v2/vault_sessions \
    -H "Authorization: Bearer $ORG_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{}'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "object": "vault_session",
    "id": "vs_2q9d1x8f3k2m4t7w",
    "user_id": null,
    "url": "https://vault.agentcard.sh/v?vs=vs_2q9d1x8f3k2m4t7w.3k1v…",
    "channel": null,
    "destination": null,
    "expires_at": "2026-08-28T21:00:00Z",
    "poll_interval": 3,
    "test_mode": false
  }
  ```
</ResponseExample>

<ResponseField name="id" type="string">Read the session by this id, never by the token inside `url`.</ResponseField>
<ResponseField name="url" type="string">The link to send the user.</ResponseField>
<ResponseField name="user_id" type="string | null">Null on an open session until it links.</ResponseField>
<ResponseField name="poll_interval" type="number">Seconds to wait between reads if you poll.</ResponseField>

**Errors.** `400 client_credentials_required` (API key used), `400 contact_missing` (connected session, nothing to send a code to), `429 rate_limited` (open sessions are budgeted at 200 per organization per rolling 24 hours).
