---
title: "Internal account status webhook"
method: POST
path: "internal-account-status"
tags: ["Webhooks"]
---

# Internal account status webhook

`POST internal-account-status` (webhook)

Webhook that is called when the status of an internal account changes. This includes balance updates and may include additional account events in the future.
This endpoint should be implemented by clients of the Grid API.

### Authentication
The webhook includes a signature in the `X-Grid-Signature` header that allows you to verify that the webhook was sent by Grid.
To verify the signature:
1. Get the Grid public key provided to you during integration
2. Decode the base64 signature from the header
3. Create a SHA-256 hash of the request body
4. Verify the signature using the public key and the hash

If the signature verification succeeds, the webhook is authentic. If not, it should be rejected.

### Event types
- `INTERNAL_ACCOUNT.BALANCE_UPDATED` — Fired when the balance of an internal account changes. The `data` payload contains the full internal account object.
- `INTERNAL_ACCOUNT.STATUS_UPDATED` — Fired when the status of an internal account changes (e.g., `OPEN` → `FROZEN`). The `data` payload contains the full internal account object.
- `INTERNAL_ACCOUNT.FUNDING_INSTRUCTIONS_UPDATED` — Fired when the account's `fundingPaymentInstructions` change: new funding coordinates became available (e.g., a SWIFT collection account finished provisioning) or previously served coordinates were withdrawn. The `data` payload contains the full internal account object, including the current `fundingPaymentInstructions`.

## Payload

- InternalAccountStatusWebhook
  - `id` string, required — Unique identifier for this webhook delivery (can be used for idempotency)
  - `type` 'INTERNAL_ACCOUNT.BALANCE_UPDATED' | 'INTERNAL_ACCOUNT.STATUS_UPDATED' | 'INTERNAL_ACCOUNT.FUNDING_INSTRUCTIONS_UPDATED', required — Type of webhook event in OBJECT.EVENT dot-notation. The part before the dot identifies the resource, the part after identifies the event. This lets consumers route purely on type without inspecting data.status.
  - `timestamp` string, date-time, required — ISO 8601 timestamp of when the webhook was sent
  - `data` InternalAccount, required
    - `id` string, required — The ID of the internal account
    - `customerId` string — 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', 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`.
    - `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.
    - `balance` CurrencyAmount, required
      - `amount` integer, required — Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
      - `currency` Currency, required
        - `code` string — Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
        - `name` string — Full name of the currency
        - `symbol` string — Symbol of the currency
        - `decimals` integer — Number of decimal places for the currency
    - `totalBalance` CurrencyAmount, required
      - `amount` integer, required — Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
      - `currency` Currency, required
        - `code` string — Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
        - `name` string — Full name of the currency
        - `symbol` string — Symbol of the currency
        - `decimals` integer — Number of decimal places for the currency
    - `fundingPaymentInstructions` PaymentInstructions[], required — Payment instructions for funding the account — unresolved $ref
    - `label` string — The platform-supplied label recorded when the account was created. Null for accounts that carry none.
    - `sweepRule` SweepRule — The routing rule attached to a rule-based account. Returned on the account rather than as a resource of its own, because the rule has no lifecycle apart from the account.
      - `destination` SweepRuleDestination, required — Where a rule-based account's credits are swept.
        - `accountId` string, required — The account that receives the swept funds.
        - `paymentRail` 'ACH' | 'ACH_COLOMBIA' | 'BANK_TRANSFER' | 'BRE_B' | 'CIPS' | 'FAST' | 'FASTER_PAYMENTS' | 'FEDNOW' | 'INSTAPAY' | 'MOBILE_MONEY' | 'NEFT' | 'PAYNOW' | 'PESONET' | 'PIX' | 'RTGS' | 'RTP' | 'SEPA' | 'SEPA_INSTANT' | 'SPEI' | 'SWIFT' | 'UNIONPAY' | 'UPI' | 'WIRE' — The payment rail used for the transfer. Payment rails represent the underlying payment network or system used to move funds between accounts.
      - `minimumAmount` CurrencyAmount
        - `amount` integer, required — Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
        - `currency` Currency, required
          - `code` string — Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
          - `name` string — Full name of the currency
          - `symbol` string — Symbol of the currency
          - `decimals` integer — Number of decimal places for the currency
      - `maximumAmount` CurrencyAmount
        - `amount` integer, required — Amount in the smallest unit of the currency (e.g., cents for USD/EUR, satoshis for BTC)
        - `currency` Currency, required
          - `code` string — Three-letter currency code (ISO 4217) for fiat currencies. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
          - `name` string — Full name of the currency
          - `symbol` string — Symbol of the currency
          - `decimals` integer — Number of decimal places for the currency
      - `purposeOfPayment` 'GIFT' | 'SELF' | 'GOODS_OR_SERVICES' | 'EDUCATION' | 'HEALTH_OR_MEDICAL' | 'REAL_ESTATE_PURCHASE' | 'TAX_PAYMENT' | 'LOAN_PAYMENT' | 'UTILITY_BILL' | 'DONATION' | 'TRAVEL' | 'FAMILY_SUPPORT' | 'SALARY_PAYMENT' | 'OTHER' — The purpose of the payment. This may be required when sending to certain geographies (e.g. India).
      - `description` string — Free-form description recorded on each sweep. Not delivered to the recipient.
      - `remittanceInformation` string — Free-form information that travels with each sweep to the recipient.
      - `platformFeeOverride` PlatformFeeOverride — Overrides the platform-collected fee for this transaction. When present, it replaces any configured platform-collected fees that would otherwise apply to the transaction. Currently only supported when the quote's source currency is USD; the fixed fee must be denominated in the source currency.
        - `platformFixedFee` FixedFee, required — Fixed fee charged per transaction.
          - `amount` integer, required — Fee amount in the smallest unit of the fixed fee's `currency` (e.g., cents for USD).
          - `currency` string, required — Three-letter currency code (ISO 4217) the fixed fee is denominated in. Some cryptocurrencies may use their own ticker symbols (e.g. "BTC" for Bitcoin, "USDC" for USDC, etc.)
        - `platformVariableFeeBps` integer, required — Variable fee in basis points (1 bps = 0.01%) to apply to the transaction's source-currency amount.
    - `privateEnabled` boolean — Whether wallet privacy is enabled for the Embedded Wallet. Only present for `EMBEDDED_WALLET` internal accounts.
    - `createdAt` string, date-time, required — Timestamp when the internal account was created
    - `updatedAt` string, date-time, required — Timestamp when the internal account was last updated

## Acknowledgement `200`

Webhook received successfully

## Other responses

- `400` — Bad request
- `401` — Unauthorized - Signature validation failed
- `409` — Conflict - Webhook has already been processed (duplicate id)

---

[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/50d71dfe03b8/schema)
