Skip to main content
Understanding the transaction lifecycle helps you build robust payment flows, handle edge cases, and provide accurate status updates to your customers.

Outgoing Transaction Flow

Your customer/platform sends funds to an external recipient.
1

Create Quote

Lock in exchange rate and fees:
Response:
  • Quote ID
  • Locked exchange rate
  • Expiration time (typically ~5 minutes or greater, depending on corridor)
2

Execute Quote

Initiate the payment:
Result:
  • Transaction created with status PENDING
  • Source account debited immediately
  • OUTGOING_PAYMENT.PENDING webhook sent
3

Processing

Grid handles:
  • Currency conversion (if applicable)
  • Routing to appropriate payment rail
  • Settlement with destination bank/wallet
Status: PROCESSING
4

Completion or Failure

Success Path:
  • Funds delivered to recipient
  • Status: COMPLETED
  • settledAt timestamp populated
  • OUTGOING_PAYMENT.COMPLETED webhook sent
Failure Path:
  • Delivery failed (invalid account, etc.)
  • Status: FAILED
  • failureReason populated
  • OUTGOING_PAYMENT.FAILED webhook sent
  • Refund initiated automatically — track via the refund object and OUTGOING_PAYMENT.REFUND_* webhooks
Most transactions on Grid are completed in seconds.

Same-Currency Transfers

For same-currency transfers without quotes:

Transfer-Out (Internal → External)

Response:
Follows same lifecycle as quote-based outgoing transactions.

Transfer-In (External → Internal)

Only works for “pullable” external accounts (e.g., debit cards).

Outgoing Payment Status

A single status field represents whether the transaction reached its destination:
EXPIRED and FAILED are terminal states, but COMPLETED is not always final — a bank can return a payment after it was marked COMPLETED, moving it to FAILED. Always continue processing webhook events for transactions even after they reach COMPLETED.

State Diagram

Refund Object

When a payment fails or is cancelled, refunds are tracked in a dedicated object on the transaction, decoupled from the payment status:

Refund destination

Where a refund lands depends on how the transaction was funded:
  • Prefunded (internal account) — the amount is credited back to the source internal account balance.
  • Real-time (JIT) funding via an instant fiat rail (RTP, PIX, SEPA Instant, etc.) — the refund is returned to the originating funding instrument.
  • Real-time (JIT) funding via crypto (for example USDC or BTC) — the refunded amount is credited to the customer’s internal account balance for that asset. It is not returned to the wallet the funds were sent from.
Crypto deposits are not refunded to the source wallet because Grid cannot verify that the sending wallet belongs to your customer — the funds may have originated from an exchange or another third-party address. The credited internal balance is reusable: spend it with a new quote, or withdraw it to an external wallet with POST /transfer-out.

Webhooks

Outgoing payment webhooks use the format OUTGOING_PAYMENT.<STATUS>. The webhook request body contains the full transaction resource.

Event Types

Example Payloads

Handling Webhooks

Scenarios

The standard successful payment flow:
  1. OUTGOING_PAYMENT.PENDING
  2. OUTGOING_PAYMENT.PROCESSING
  3. OUTGOING_PAYMENT.COMPLETED

Listing Transactions

Query all transactions for a customer or date range:
Response:
Use for reconciliation and reporting.

Failure Handling

Common Failure Reasons

When a transaction fails, a refund is initiated automatically. Track the refund via the refund object on the transaction and OUTGOING_PAYMENT.REFUND_* webhook events. See Refund Object above.

Best Practices

Save transaction IDs to your database:
Use the Idempotency-Key HTTP header for safe retries:
Translate technical statuses to user-friendly messages: