Skip to content
Select theme

Create a Transaction

A Transaction in the GrailPay Payments API initiates the movement of funds between two parties — a payer ( sender ) and a payee ( recipient ) — via the ACH network. It represents the debit leg of the transfer, capturing the withdrawal of funds from the payer’s bank account. Once processed, the transaction will result in a corresponding Payout, which reflects the credit leg — the delivery of funds to the payee. Each transaction is uniquely identified by a uuid and includes metadata such as the amount, participants, and processing status.

Transactions can represent:

  • Merchant to Merchant payments
  • Merchant to Business or Business to Merchant payments
  • Merchant to Person disbursements
  • Person to Merchant collections
  • Person to Person payments

Once created, the transaction enters a processing pipeline that will debit the payer’s bank account and credit the payee’s bank account, subject to ACH network rules and timing.


Creating a transaction involves initiating a fund transfer between two parties — a payer (sender) and a payee (recipient). Both parties must be onboarded and must have valid, connected bank accounts within the GrailPay system.

When a transaction is successfully created, the API returns a unique uuid that can be used to track its status or retrieve its details later.

This guide outlines the required fields, entity prerequisites, and common validation scenarios encountered when initiating a transaction.


GrailPay supports payments directly between two people, allowing funds to move from one individual to another without a registered Merchant on either side of the transaction.

Please note that fulfilling the compliance obligations applicable to ACH operates differently for Person to Person payments than payments with Merchants in our system.

To create a Person to Person transaction, both of the following must be true:

  • The payee’s KYC status is approved. The individual receiving funds must have successfully passed Know Your Customer (KYC) identity verification and reached the approved status before you create the transaction. Submitting a person for KYC does not immediately approve them — wait for the compliance_status.approved webhook event. A submitted, rejected, or any ON_HOLD_* status does not satisfy this requirement. See Submit Person for KYC to initiate verification for a person.
  • Your account is approved for Person to Person payments. This functionality must be explicitly enabled on your integration by GrailPay.

When creating a transaction, you can optionally specify a destination account — the payee’s bank account that will receive the payout — using the destination_bank_account_uuid field. Omit the key to use the payee’s default connected account; do not send null. The payer side works the same way: source_bank_account_uuid selects the account to debit, and omitting it uses the payer’s default connected account. How GrailPay uses the destination value depends on whether the merchant receiving the funds is configured for Batch Payouts, that is, whether its payout_type is batch.

Merchant configurationWhere the payout is sent
Not configured for Batch Payouts (payout_type is individual)The destination account specified during transaction creation (destination_bank_account_uuid).
Configured for Batch Payouts (payout_type is batch)The merchant’s default bank account. The destination account specified during transaction creation is not used.

For more on how batch and direct payouts are delivered, see Scenarios: Direct & Batch Payouts.

To update a Merchant or Business to receive individual payouts instead of Batch Payouts (its payout_type), please refer to the Manage Users page.


When creating a transaction, you can optionally include metadata fields that describe the transfer. These values are passed through to the ACH entries and appear on bank statements and in ACH records, helping both the payer and payee recognize the purpose of the payment.

FieldMax LengthDescription
company_name16 charactersThe originator (company) name displayed on the ACH entry and bank statement. Auto-populated when omitted — see the rules below.
description10 charactersA short descriptor of the transfer’s purpose included on the ACH entry.
addenda80 charactersSupplemental free-form information attached to the ACH entry. Only transmitted on CCD (business-to-business) entries.

All three fields are optional. Any value you send is sanitized before it is used:

  • Only letters, numbers, and spaces are kept — any other characters are removed.
  • Consecutive spaces are collapsed into a single space.

Every transfer moves money in two legs, and metadata is applied independently to each:

  • Capture — the debit that pulls funds from the payer’s bank account. Uses the values you send at creation.
  • Payout — the credit that delivers funds to the payee’s bank account. Derives its own metadata later, drawing on the stored transaction values and the payer’s profile.

Because the two legs are computed separately, they can display different values, and leaving a field blank at creation does not mean it will be empty on the payout.

At creation, the values you provide are applied to the capture ACH entry:

FieldWhen you provide a valueWhen you omit it
company_nameUsed as sent, after sanitization.Auto-generated from the payee: the payee’s business/merchant name, otherwise the payee’s first and last name, otherwise left empty.
descriptionUsed as sent, after sanitization.Left empty on the capture (no fallback at this stage).
addendaStored as sent, after sanitization.Left empty.

