> ## Documentation Index
> Fetch the complete documentation index at: https://docs.grailpay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create a Transaction

## What is a Transaction?

A **Transaction** in the GrailPay Payments API initiates the movement of funds between two users — typically 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

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

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 [ComplianceStatusChanged](/docs/technical/webhooks/events#compliance-status-changed-event)
  webhook event to report an `approved` status. A `submitted`, `rejected`, or any `ON_HOLD_*` status does **not** satisfy
  this requirement. See [Submit Person for KYC](/docs/technical/users/manage-users#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.

<Note>
  Person to Person payments are not enabled by default. If you would like to offer this functionality, contact your
  GrailPay integration support contact to have it enabled on your account.
</Note>

<Warning>
  A Person to Person transaction will be rejected if the payee's KYC status is not `approved`, or if your account is
  not approved for Person to Person payments.

  Before creating the transaction, wait for the payee's KYC to reach an `approved` status, delivered via the
  [ComplianceStatusChanged](/docs/technical/webhooks/events#compliance-status-changed-event) webhook event. Any other
  status — including `submitted`, `rejected`, or any `ON_HOLD_*` status — does not satisfy this requirement.

  All other transaction types continue to require at least one KYB-verified Merchant, as described above.
</Warning>

***

## 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` field. How GrailPay uses this value depends on whether the
merchant receiving the funds is configured for **Batch Payouts**.

| Merchant configuration               | Where the payout is sent                                                                                            |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| **Not** configured for Batch Payouts | The destination account specified during transaction creation (`destination_bank_account`).                         |
| Configured for Batch Payouts         | The merchant's **default bank account**. The destination account specified during transaction creation is not used. |

<Note>
  This is expected system behavior. For merchants configured for Batch Payouts, payouts are **always** sent to the
  merchant's default bank account, regardless of any destination account provided at transaction creation. The
  destination account you specify is only used when the merchant is **not** configured for Batch Payouts.
</Note>

For more on how batch and direct payouts are delivered, see
[Scenarios: Direct & Batch Payouts](/docs/resources/scenarios-direct-and-batch-payouts).

To update a Merchant or Business to receive individual payouts instead of Batch Payouts, please refer to
the [Manage Users](/docs/technical/users/manage-users) page.

***

## 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.

<Warning>
  These fields are **not** truncated. If a value exceeds its maximum length, the API rejects the entire transaction
  request rather than trimming the value. Check the length of `company_name`, `description`, and `addenda` before
  submitting.

  For clean, predictable metadata, send values that are already within the character limits and avoid punctuation or
  symbols you need preserved.
</Warning>

### 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)

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.                                                                                                                             |

<Note>
  `addenda` is always stored on the transaction, but it is only transmitted on the outgoing ACH entry for CCD
  (business-to-business) entries. On PPD or WEB entries the value is retained but not sent to the bank.
</Note>

### 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. |

<Note>
  Because the payout fills in `company_name` and `description` from the payer's profile when you leave them blank, the
  credit entry is rarely empty even if you send no metadata. If you want consistent, predictable values on both legs,
  send `company_name` and `description` explicitly.
</Note>

<Note>
  **Batch Payouts only:** GrailPay offers an optional, account-level configuration — available on request — that
  overrides the `company_name` fallback order above and always sends your (the client's) name as the originator
  company name on batch payout entries. Contact your GrailPay integration support contact to enable it.
</Note>

***

## 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](/docs/technical/overview#testing) guide.

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

* [Onboard a Person](/docs/technical/users/onboard-a-person)
* [Onboard a Business](/docs/technical/users/onboard-a-business)
* [Onboard a Merchant](/docs/technical/users/onboard-a-merchant)
* [Add Bank Account](/docs/technical/bank-accounts/add-bank-account)

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

<Note>
  Most transactions require that at least one party (either the payer or payee) has successfully completed KYB
  verification — meaning one side must be a registered Merchant. The exception is Person to Person payments, which
  instead require the payee to have completed KYC verification and your account to be approved for the functionality
  (see [Person to Person Payments](#person-to-person-payments) above).
</Note>

***

## Step 1: Confirm Participants Are Onboarded

Before creating a transaction, both the **payer** and **payee** must exist in the system as valid users
(i.e. persons or businesses).

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:

* `payer_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

Each transaction must include:

* `amount` — The dollar value to be transferred
* `speed` — Indicates processing tier (e.g., `standard` or `sameday`, if available in your integration)

Optional fields include:

* `client_reference_id` — Optional reference ID from your system
* `description` — Optional metadata for reporting

All amounts must be denominated in USD and specified in cents (e.g., \$10.00 = 1000).

***

## Step 3: Submit the Transaction

To initiate the transaction, send a `POST` request to the following endpoint: `/3p/api/v1/transactions` with the required
fields.  Upon success, the API will return a `uuid` representing the newly created transaction. This can be used to
fetch status updates or cancellation requests.

### 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](https://api.grailpay.com/api/documentation#/Transactions/f96034804914c77cf08a89c767ec8be4)
for the full schema, including all required and optional fields.

***

## 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:

* `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](/docs/resources/transaction-states) documentation.

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

* **Webhook Notifications**: Set up webhooks to receive real-time [Webhook Events](/docs/technical/webhooks/events) on transaction status changes.
* **API Polling**: Use the `GET /3p/api/v2/transactions/{transaction_uuid}` endpoint to fetch the current status of a specific transaction.

<Note>
  To fully monitor the lifecycle of a funds transfer, it’s important to understand that a Transaction only represents
  the debit leg of the movement. The Payout, which delivers funds to the payee, follows its own processing lifecycle
  and status updates.

  We **strongly recommend** subscribing to both the Transaction and Payout webhook events to accurately track the complete
  flow of funds — from initiation to settlement.
</Note>

***

## Questions?

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

***

## Resources

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

* [Transaction States](/docs/resources/transaction-states)
* [ACH Return Codes](/docs/resources/return-codes)
* [Scenarios: Direct & Batch Payouts](/docs/resources/scenarios-direct-and-batch-payouts)
* [Transaction Queues](/docs/resources/transaction-queues)
