---
title: "Refresh an authentication session"
method: POST
path: "/auth/sessions/{id}/refresh"
tags: ["Embedded Wallet Auth"]
---

# Refresh an authentication session

`POST /auth/sessions/{id}/refresh`

Refresh an active Embedded Wallet auth session and create a new session signing key. Session refresh is a two-step signed-retry flow:

1. Call `POST /auth/sessions/{id}/refresh` with the request body `{ "clientPublicKey": "02..." }` and no signature headers. Send a freshly generated client public key and retain its private key. Grid binds the supplied `clientPublicKey` into the session-refresh payload, persists it as a pending request, and returns `202` with `payloadToSign`, `requestId`, and `expiresAt`.

2. Sign `payloadToSign` with the current session signing key, then retry the same request with the full API-key stamp as `Grid-Wallet-Signature`, the `requestId` echoed back as `Request-Id`, and the same `clientPublicKey` in the request body. On success, Grid returns a new `AuthSession`. Sending a compressed `clientPublicKey` selects the recommended client-held-key model, where the client retains the new session signing key and no key material is returned; sending an uncompressed key selects the deprecated legacy flow, where the new key is sealed to it and returned as `encryptedSessionSigningKey`.

The original session must still be active on both steps so it can authorize the refresh. If the session has already expired, use the credential reauthentication flow instead.

## Path parameters

- `id` string, required

## Headers

- `Grid-Wallet-Signature` string
- `Request-Id` string

## Request body

- AuthSessionRefreshRequest — Request body for refreshing an active authentication session. The `clientPublicKey` is required on both steps of the signed-retry flow and must match on both. Its SEC1 encoding selects how the refreshed session signing key is delivered: a compressed key gets the recommended client-held-key model, where the client retains the new signing key itself; an uncompressed key gets the deprecated legacy flow, where Grid returns the new key as `encryptedSessionSigningKey` sealed to it. On the initial call, Grid binds the supplied key into the session-creation payload returned as `payloadToSign`.
  - `clientPublicKey` string, required — Client-generated P-256 public key; the matching private key is retained on the client. Send a compressed SEC1 key (`02`/`03` prefix followed by the 32-byte X coordinate; 66 hex characters) for the recommended client-held-key model, where that private key becomes the new session signing key. Send an uncompressed SEC1 key (`04` prefix followed by the 32-byte X and 32-byte Y coordinates; 130 hex characters) for the deprecated legacy flow, where Grid seals the new session signing key to it and returns it as `encryptedSessionSigningKey` on the signed retry.

## Response `201`

New authentication session created successfully.

- AuthSession — An authentication session on an Embedded Wallet internal account. Returned from `GET /auth/sessions` (list) and `POST /auth/credentials/{id}/verify` (on credential verification) or `POST /auth/sessions/{id}/refresh` (on mid-session refresh). The `clientPublicKey` encoding on the issuing request selects the flow: a compressed key gets the client-held-key model, where the client generates and retains the session signing key and session-issuing responses carry no key material; an uncompressed key gets the deprecated legacy flow, where Grid seals the session signing key to that public key and returns it as `encryptedSessionSigningKey`. Never returned by the list endpoint.
  - `id` string, required — System-generated unique identifier for the session. Pass this value to `DELETE /auth/sessions/{id}` to revoke the session before `expiresAt`. Overrides the `id` inherited from `AuthMethod` so this response identifies the session rather than the authenticating credential.
  - `accountId` string, required — Identifier of the internal account that this credential authenticates.
  - `type` 'OAUTH' | 'EMAIL_OTP' | 'SMS_OTP' | 'PASSKEY', required — The type of authentication credential. - `OAUTH`: OpenID Connect (OIDC) token issued by an identity provider such as Google or Apple. - `EMAIL_OTP`: A one-time password delivered to the user's email address. - `SMS_OTP`: A one-time password delivered to the user's phone number. - `PASSKEY`: A WebAuthn passkey bound to the user's device.
  - `credentialId` string — Base64url-encoded WebAuthn credential identifier for this passkey. Present only for `PASSKEY` authentication credentials. Corresponds to `PublicKeyCredential.rawId`; pass this value as `allowCredentials[].id` when requesting a passkey assertion for this auth method.
  - `nickname` string, required — Human-readable identifier for this credential. For EMAIL_OTP credentials this is the email address; for SMS_OTP credentials this is the E.164 phone number; for OAUTH credentials it is typically the email claim from the OIDC token; for PASSKEY credentials it is the validated nickname provided at registration time.
  - `createdAt` string, date-time, required — Creation timestamp.
  - `updatedAt` string, date-time, required — Last update timestamp.
  - `encryptedSessionSigningKey` string — Deprecated; present only for the legacy flow, selected by sending an uncompressed `clientPublicKey` on the verification or refresh request. Grid seals the session signing key to that public key and returns it here as a base58check string (a 33-byte compressed P-256 encapsulated public key followed by AES-256-GCM ciphertext) for the client to decrypt with its private key. The recommended client-held-key flow sends a compressed `clientPublicKey` instead: the client generates and retains the session signing key itself, so this field is omitted — the same way `EMAIL_OTP` and `SMS_OTP` sessions have always worked. See the "Client keys & signing" guide. Always omitted from list responses (`GET /auth/sessions`).
  - `expiresAt` string, date-time, required — Timestamp after which the session is no longer valid and the session signing key must not be used to sign further requests.

## Other responses

- `202` — Challenge issued. The response contains `payloadToSign` plus a `requestId`. Build an API-key stamp over `payloadToSign` with the current session API keypair, then echo `requestId` on the signed retry.
- `400` — Bad request
- `401` — Unauthorized. Returned when the `BasicAuth` credentials are missing or invalid, when the target session is no longer active and cannot be used for refresh, when the signed retry omits `Grid-Wallet-Signature`, when the provided signature is malformed or does not match the pending refresh challenge, when the `Request-Id` does not match an unexpired pending challenge, or when the retry's `clientPublicKey` does not match the one bound into `payloadToSign` on the initial call.
- `404` — Session not found
- `500` — Internal service error

---

[API](https://skmtc.net/stainless-api/apis/grid-api.md) · [All operations](https://skmtc.net/stainless-api/apis/grid-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/stainless-api/grid-api/revisions/4f1f6b937f93/schema)
