Internal Accounts

Create an internal account

Changed on

Create a rule-based internal account.

A rule-based account is an additional account number for an account holder that already holds an account in the same currency. It carries a routing rule: every payment that settles into it is attributed to that account number and then swept to the rule's destination, so you can issue one number per payer and reconcile incoming payments without matching on remittance text.

Only RULE_BASED accounts can be created here. INTERNAL_FIAT, INTERNAL_CRYPTO, and EMBEDDED_WALLET accounts are provisioned automatically when an account holder is created or approved.

The response carries the account's own fundingPaymentInstructions — the routable number payers send to. Rule-based accounts are currently available in USD, for individual customers, and must be enabled for your platform before this endpoint accepts requests.

Sandbox platforms can create rule-based accounts and exercise the whole flow. The account number is generated locally rather than issued by a partner bank, and POST /sandbox/internal-accounts/{accountId}/fund stands in for a settled deposit — funding the account triggers its sweep just as a real deposit would.

Send an Idempotency-Key header to make retries safe: a request carrying a key already used returns the account created by the first request with a 200 instead of a 201. Reusing a key for a materially different account is rejected with 409. Without a key a retry cannot be recognised, so each request creates its own account and mints its own account number.

post/internal-accounts

Request

  • Base URL: https://api.lightspark.com/grid/2025-10-13
  • URL: https://api.lightspark.com/grid/2025-10-13/internal-accounts
  • Auth: HTTP basic

Headers

Idempotency-Keystring
Example:550e8400-e29b-41d4-a716-446655440000

A unique identifier for the request. Strongly recommended: creating the account mints an account number that cannot be reversed, and the key is what lets a retry return the first account rather than minting a second.

Request body

customerIdstring

The customer the account is created for. Omit it to create a platform-owned account. The account holder must already have a verified account in the same currency, which is where funds land when a sweep cannot be completed. Platform-owned rule-based accounts are not available yet, so omitting this is currently rejected.

type'INTERNAL_FIAT' | 'INTERNAL_CRYPTO' | 'EMBEDDED_WALLET' | 'RULE_BASED' | 'BULK_SETTLEMENT' required

Classification of an internal account.

  • INTERNAL_FIAT: A Grid-managed fiat holding account (for example, the USD holding account used as the source for Payouts flows).
  • INTERNAL_CRYPTO: A Grid-managed crypto holding account denominated in a stablecoin such as USDC.
  • EMBEDDED_WALLET: A self-custodial Embedded Wallet provisioned for the customer. Outbound transfers require a session signature produced by the customer's device — see the Embedded Wallets guide.
  • RULE_BASED: An additional account number for an existing account holder, with a routing rule attached, so incoming payments can be attributed to a specific payer and swept automatically. Created with POST /internal-accounts.
  • BULK_SETTLEMENT: An account for receiving bulk payments (for example, a single settlement from a payment processor) that the platform then pays out to its customers. Only a platform can hold one, and funds in it can move only to the platform's customers.
currencystring required

Currency code the account is denominated in (ISO 4217). Rule-based accounts are currently available in USD only.

labelstring

Your own name for the account, echoed back on reads. Useful for identifying which payer the account was issued for.

Example request

{
  "customerId": "Customer:019542f5-b3e7-1d02-0000-000000000001",
  "currency": "USD",
  "label": "invoice-4417",
  "sweepRule": {
    "destination": {
      "accountId": "ExternalAccount:e85dcbd6-dced-4ec4-b756-3c3a9ea3d965",
      "paymentRail": "ACH"
    },
    "description": "Rent sweep",
    "remittanceInformation": "Unit 4B March",
    "platformFeeOverride": {
      "platformFixedFee": {
        "amount": 50,
        "currency": "USD"
      },
      "platformVariableFeeBps": 30
    }
  }
}

Response

The Idempotency-Key was already used to create this account. The account created by the first request is returned unchanged.

idstring required

The ID of the internal account

customerIdstring

The ID of the customer associated with the internal account. If this field is empty, the internal account belongs to the platform.

type'INTERNAL_FIAT' | 'INTERNAL_CRYPTO' | 'EMBEDDED_WALLET' | 'RULE_BASED' | 'BULK_SETTLEMENT' required

Classification of an internal account.

  • INTERNAL_FIAT: A Grid-managed fiat holding account (for example, the USD holding account used as the source for Payouts flows).
  • INTERNAL_CRYPTO: A Grid-managed crypto holding account denominated in a stablecoin such as USDC.
  • EMBEDDED_WALLET: A self-custodial Embedded Wallet provisioned for the customer. Outbound transfers require a session signature produced by the customer's device — see the Embedded Wallets guide.
  • RULE_BASED: An additional account number for an existing account holder, with a routing rule attached, so incoming payments can be attributed to a specific payer and swept automatically. Created with POST /internal-accounts.
  • BULK_SETTLEMENT: An account for receiving bulk payments (for example, a single settlement from a payment processor) that the platform then pays out to its customers. Only a platform can hold one, and funds in it can move only to the platform's customers.
status'PENDING' | 'ACTIVE' | 'CLOSED' | 'FROZEN' | 'FAILED' required

Status of a Grid internal account. The status determines whether the account can send or receive payments.

  • PENDING: The account is under review and is being provisioned. The account cannot send or receive payments until provisioning completes.
  • ACTIVE: The account is ready to send and receive payments.
  • CLOSED: The account cannot send or receive payments. A customer can initiate the closing of an internal account, after which the account transitions to this status.
  • FROZEN: The account cannot send or receive payments. Grid may freeze an account in response to compliance or fraud signals; payments are blocked while the account remains frozen.
  • FAILED: The account could not be provisioned. Grid was unable to create the underlying account, so it cannot send or receive payments and requires remediation.
fundingPaymentInstructionsPaymentInstructions[] required(unresolved $ref)

Payment instructions for funding the account

labelstring

The platform-supplied label recorded when the account was created. Null for accounts that carry none.

privateEnabledboolean

Whether wallet privacy is enabled for the Embedded Wallet. Only present for EMBEDDED_WALLET internal accounts.

createdAtstring date-time required

Timestamp when the internal account was created

updatedAtstring date-time required

Timestamp when the internal account was last updated

Changes

    • warning

      added the new ACH_SAME_DAY enum value to the ////////// response property for the response status

    • warning

      added the new ACH_SAME_DAY enum value to the ////////// response property for the response status

    • warning

      added the new ACH_SAME_DAY enum value to the //////// response property for the response status

    • warning

      added the new ACH_SAME_DAY enum value to the //////// response property for the response status

    • warning

      added the new BULK_SETTLEMENT enum value to the response property for the response status

    • warning

      added the new BULK_SETTLEMENT enum value to the response property for the response status

    • info

      added the new optional request property //

    • info

      added the new ACH_SAME_DAY enum value to the request property ////////

    • info

      added the new BULK_SETTLEMENT enum value to the request property /

    • warning

      removed the optional property //////////// from the response with the status

    • warning

      removed the optional property //////////// from the response with the status

    • info

      added the optional property ///////// to the response with the status

    • info

      added the optional property ///////// to the response with the status