> ## Documentation Index
> Fetch the complete documentation index at: https://ramps-04-30-docs-add-grid-tutorial-skill-interactive-zero-t.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Export internal account wallet credentials

> 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 `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.




## OpenAPI

````yaml https://app.stainless.com/api/spec/documented/grid/openapi.documented.yml post /internal-accounts/{id}/export
openapi: 3.1.0
info:
  title: Grid API
  description: >
    API for managing global payments on the open Money Grid. Built by
    Lightspark. See the full documentation at https://grid.lightspark.com/.
  version: '2025-10-13'
  contact:
    name: Lightspark Support
    email: support@lightspark.com
  license:
    name: Proprietary
    url: https://lightspark.com/terms
servers:
  - url: https://api.lightspark.com/grid/2025-10-13
    description: Production server
security:
  - BasicAuth: []
tags:
  - name: Platform Configuration
    description: >-
      Platform configuration endpoints for managing global settings. You can
      also configure these settings in the Grid dashboard.
  - name: Customers
    description: >-
      Customer management endpoints for creating and updating customer
      information
  - name: KYC/KYB Verifications
    description: >-
      Endpoints for Know Your Customer (KYC) and Know Your Business (KYB)
      verification, including managing beneficial owners and triggering
      verification for customers.
  - name: Documents
    description: >-
      Endpoints for uploading and managing verification documents for customers
      and beneficial owners. Supports KYC and KYB document requirements.
  - name: Internal Accounts
    description: >-
      Internal account management endpoints for creating and managing internal
      accounts
  - name: External Accounts
    description: >-
      External account management endpoints for creating and managing external
      bank accounts
  - name: Same-Currency Transfers
    description: >-
      Endpoints for transferring funds between internal and external accounts
      with the same currency
  - name: Cross-Currency Transfers
    description: Endpoints for creating and confirming quotes for cross-currency transfers
  - name: Transactions
    description: Endpoints for retrieving transaction information
  - name: Webhooks
    description: Webhook endpoints and configuration for receiving notifications
  - name: Invitations
    description: Endpoints for creating, claiming and managing UMA invitations
  - name: Sandbox
    description: Endpoints to trigger test cases in sandbox
  - name: API Tokens
    description: Endpoints to programmatically manage API tokens
  - name: Exchange Rates
    description: >-
      Endpoints for retrieving cached foreign exchange rates. Rates are cached
      for approximately 5 minutes and include platform-specific fees.
  - name: Discoveries
    description: >-
      Endpoints for discovering available payment rails, banks, and providers
      for a given country and currency corridor.
  - name: Embedded Wallet Auth
    description: >-
      Endpoints for registering and verifying end-user authentication
      credentials (email OTP, OAuth, passkey) used to sign Embedded Wallet
      actions.
paths:
  /internal-accounts/{id}/export:
    post:
      tags:
        - Internal Accounts
      summary: Export internal account wallet credentials
      description: >
        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 `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.
      operationId: exportInternalAccount
      parameters:
        - name: id
          in: path
          description: The id of the internal account to export.
          required: true
          schema:
            type: string
        - name: Grid-Wallet-Signature
          in: header
          required: false
          description: >-
            Full API-key stamp built over the prior `payloadToSign` with the
            session API keypair of a verified authentication credential on the
            target internal account. Required on the signed retry; ignored on
            the initial call.
          schema:
            type: string
          example: >-
            eyJwdWJsaWNLZXkiOiIwMmExYjIuLi4iLCJzaWduYXR1cmUiOiIzMDQ1MDIyMTAwLi4uIiwic2NoZW1lIjoiUDI1Nl9FQ0RTQV9TSEEyNTYifQ
        - name: Request-Id
          in: header
          required: false
          description: >-
            The `requestId` returned in a prior `202` response, echoed back on
            the signed retry so the server can correlate it with the issued
            challenge. Required on the signed retry; must be paired with
            `Grid-Wallet-Signature`.
          schema:
            type: string
          example: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InternalAccountExportRequest'
            examples:
              export:
                summary: Export request (both steps)
                value:
                  clientPublicKey: >-
                    04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2
      responses:
        '200':
          description: Signed retry accepted. Returns the encrypted wallet credentials.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalAccountExportResponse'
        '202':
          description: >-
            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.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SignedRequestChallenge'
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error400'
        '401':
          description: >-
            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.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error401'
        '404':
          description: Internal account not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error404'
        '500':
          description: Internal service error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error500'
      security:
        - BasicAuth: []
      x-codeSamples:
        - lang: JavaScript
          source: |-
            import LightsparkGrid from '@lightsparkdev/grid';

            const client = new LightsparkGrid({
              username: process.env['GRID_CLIENT_ID'], // This is the default and can be omitted
              password: process.env['GRID_CLIENT_SECRET'], // This is the default and can be omitted
            });

            const response = await client.internalAccounts.export('id', {
              clientPublicKey:
                '04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2',
            });

            console.log(response.id);
        - lang: Python
          source: |-
            import os
            from grid import LightsparkGrid

            client = LightsparkGrid(
                username=os.environ.get("GRID_CLIENT_ID"),  # This is the default and can be omitted
                password=os.environ.get("GRID_CLIENT_SECRET"),  # This is the default and can be omitted
            )
            response = client.internal_accounts.export(
                id="id",
                client_public_key="04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2",
            )
            print(response.id)
        - lang: Kotlin
          source: >-
            package com.lightspark.grid.example


            import com.lightspark.grid.client.LightsparkGridClient

            import com.lightspark.grid.client.okhttp.LightsparkGridOkHttpClient

            import
            com.lightspark.grid.models.internalaccounts.InternalAccountExportParams

            import
            com.lightspark.grid.models.internalaccounts.InternalAccountExportResponse


            fun main() {
                val client: LightsparkGridClient = LightsparkGridOkHttpClient.fromEnv()

                val params: InternalAccountExportParams = InternalAccountExportParams.builder()
                    .id("id")
                    .clientPublicKey("04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2")
                    .build()
                val response: InternalAccountExportResponse = client.internalAccounts().export(params)
            }
components:
  schemas:
    InternalAccountExportRequest:
      title: Internal Account Export Request
      description: >-
        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.
      type: object
      required:
        - clientPublicKey
      properties:
        clientPublicKey:
          type: string
          description: >-
            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.
          example: >-
            04f45f2a22c908b9ce09a7150e514afd24627c401c38a4afc164e1ea783adaaa31d4245acfb88c2ebd42b47628d63ecabf345484f0a9f665b63c54c897d5578be2
    InternalAccountExportResponse:
      title: Internal Account Export Response
      type: object
      required:
        - id
        - encryptedWalletCredentials
      properties:
        id:
          type: string
          description: The id of the internal account that was exported.
          example: InternalAccount:019542f5-b3e7-1d02-0000-000000000002
        encryptedWalletCredentials:
          type: string
          description: >-
            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.
          example: >-
            {"version":"v1.0.0","data":"7b22656e6361707065645075626c6963223a22303433...","dataSignature":"3045022100c9...","enclaveQuorumPublic":"04a1b2c3..."}
    SignedRequestChallenge:
      title: Signed Request Challenge
      type: object
      required:
        - payloadToSign
        - requestId
        - expiresAt
      description: >-
        Common base for two-step signed-retry challenge responses on Embedded
        Wallet endpoints (credential revocation, session revocation, wallet
        export, and similar). Holds the signing fields shared across every
        challenge shape; each variant composes this base via `allOf` and adds
        its own resource `id` (and `type`, when applicable) with
        variant-specific description and example.
      properties:
        payloadToSign:
          type: string
          description: >-
            Canonical payload for the retry authorization stamp. Build an
            API-key stamp over this exact value with the session API keypair,
            then send the full base64url-encoded stamp in
            `Grid-Wallet-Signature` on the retry that completes the original
            request.
          example: Y2hhbGxlbmdlLXBheWxvYWQtdG8tc2lnbg==
        requestId:
          type: string
          description: >-
            Unique identifier for this request. Must be echoed in the
            `Request-Id` header on the signed retry so the server can correlate
            the retry with the issued challenge.
          example: 7c4a8d09-ca37-4e3e-9e0d-8c2b3e9a1f21
        expiresAt:
          type: string
          format: date-time
          description: >-
            Timestamp after which this challenge is no longer valid. The signed
            retry must be submitted before this time.
          example: '2026-04-08T15:35:00Z'
    Error400:
      type: object
      required:
        - message
        - status
        - code
      properties:
        status:
          type: integer
          enum:
            - 400
          description: HTTP status code
        code:
          type: string
          description: >
            | Error Code | Description |

            |------------|-------------|

            | INVALID_INPUT | Invalid input provided |

            | MISSING_MANDATORY_USER_INFO | Required customer information is
            missing |

            | INVITATION_ALREADY_CLAIMED | Invitation has already been claimed |

            | INVITATIONS_NOT_CONFIGURED | Invitations are not configured |

            | INVALID_UMA_ADDRESS | UMA address format is invalid |

            | INVITATION_CANCELLED | Invitation has been cancelled |

            | QUOTE_REQUEST_FAILED | An issue occurred during the quote process;
            this is retryable |

            | INVALID_PAYREQ_RESPONSE | Counterparty Payreq response was invalid
            |

            | INVALID_RECEIVER | Receiver is invalid |

            | PARSE_PAYREQ_RESPONSE_ERROR | Error parsing receiver PayReq
            response |

            | CERT_CHAIN_INVALID | Counterparty certificate chain is invalid |

            | CERT_CHAIN_EXPIRED | Counterparty certificate chain has expired |

            | INVALID_PUBKEY_FORMAT | Counterparty Public key format is invalid
            |

            | MISSING_REQUIRED_UMA_PARAMETERS | Counterparty required UMA
            parameters are missing |

            | SENDER_NOT_ACCEPTED | Sender is not accepted |

            | AMOUNT_OUT_OF_RANGE | Amount is out of range |

            | INVALID_CURRENCY | Currency is invalid |

            | INVALID_TIMESTAMP | Timestamp is invalid |

            | INVALID_NONCE | Nonce is invalid |

            | INVALID_REQUEST_FORMAT | Request format is invalid |

            | INVALID_BANK_ACCOUNT | Bank account is invalid |

            | SELF_PAYMENT | Self payment not allowed |

            | LOOKUP_REQUEST_FAILED | Lookup request failed |

            | PARSE_LNURLP_RESPONSE_ERROR | Error parsing LNURLP response |

            | INVALID_AMOUNT | Amount is invalid |

            | WEBHOOK_ENDPOINT_NOT_SET | Webhook endpoint is not set |

            | WEBHOOK_DELIVERY_ERROR | Webhook delivery error |

            | LOW_QUALITY | Document quality too low to process |

            | DATA_MISMATCH | Document details don't match provided information
            |

            | EXPIRED | Document has expired |

            | SUSPECTED_FRAUD | Document suspected of being forged or edited |

            | UNSUITABLE_DOCUMENT | Document type is not accepted or not
            supported |

            | INCOMPLETE | Document is missing pages or sides |

            | EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS | An EMAIL_OTP credential is
            already registered on the target internal account; only one email
            OTP credential is supported per internal account at this time |

            | PASSKEY_CREDENTIAL_ALREADY_EXISTS | A PASSKEY credential is
            already registered on the target internal account; only one passkey
            credential is supported per internal account in v1 |
          enum:
            - INVALID_INPUT
            - MISSING_MANDATORY_USER_INFO
            - INVITATION_ALREADY_CLAIMED
            - INVITATIONS_NOT_CONFIGURED
            - INVALID_UMA_ADDRESS
            - INVITATION_CANCELLED
            - QUOTE_REQUEST_FAILED
            - INVALID_PAYREQ_RESPONSE
            - INVALID_RECEIVER
            - PARSE_PAYREQ_RESPONSE_ERROR
            - CERT_CHAIN_INVALID
            - CERT_CHAIN_EXPIRED
            - INVALID_PUBKEY_FORMAT
            - MISSING_REQUIRED_UMA_PARAMETERS
            - SENDER_NOT_ACCEPTED
            - AMOUNT_OUT_OF_RANGE
            - INVALID_CURRENCY
            - INVALID_TIMESTAMP
            - INVALID_NONCE
            - INVALID_REQUEST_FORMAT
            - INVALID_BANK_ACCOUNT
            - SELF_PAYMENT
            - LOOKUP_REQUEST_FAILED
            - PARSE_LNURLP_RESPONSE_ERROR
            - INVALID_AMOUNT
            - WEBHOOK_ENDPOINT_NOT_SET
            - WEBHOOK_DELIVERY_ERROR
            - LOW_QUALITY
            - DATA_MISMATCH
            - EXPIRED
            - SUSPECTED_FRAUD
            - UNSUITABLE_DOCUMENT
            - INCOMPLETE
            - EMAIL_OTP_CREDENTIAL_ALREADY_EXISTS
            - PASSKEY_CREDENTIAL_ALREADY_EXISTS
        message:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error401:
      type: object
      required:
        - message
        - status
        - code
      properties:
        status:
          type: integer
          enum:
            - 401
          description: HTTP status code
        code:
          type: string
          description: |
            | Error Code | Description |
            |------------|-------------|
            | UNAUTHORIZED | Issue with API credentials |
            | INVALID_SIGNATURE | Signature header is invalid |
          enum:
            - UNAUTHORIZED
            - INVALID_SIGNATURE
        message:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error404:
      type: object
      required:
        - message
        - status
        - code
      properties:
        status:
          type: integer
          enum:
            - 404
          description: HTTP status code
        code:
          type: string
          description: |
            | Error Code | Description |
            |------------|-------------|
            | TRANSACTION_NOT_FOUND | Transaction not found |
            | INVITATION_NOT_FOUND | Invitation not found |
            | USER_NOT_FOUND | Customer not found |
            | QUOTE_NOT_FOUND | Quote not found |
            | LOOKUP_REQUEST_NOT_FOUND | Lookup request not found |
            | TOKEN_NOT_FOUND | Token not found |
            | BULK_UPLOAD_JOB_NOT_FOUND | Bulk upload job not found |
            | REFERENCE_NOT_FOUND | Reference not found |
          enum:
            - TRANSACTION_NOT_FOUND
            - INVITATION_NOT_FOUND
            - USER_NOT_FOUND
            - QUOTE_NOT_FOUND
            - LOOKUP_REQUEST_NOT_FOUND
            - TOKEN_NOT_FOUND
            - BULK_UPLOAD_JOB_NOT_FOUND
            - REFERENCE_NOT_FOUND
        message:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
    Error500:
      type: object
      required:
        - message
        - status
        - code
      properties:
        status:
          type: integer
          enum:
            - 500
          description: HTTP status code
        code:
          type: string
          description: |
            | Error Code | Description |
            |------------|-------------|
            | GRID_SWITCH_ERROR | Grid switch error |
            | INTERNAL_ERROR | Internal server or UMA error |
          enum:
            - GRID_SWITCH_ERROR
            - INTERNAL_ERROR
        message:
          type: string
          description: Error message
        details:
          type: object
          description: Additional error details
          additionalProperties: true
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
      description: >-
        API token authentication using format `<api token id>:<api client
        secret>`

````