---
title: "Export internal account wallet credentials"
method: POST
path: "/internal-accounts/{id}/export"
tags: ["Internal Accounts"]
---

# Export internal account wallet credentials

`POST /internal-accounts/{id}/export`

Export the wallet credentials of an Embedded Wallet internal account. The returned wallet credentials are HPKE-encrypted to the `clientPublicKey` supplied in the request body.

Export is a two-step signed-retry flow (same pattern as add-additional credential, revoke credential, and revoke session):

1. Call `POST /internal-accounts/{id}/export` with the request body `{ "clientPublicKey": "..." }` and no signature headers. Grid binds the `clientPublicKey` into the `payloadToSign` it returns, so the subsequent stamp in `Grid-Wallet-Signature` commits to the target encryption key. The response is `202` with `payloadToSign`, `requestId`, and `expiresAt`.

2. Use the session API keypair of a verified authentication credential on the same internal account to build an API-key stamp over `payloadToSign`, then retry with that full stamp as the `Grid-Wallet-Signature` header and the `requestId` echoed back as the `Request-Id` header. The retry body must carry the **same** `clientPublicKey` submitted in step 1 — Grid rejects the retry with `401` if it disagrees with what was bound into `payloadToSign`. The signed retry returns `200` with `encryptedWalletCredentials`, which the client decrypts with the matching private key.

The export may not settle within that request: an approval- or consensus-gated wallet-provider activity answers `200` with `status: "PROCESSING"` instead. The credentials are never stored server-side, so collecting them is the client's job — re-send the byte-identical signed retry (same headers, same body) until it returns `encryptedWalletCredentials`. The `Request-Id` challenge stays usable until an attempt actually delivers them, so a `PROCESSING` response never burns it; a delivered export does, and a later re-send is then rejected with `401`. Subscribe to `wallet_operation.completed` to learn when re-sending will succeed rather than polling blind.

The `clientPublicKey` is ephemeral: generate a fresh P-256 keypair for this export and discard the private key after decrypting. Do not reuse the keypair from any prior verify call — that private key was already discarded after decrypting the session signing key it was issued against.

## Path parameters

- `id` string, required

## Headers

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

## Request body

- InternalAccountExportRequest — Request body for `POST /internal-accounts/{id}/export`. The `clientPublicKey` is required on both steps of the signed-retry flow. On step 1 Grid binds it into `payloadToSign` so the subsequent stamp in `Grid-Wallet-Signature` commits to the target pubkey; on step 2 the client echoes the same `clientPublicKey` back and Grid uses it to encrypt the wallet credentials returned in the `200` response.
  - `clientPublicKey` string, required — Fresh P-256 public key, uncompressed SEC1 hex — 130 hex chars where the first two are `04` (the uncompressed-point indicator). Generate a new keypair for each export and discard the private key after decrypting the response.

## Response `200`

Signed retry accepted. Returns the encrypted wallet credentials (`InternalAccountExportResponse`); or, when the underlying wallet-provider activity is still in flight, a `WalletOperationProcessing` body with `status: "PROCESSING"` — the credentials are never stored server-side, so the client re-sends the byte-identical signed retry to collect them once the activity settles. The challenge stays usable until an attempt actually returns credentials.

- union — Response body for the signed retry of `POST /internal-accounts/{internalAccountId}/export`. Normally an `InternalAccountExportResponse` — the encrypted wallet credentials. When the underlying wallet-provider activity is still in flight, this is instead a `WalletOperationProcessing` body with `status: "PROCESSING"`. The credentials are never stored server-side, so re-sending the byte-identical signed retry is how they are collected: the re-send returns them as soon as the activity has settled, and the challenge is consumed only by the attempt that delivers them.
  - InternalAccountExportResponse
    - `id` string, required — The id of the internal account that was exported.
    - `encryptedWalletCredentials` string, required — Encrypted wallet mnemonic, sealed to the `clientPublicKey` from the request body using HPKE: DHKEM(P-256, HKDF-SHA256) + HKDF-SHA256 + AES-256-GCM. Decrypt with the matching private key, then manage the mnemonic securely because it is the master key of the self-custodial Embedded Wallet. The value is a JSON string of the form `{"version": "v1.0.0", "data": "<hex>", "dataSignature": "<hex>", "enclaveQuorumPublic": "<hex>"}`. `data` hex-decodes to JSON `{"encappedPublic": "<hex>", "ciphertext": "<hex>", "organizationId": "<id>"}`, where `encappedPublic` is the uncompressed SEC1 ephemeral public key. `dataSignature` is an ECDSA-P256-SHA256 signature over the `data` bytes produced by the issuer key in `enclaveQuorumPublic`; verify before decrypting. In sandbox, `dataSignature` and `enclaveQuorumPublic` are empty strings. Clients should bypass attestation verification when calling against sandbox.
  - WalletOperationProcessing — `200` response returned by an Embedded Wallet operation that the wallet provider has accepted but not yet settled — a consensus- or approval-gated activity that is still in flight. It is not an error and needs no client action beyond patience: the backend reconciles the operation to its terminal state on its own. The client MAY re-send the byte-identical request to converge sooner; the request is idempotent and returns the settled success response once the operation completes.
    - `status` 'PROCESSING', required — Always `PROCESSING`. Marks a still-in-flight operation whose terminal result is not yet available.
    - `message` string — Human-readable explanation that the operation is still being processed and the same request may be retried.

## Other responses

- `202` — Challenge issued. The response contains `payloadToSign` (which binds the submitted `clientPublicKey`) plus a `requestId`. Build an API-key stamp over `payloadToSign` with the session API keypair and echo `requestId` on the retry.
- `400` — Bad request
- `401` — Unauthorized. Returned when the provided `Grid-Wallet-Signature` is missing, malformed, or does not match a pending export challenge for this internal account, 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` — Internal account not found
- `500` — Internal service error

## Changes

- **2026-08-25** `8964d9c7b6f9` — 3 breaking, 1 info
  - the response's body type/format changed from `object`/`` to ``/`` for status `200`
  - removed the required property `encryptedWalletCredentials` from the response with the `200` status
  - removed the required property `id` from the response with the `200` status
  - added `#/components/schemas/InternalAccountExportResponse, #/components/schemas/WalletOperationProcessing` to the response body `anyOf` list for the response status `200`
- **2026-08-14** `aaa1fb8782c8` — 1 warning
  - added the new `EXTERNAL_ACCOUNT_VERIFICATION_REQUIRED` enum value to the `code` response property for the response status `400`
- **2026-08-13** `df12ec487f0e` — 1 warning
  - added the new `TRANSACTION_SIZE_LIMIT_EXCEEDED` enum value to the `code` response property for the response status `400`
- **2026-08-11** `b06902b6595a` — 1 warning
  - added the new `CARDHOLDER_KYC_NOT_APPROVED` enum value to the `code` response property for the response status `400`
- **2026-08-06** `526036c12609` — 1 warning
  - added the new `END_USER_TERMS_VERSION_NOT_FOUND` enum value to the `code` response property for the response status `400`

[Full history](https://skmtc.dev/stainless-api/apis/grid-api/changes/internal-accounts/:id/export/post.md)

---

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