When the transaction reaches payout, metadata for the credit ACH entry is recalculated — it does not simply copy the capture values. Each field falls through the following order until a usable value is found. Because these payout values are derived by GrailPay rather than submitted in your request, they are sanitized and trimmed to fit each field’s limit:

FieldFallback order (first match wins)
company_name1) the transaction’s company_name → 2) the payer’s business/merchant name → 3) the payer’s name → 4) GrailPay (default)
description1) the transaction’s description → 2) the payer’s business/merchant name → 3) the payer’s name → 4) empty
addendaIncluded only when the payout is sent as CCD (business-to-business), using the transaction’s addenda. Omitted (null) for PPD and WEB payouts.

To test transactions in GrailPay’s sandbox environment, you’ll need two entities:

  • One with a connected bank account to act as the payer
  • One with a connected bank account to act as the payee

For more information on creating accounts in our sandbox environment, see the Technical Overview guide.

You can provide these details when creating test users via the following endpoints:

This setup allows you to perform end-to-end transaction testing — including creation, settlement, and simulated failure — without using real financial data.


Step 1: Confirm Participants Are Onboarded

Section titled “Step 1: Confirm Participants Are Onboarded”

Before creating a transaction, both the payer and payee must exist in the system as valid entities under your vendor — a person, a business, or a merchant. You reference each by the UUID you were given when it was onboarded; there is no separate user UUID to look up.

Each must meet the following criteria:

  • Successfully onboarded using the appropriate flow
  • Possess a valid uuid
  • Have an active, connected bank account (manual or Plaid-linked)

You will reference these participants using:

  • payor_uuid — the sender of funds
  • payee_uuid — the recipient of funds

If either party is missing or has an invalid account, the transaction will be rejected.


Step 2: Determine Transaction Type and Amount

Section titled “Step 2: Determine Transaction Type and Amount”

Each transaction must include:

  • payor_uuid and payee_uuid — The two participants, as described in Step 1
  • amount — The value to transfer, in cents

Optional fields include:

  • transaction_fee — A fee in cents, which must not exceed amount
  • client_reference_id — A reference ID from your system
  • company_name, description, and addenda — ACH metadata, as described under Transaction Metadata
  • source_bank_account_uuid and destination_bank_account_uuid — The accounts to debit and credit, as described under Destination Account & Batch Payouts
  • modality — The rail and speed of each leg. modality.transaction covers the debit and is ACH only, with a speed of standard or sameday. modality.payout covers the credit: payment_rail is ach or fednow where FedNow is enabled for your account, and speed is standard, sameday, or instant, with instant valid only on fednow. When modality.payout is omitted, GrailPay resolves a default from your vendor and the payee’s configuration. It is rejected when your account uses processor batch payouts.

All amounts must be denominated in USD and specified in cents (e.g., $10.00 = 1000). The platform minimum is 10 cents, and a higher minimum may apply if one is configured for your account.


To initiate the transaction, send a POST request to /api/v3/transactions with the required fields. Include an Idempotency-Key header so that a retried request cannot create a second transaction; a duplicate is answered with 409. Upon success, the API returns 201 with the new transaction, including the uuid that identifies it from here on and an initial status of QUEUED. The uuid is what you use to fetch status updates, pause or resume the transaction, or cancel it.

When creating a new transaction, certain fields are subject to strict character limits. These constraints are imposed by the ACH network and our banking partners to ensure compatibility with downstream systems:

FieldCharacter Limit
company_name16 characters
description10 characters
addenda80 characters

Make sure your values do not exceed these limits, or the transaction may be rejected during processing.

See the Create Transaction OpenAPI documentation for the full schema, including all required and optional fields.


Once submitted, a transaction may move through multiple states depending on processing speed, ACH timing, and risk evaluation.

Possible states include:

  • QUEUED
  • CAPTURE_PENDING
  • CAPTURE_ACH_PENDING
  • CAPTURE_ACH_FAILED
  • CANCELED
  • IN_PAYOUT

To see a full list of states and their definitions, refer to the Transaction States documentation.

To monitor the state of a transaction, you can use one of the following methods:

  • Webhook Notifications: Register a webhook to receive the Transaction events — transaction.processing, transaction.completed, transaction.failed, and the rest — as the status changes. See Webhook Events for the envelope every event shares.
  • API Polling: Use the GET /api/v3/transactions/{uuid} endpoint to fetch the current state of a specific transaction, along with its payout, refunds, and clawback.

If you’re encountering any issues, contact your GrailPay integration support contact or open a support request via the portal.


Below you will find some helpful resources to assist with understanding how transactions work in GrailPay.

Maintained by EkLine