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

# session.vaultRequests.create

> Opens a vault request from the owner's approval, which only the Endstate wallet frame signs (`wallet.vault()` in `@endstate-sdk/web` does both); it stays `pending` until the vault confirms it has the item.

```ts theme={null}
create(body: CreateVaultRequest, options?: IdempotentRequestOptions): Promise<VaultRequest>
```

| | |
| - | - |
| Endpoint | [`POST /v1/units/{unit_id}/vault-requests`](https://docs.endstate.io/api-reference/vaults/request-to-vault-a-unit) |
| Credential | Session token (`end_sess_...`) |
| Retry class | `keyed` |
| Idempotency key | Accepted |

Carries an idempotency key. Retried on network failure, timeout, `429`, and `409 idempotency.in_progress` - never on a `5xx`.

## Example

```ts theme={null}
const result = await session.vaultRequests.create({
  vaultId: "...",
  nonce: "...",
  ownerSignature: "...",
});
```

## Parameters

**unit\_id** `string` *required*

**vault\_id** `string` *required*

The vault to hold the item. It must be the brand's default vault or another vault the brand allows.

**nonce** `string` *required*

The 32-byte nonce in the owner's signed approval.

**owner\_signature** `string` *required*

The owner's signature over the approval.

## Returns

`201` - `VaultRequest`.

**id** `string` *required*

**unit\_id** `string` *required*

**vault** `object` *required*

**status** `'pending' | 'submitted' | 'active' | 'unvault_waiting' | 'unvaulting' | 'unvaulted' | 'cancelled' | 'expired' | 'rejected' | 'failed'` *required*

**notes** `string | null` *required*

**rejection\_reason** `string | null` *required*

Why the request was rejected: the vault's reason, or `owner_changed` when the unit changed hands after its owner approved.

**decided\_at** `string | null` *required*

**available\_at** `string | null` *required*

**hold** `object | null` *required*

**ready\_to\_ship** `boolean` *required*

Whether the item is ready to ship: its waiting period has ended and nothing holds it. The vault records dispatch with a tap of the item from then on.

**dispatched\_at** `string | null` *required*

When the vault's tap recorded the item's dispatch. Endstate then completes the unvault; the vault hands the item over once the request reads `unvaulted`.

**expires\_at** `string | null` *required*

When a pending request expires; null once it has moved on.

## Errors

Branch on `error.code`, never on the HTTP status - several codes share one.

| Code | HTTP | Retry |
| - | - | - |
| `auth.forbidden` | 403 | Do not retry |
| `auth.unauthorized` | 401 | Do not retry |
| `collection.not_active` | 409 | Wait, then retry |
| `idempotency.in_progress` | 409 | Safe to retry |
| `idempotency.key_conflict` | 409 | Do not retry |
| `internal.error` | 500 | Safe to retry |
| `not_found.resource` | 404 | Do not retry |
| `rate_limit.exceeded` | 429 | Safe to retry |
| `session_token.invalid_or_expired` | 401 | Do not retry |
| `session_token.wrong_chip` | 403 | Do not retry |
| `unit.not_found` | 404 | Do not retry |
| `unit.not_minted` | 409 | Poll the resource |
| `validation.failed` | 400 | Do not retry |
| `vault.consent_invalid` | 403 | Do not retry |
| `vault.consent_used` | 409 | Do not retry |
| `vault.in_progress` | 409 | Do not retry |
| `vault.not_found` | 404 | Do not retry |
| `vault.not_permitted` | 403 | Do not retry |
| `vault.unavailable` | 409 | Do not retry |

See [Errors and retries](https://docs.endstate.io/sdks/core/errors-and-retries.md) for the error types and how to narrow them.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.