Create a Transaction
What is a Transaction?
Section titled “What is 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.
Overview
Section titled “Overview”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.
Person to Person Payments
Section titled “Person to Person Payments”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 theapprovedstatus before you create the transaction. Submitting a person for KYC does not immediately approve them — wait for thecompliance_status.approvedwebhook event. Asubmitted,rejected, or anyON_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.
Destination Account & Batch Payouts
Section titled “Destination Account & Batch Payouts”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 configuration | Where 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.
Transaction Metadata
Section titled “Transaction Metadata”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.
| Field | Max Length | Description |
|---|---|---|
company_name | 16 characters | The originator (company) name displayed on the ACH entry and bank statement. Auto-populated when omitted — see the rules below. |
description | 10 characters | A short descriptor of the transfer’s purpose included on the ACH entry. |
addenda | 80 characters | Supplemental 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.
Capture vs. Payout Metadata
Section titled “Capture vs. Payout Metadata”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.
Capture metadata (debit leg)
Section titled “Capture metadata (debit leg)”At creation, the values you provide are applied to the capture ACH entry:
| Field | When you provide a value | When you omit it |
|---|---|---|
company_name | Used 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. |
description | Used as sent, after sanitization. | Left empty on the capture (no fallback at this stage). |
addenda | Stored as sent, after sanitization. | Left empty. |
Payout metadata (credit leg)
Section titled “Payout metadata (credit leg)”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:
| Field | Fallback order (first match wins) |
|---|---|
company_name | 1) the transaction’s company_name → 2) the payer’s business/merchant name → 3) the payer’s name → 4) GrailPay (default) |
description | 1) the transaction’s description → 2) the payer’s business/merchant name → 3) the payer’s name → 4) empty |
addenda | Included only when the payout is sent as CCD (business-to-business), using the transaction’s addenda. Omitted (null) for PPD and WEB payouts. |
Testing
Section titled “Testing”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 fundspayee_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_uuidandpayee_uuid— The two participants, as described in Step 1amount— The value to transfer, in cents
Optional fields include:
transaction_fee— A fee in cents, which must not exceedamountclient_reference_id— A reference ID from your systemcompany_name,description, andaddenda— ACH metadata, as described under Transaction Metadatasource_bank_account_uuidanddestination_bank_account_uuid— The accounts to debit and credit, as described under Destination Account & Batch Payoutsmodality— The rail and speed of each leg.modality.transactioncovers the debit and is ACH only, with aspeedofstandardorsameday.modality.payoutcovers the credit:payment_railisachorfednowwhere FedNow is enabled for your account, andspeedisstandard,sameday, orinstant, withinstantvalid only onfednow. Whenmodality.payoutis 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.
Step 3: Submit the Transaction
Section titled “Step 3: Submit the Transaction”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.
Character Limits
Section titled “Character Limits”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:
| Field | Character Limit |
|---|---|
company_name | 16 characters |
description | 10 characters |
addenda | 80 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.
Step 4: Monitor the Transaction Status
Section titled “Step 4: Monitor the Transaction Status”Once submitted, a transaction may move through multiple states depending on processing speed, ACH timing, and risk evaluation.
Possible states include:
QUEUEDCAPTURE_PENDINGCAPTURE_ACH_PENDINGCAPTURE_ACH_FAILEDCANCELEDIN_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.
Questions?
Section titled “Questions?”If you’re encountering any issues, contact your GrailPay integration support contact or open a support request via the portal.
Resources
Section titled “Resources”Below you will find some helpful resources to assist with understanding how transactions work in GrailPay.
Maintained by EkLine