Overview

Webhooks allow your application to react in real-time to important events across the GrailPay platform—without the need to constantly poll the API. Whenever a subscribed event occurs (like a payout being sent or a transaction status changing), GrailPay sends a secure HTTP POST request directly to your server with the event details. This push-based architecture enables you to automate workflows, synchronize data, and trigger time-sensitive actions the moment something happens. Each webhook is sent to a configured HTTPS endpoint, and your server is expected to return an HTTP 200 OK response to confirm receipt. Webhooks may be sent to both vendors and processors, and the payloads are tailored to each recipient’s role and financing type (e.g., credit, debit, or alternate flows) to ensure accurate processing and traceability.

Authenticating Webhooks

To verify that a webhook really came from GrailPay and not a malicious actor, every webhook request includes a special signature header: X-Caller-Auth. This header contains a SHA-256 hash of your API key, and it should be validated in your server-side code to ensure the authenticity of the request. We strongly recommend implementing this verification step. It helps protect your application from spoofed requests and ensures that only genuine GrailPay events are processed.

Security

GrailPay requires all webhook endpoints to use HTTPS to guarantee the secure delivery of sensitive financial event data. This applies across both sandbox and production environments—non-secure HTTP URLs will be rejected, and no webhook events will be delivered until a valid HTTPS endpoint is configured. Requiring HTTPS helps protect against man-in-the-middle attacks and ensures compliance with industry-standard security practices. Before subscribing to webhook events, make sure your server is accessible via a secure, publicly reachable HTTPS URL with a valid SSL certificate. If your environment isn’t properly configured, webhook notifications will silently fail to deliver.

Response & Retry Logic

To acknowledge receipt of a webhook event, your server must respond with an HTTP 200 OK status code. This tells GrailPay that the event was received and processed successfully. If a 200 OK response is not returned, we consider the delivery attempt a failure. In such cases, GrailPay will automatically retry sending the webhook at increasing intervals for a limited number of attempts. Repeated failures may result in delayed event delivery or eventual webhook deactivation. To ensure reliable communication, your webhook handler should be:
  • Idempotent – able to handle duplicate event deliveries without side effects.
  • Efficient – respond quickly, even if additional processing is handled asynchronously.
Properly handling responses and retries ensures smooth, real-time integration with your systems.

Available Webhook Events

Our webhooks are not specific to any particular entity in our ACH Application. So for example, you would not want to register an individual webhook for every merchant that you onboard. Each of those webhooks urls will get the same data each time an event is triggered. The approach we recommend is to register a single webhook url to the events you wish to subscribe to. Then you can use the event data to determine which entity the event is related to.

Bank Account Events

Bank accounts are foundational to ACH transactions within the GrailPay platform, serving as the endpoints for debits and credits between payors and payees. Whether added through direct input, or our Bank Link SDK, these accounts must be tracked and maintained throughout their lifecycle. GrailPay provides webhook events that notify you when a bank account has been successfully linked, failed to link, or has been deleted. These events allow your system to react to key account changes in real time—helping to keep records accurate and ensuring smooth payment processing. By subscribing to bank account-related webhooks, your integration gains full visibility into the account lifecycle. For example, a failed bank link may prompt you to notify a user, while a successful link may trigger onboarding flows or transaction enablement. These webhooks are essential for keeping your application responsive, user-friendly, and compliant with modern financial workflows.

Bank Account Removed Event

This webhook event is triggered whenever a bank account is deleted from the GrailPay system. It allows your integration to stay in sync with the current state of user-linked financial accounts, ensuring that your records remain accurate and up-to-date. When this event occurs, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BankAccountRemoved",
    "account_uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "user_uuid": "ce334276-3a2e-4db6-8e67-600ed1fcd397",
    "aggregator_type": "bank_link",
    "account_number": "45287159",    
    "provider_name": "chase",
    "routing_number": "011401533"
}
This webhook event is triggered whenever a bank account fails to link successfully using GrailPay’s Bank Link SDK. This allows your application to track and respond to failed bank connection attempts—whether due to user cancellation, timeouts, or external provider errors. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BankLinkFailed",
    "user_uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
  	"aggregator_type": "bank_link",
    "vendor_id": "123456",
    "failed_reason": ".....",
    "source": "api",
    "ui_notified": true|false
}

Bank Linked Successfully Event

This event is triggered when a bank account is successfully linked using GrailPay’s Bank Link SDK. flow. It confirms that the user has completed the linking process and the account is now available for transactions or balance checks. You can use this event to update your internal records, unlock funding workflows, or display confirmation messages to the user. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BankLinkedSuccessfully",
    "account_uuid": "becdf333-53cc-4db1-a6bd-a01b1ba9585c",
    "user_uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "aggregator_type": "bank_link",
    "source": "api",
    "account_id": "acc_9Dw8QmdZtcXrEMDuZWLyfi",
    "account_number": "45287159",
    "routing_number": "011401533",
    "provider_name": "chase",
    "vendor_id": "12345",
    "ui_notified": true|false
}

Batch Payout Events

Batch payouts are a key mechanism in the GrailPay ACH platform, allowing multiple transactions to be grouped together and disbursed to a single entity’s linked bank account in one consolidated action. This not only streamlines the movement of funds but also simplifies reconciliation and reporting for partners managing high transaction volumes. GrailPay emits batch payout webhook events for four entity types: Business, Merchant, Person, and Processor. These events provide visibility into when a payout batch is created and initiated, enabling partners to track disbursement activity and trigger downstream processes like ledger updates or partner notifications. Each event includes a structured payload specific to the entity type, which is outlined in the sections below.

Batch Payout Business Event

When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BatchPayoutBusiness",
    "uuid": "9bd53fe1-ac74-4e81-b6f2-be88b7c86a68",
    "amount": 10100,
    "created_at": "2024-04-18 01:00:20",
    "updated_at": "2024-04-18 01:00:20"
}

Batch Payout Merchant Event

When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BatchPayoutMerchant",
    "uuid": "9bd53fe1-ac74-4e81-b6f2-be88b7c86a68",
    "amount": 10100,
    "created_at": "2024-04-18 01:00:20",
    "updated_at": "2024-04-18 01:00:20"
}

Batch Payout Person Event

When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BatchPayoutPerson",
    "uuid": "9bd53fe1-ac74-4e81-b6f2-be88b7c86a68",
    "amount": 10100,
    "created_at": "2024-04-18 01:00:20",
    "updated_at": "2024-04-18 01:00:20"
}

Batch Payout Processor Event

When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BatchPayout",
    "uuid": "9bd53fe1-ac74-4e81-b6f2-be88b7c86a68",
    "amount": 10100,
    "created_at": "2024-04-18 01:00:20",
    "updated_at": "2024-04-18 01:00:20"
}

Batch Refund Event

This webhook event is triggered when a debit ACH is initiated from the processor’s bank account to fund a batch of refunds. It signifies that GrailPay has begun collecting funds to fulfill refund requests that were previously grouped and approved for processing. This event is typically used in integrations where the processor, rather than the original payee, is responsible for funding the refund payouts. It ensures visibility into the moment refund funding is initiated, allowing for downstream reconciliation or tracking. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BatchRefund",
    "uuid": "9bd53fe1-ac74-4e81-b6f2-be88b7c86a68",
    "amount": 10100,
    "created_at": "2024-04-18 01:00:20",
    "updated_at": "2024-04-18 01:00:20"
}

Business & Merchant Events

GrailPay emits webhook events when key lifecycle changes occur for business or merchant entities within the platform. These events notify you in real time when a business or merchant is created or updated, allowing you to synchronize entity data across your systems, trigger onboarding workflows, or audit compliance checkpoints as part of your ACH integration. Because merchants are a specialized type of business entity that has completed Know Your Business (KYB) verification, some events—such as BusinessCreated—may be emitted for both businesses and merchants, while others—like BusinessUpdated—are specific to merchant entities only. Each webhook payload includes metadata and identifiers that allow you to distinguish between general business entities and merchants, giving your platform the flexibility to track, audit, and respond to entity updates appropriately.

Business Created Event

This webhook is triggered whenever a new Business or Merchant entity is successfully created within the GrailPay system.
This event applies to both businesses and merchants, as both entity types follow the same creation and onboarding flow within the ACH API.
When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BusinessCreated",
    "uuid": "401c79dd-d38c-4c3a-8edf-1afac5914d2d",
    "first_name": "Jack",
    "last_name": "Jones",
    "name": "Jack Inc.",
    "tin": "961862955",
    "user_status": "Approved|On Hold|Rejected",
    "kyb_status": "Approved|In Review|Failed|null",
    "email": "[email protected]",
    "phone": "2541234567",                    
    "address": {
        "street_address": "20 Elmora Ave",
        "additional_address": "",
        "city": "Elizabeth",
        "state": "NJ",
        "country": "US",
        "zip": "07202"
    },
    "business_owners": [],
    "financing_credit_balance": null,
    "source": "api",
    "created_at": "2023-06-10 14:15:54",
    "updated_at": "2023-06-10 14:15:54"
}

Business Updated Event

This webhook is triggered whenever a Merchant entity is updated within the GrailPay system. Updates may include changes to KYB information, business name, address, or other identifying details.
This event currently only fires when updating the merchant record based on the results of running KYB checks.
When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "BusinessUpdated",
    "uuid": "401c79dd-d38c-4c3a-8edf-1afac5914d2d",
    "first_name": "Jack",
    "last_name": "Jones",
    "name": "Jack Inc.",
    "tin": "961862955",
    "user_status": "Approved|On Hold|Rejected",
    "kyb_status": "Approved|In Review|Failed|null",
    "kyb_rejected_reason": "Reason for KYB rejection ( ie. Cannot match TIN )",
    "email": "[email protected]",
    "phone": "2541234567",                    
    "address": {
        "street_address": "20 Elmora Ave",
        "additional_address": "",
        "city": "Elizabeth",
        "state": "NJ",
        "country": "US",
        "zip": "07202"
    },
    "business_owners": [],
    "financing_credit_balance": null,
    "source": "api",
    "created_at": "2023-06-10 14:15:54",
    "updated_at": "2023-06-10 14:15:54"
}

Clawback Events

Clawbacks occur when a transaction that has already been disbursed to the payee fails—often due to insufficient funds, a return from the receiving bank, or a rejection by the ACH network. In such cases, GrailPay initiates a payout return to recover the funds, which is referred to as a clawback. These events are crucial for maintaining the integrity of your payment workflows, ensuring that failed disbursements are properly tracked and reconciled. GrailPay emits a series of webhook events throughout the clawback lifecycle to notify you when a return has been initiated (ClawbackStarted), fails to complete (ClawbackFailed), or finishes successfully (ClawbackCompleted). By subscribing to these events, you can monitor failed transactions in real time, update internal records, trigger customer notifications, or pause related operations until resolution.

Clawback Completed Event

This webhook is triggered when a payout return (clawback) has been initiated by GrailPay as part of a completed refund or recovery process.
This event confirms that GrailPay has initiated the return of funds. It does not guarantee that the receiving bank has successfully delivered the funds.
When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "ClawbackCompleted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "CLAWBACK_COMPLETE",
    "capture_status": "CAPTURE_ACH_FAILED",
    "payout_status": "PAYOUT_COMPLETE",
    "clawback_status": "CLAWBACK_COMPLETE",
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "failure_reason": "Insufficient funds",
    "failure_code": "R01",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Clawback Failed Event

This webhook is triggered when a payout return (clawback) attempt fails within the GrailPay system.
A failed clawback typically indicates that the funds could not be withdrawn from the recipient’s bank account due to reasons such as insufficient funds or a closed account.
When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "ClawbackFailed",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "CLAWBACK_ACH_FAILED",
    "capture_status": "CAPTURE_ACH_FAILED",
    "payout_status": "PAYOUT_COMPLETE",
    "clawback_status": "CLAWBACK_ACH_FAILED",
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "failure_reason": "Insufficient funds",
    "failure_code": "R01",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Clawback Started Event

This webhook is triggered when a payout return (clawback) has been initiated by the GrailPay system. A clawback is required when a transaction fails (e.g., due to an ACH return) after the payout (credit) has already been disbursed to the recipient. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "ClawbackStarted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "CLAWBACK_ACH_PENDING",
    "capture_status": "CAPTURE_ACH_FAILED",
    "payout_status": "PAYOUT_COMPLETE",
    "clawback_status": "CLAWBACK_ACH_PENDING",
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "failure_reason": "Insufficient funds",
    "failure_code": "R01",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Payout Events

Payout events reflect the final stage in GrailPay’s transaction lifecycle, where funds are disbursed from the platform to a payee’s linked bank account. These events are essential for tracking when money has been successfully moved out of the system—or when something has gone wrong. Whether you’re monitoring cash flow, updating transaction statuses, or reconciling financial data, payout events provide the real-time signals you need. GrailPay emits webhook events for each critical state in a payout’s lifecycle: when a payout is initiated (PayoutPending), fails (PayoutFailed), or completes (PayoutCompleted). These events help ensure transparency and operational continuity across your systems. They allow your application to respond dynamically—such as notifying users, retrying failed disbursements, or logging final confirmations for reporting and audit purposes.

Payout Completed Event

This webhook is triggered each time a payout (transfer of funds to the payee) has been completed.
Please note that this event indicates the payout has been initiated by GrailPay. It does not confirm final delivery of funds by the receiving bank.
When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "PayoutCompleted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "PAYOUT_COMPLETE",
    "capture_status": "CAPTURE_COMPLETE",
    "payout_status": "PAYOUT_COMPLETE",
    "reverse_payout_status": null,
    "clawback_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Payout Failed Event

This webhook is triggered when a payout—the transfer of funds to the payee’s bank account—fails. This may occur for several reasons, such as invalid account details, routing issues, or problems reported by the receiving financial institution. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "PayoutFailed",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "PAYOUT_ACH_FAILED",
    "capture_status": "CAPTURE_COMPLETE",
    "payout_status": "PAYOUT_ACH_FAILED",
    "clawback_status": null,
    "reverse_payout_status": "REVERSE_PAYOUT_PENDING",
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Refund Events

Refund events are triggered throughout the lifecycle of a refund transaction—starting from the moment a refund is created, through the capture of funds from the payee or processor, and concluding with the delivery of funds back to the original payer. These events help ensure your platform can track, audit, and respond to refunds in real time. GrailPay emits webhook events for each key milestone in the refund process: when a refund is initiated (RefundPending), when the corresponding debit ACH is started, completed, or fails (RefundCaptureStarted, RefundCaptureCompleted, RefundCaptureFailed), and when the outbound credit to the payer is initiated, completed, or fails (RefundPayoutPending, RefundPayoutCompleted, RefundPayoutFailed). Together, these events provide a complete picture of refund flow—enabling you to keep users informed, automate reconciliation, and ensure accurate financial reporting.

Refund Capture Completed Event

This webhook is triggered when a debit ACH transaction has been successfully completed from either the payee’s or processor’s bank account to fund a refund. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "RefundCaptureCompleted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "transaction_uuid": "7049f46f-8502-402e-952b-b29ad5ec8a55",
    "amount": 12000,
    "status": "REFUND_ACH_PENDING",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "client_reference_id": "",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Refund Capture Failed Event

This webhook is triggered when a debit ACH fails while attempting to collect funds for a refund from either the payee’s or processor’s bank account. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "RefundCaptureFailed",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "transaction_uuid": "7049f46f-8502-402e-952b-b29ad5ec8a55",
    "amount": 12000,
    "status": "REFUND_FAILED",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "client_reference_id": "",
    "failure_reason": "Account closed",
    "failure_code": "R02",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Refund Capture Started Event

This webhook is triggered each time a refund request has been initiated and a debit ACH has been created from either the payee’s or processor’s bank account.
  • For individual payouts, a debit ACH is created for each refund request from the payee or processor.
  • For batch payouts, a single debit ACH is created from the processor’s account to cover all refund requests for the day.
  • In both cases, this webhook will be triggered for each individual refund request.
When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "RefundCaptureStarted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "transaction_uuid": "7049f46f-8502-402e-952b-b29ad5ec8a55",
    "amount": 12000,
    "status": "REFUND_CAPTURE_ACH_PENDING",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "client_reference_id": "",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Refund Payout Completed Event

This webhook is triggered each time a refund has been completed and the funds have been sent to the payer’s bank account. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "RefundPayoutCompleted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "transaction_uuid": "7049f46f-8502-402e-952b-b29ad5ec8a55",
    "amount": 12000,
    "status": "REFUND_COMPLETE",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "client_reference_id": "",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Refund Payout Failed Event

This webhook is triggered when a credit ACH transfer to the payer’s bank account has failed during the refund process. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "RefundPayoutFailed",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "transaction_uuid": "7049f46f-8502-402e-952b-b29ad5ec8a55",
    "amount": 12000,
    "status": "REFUND_FAILED",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "client_reference_id": "",
    "failure_reason": "Account closed",
    "failure_code": "R02",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Refund Payout Pending Event

This webhook is triggered when a credit ACH transfer has been initiated to the payer’s bank account as part of a refund. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "RefundPayoutPending",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "transaction_uuid": "7049f46f-8502-402e-952b-b29ad5ec8a55",
    "amount": 12000,
    "status": "REFUND_ACH_PENDING",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "client_reference_id": "",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Refund Pending Event

This webhook is triggered when a refund request is first created in the system. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "RefundPending",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "transaction_uuid": "7049f46f-8502-402e-952b-b29ad5ec8a55",
    "amount": 12000,
    "status": "REFUND_PENDING",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "client_reference_id": "",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Reverse Payout Events

Reverse payout events are emitted when GrailPay must return funds to the original payer because a payout to the intended payee could not be completed. This can happen due to reasons like an invalid or closed bank account, or a failed delivery attempt after the payout was initiated. These events help your platform stay aligned with the refund and reconciliation flow for failed disbursements. GrailPay provides webhook events for when a reverse payout is initiated (ReversePayoutStarted), successfully completed (ReversePayoutCompleted), or fails during processing (ReversePayoutFailed). These allow you to track the full lifecycle of the reversal process, update transaction statuses, and notify relevant users or systems of the outcome.

Reverse Payout Completed Event

This webhook is triggered when a reverse payout has been successfully completed. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "ReversePayoutCompleted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "PAYOUT_ACH_FAILED",
    "capture_status": "CAPTURE_COMPLETE",
    "payout_status": "PAYOUT_ACH_FAILED",
    "clawback_status": null,
    "reverse_payout_status": "REVERSE_PAYOUT_COMPLETE",
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Reverse Payout Failed Event

This webhook is triggered when a reverse payout attempt fails due to an error or issue during processing. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "ReversePayoutFailed",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "PAYOUT_ACH_FAILED",
    "capture_status": "CAPTURE_COMPLETE",
    "payout_status": "PAYOUT_ACH_FAILED",
    "clawback_status": null,
    "reverse_payout_status": "REVERSE_PAYOUT_FAILED",
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Reverse Payout Started Event

This webhook is triggered when a reverse payout has been successfully initiated and is in the process of being completed. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "ReversePayoutStarted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "PAYOUT_ACH_FAILED",
    "capture_status": "CAPTURE_COMPLETE",
    "payout_status": "PAYOUT_ACH_FAILED",
    "clawback_status": null,
    "reverse_payout_status": "REVERSE_PAYOUT_ACH_PENDING",
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Transaction Events

Transaction events provide visibility into the full lifecycle of the debit side of a payment—when funds are pulled from the payer’s bank account. These events allow your platform to monitor the status of ACH debits as they move through creation, processing, completion, or failure. Each webhook corresponds to a specific stage of the transaction journey, from initial creation (TransactionStarted) to settlement (TransactionCompleted), including events for cancellation, failure, and capture. By subscribing to these events, you can build real-time audit trails, trigger status updates, and automate downstream actions tied to the movement of funds from the payer.

Transaction Capture Started Event

This webhook is triggered when an ACH debit has been successfully initiated as part of a transaction. It indicates that the funds capture process has begun from the payor’s bank account. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following
{
    "event": "TransactionCaptureStarted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "CAPTURE_ACH_PENDING",
    "capture_status": "CAPTURE_ACH_PENDING",
    "payout_status": null,
    "clawback_status": null,
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Transaction Canceled Event

This webhook is triggered whenever a transaction is canceled before it is processed. It confirms that no funds will be captured or disbursed for the canceled transaction. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "TransactionCanceled",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "CANCELED",
    "capture_status": "CANCELED",
    "payout_status": null,
    "clawback_status": null,
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "cancel_reason": null,
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Transaction Completed Event

This webhook is triggered when a transaction has been successfully completed—meaning the ACH debit from the payor and the ACH credit to the payee have both been processed. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "TransactionCompleted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "PAYOUT_PENDING_ACH",
    "capture_status": "CAPTURE_COMPLETE",
    "payout_status": null,
    "clawback_status": null,
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Transaction Failed Event

This webhook is triggered when a transaction fails at any stage of processing—whether due to account issues, validation errors, or ACH return codes. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
If for some reason the payment cannot be successfully processed the error details will be sent in the payload through a variable called ach_return_code along with the corresponding R code in ‘ach_return_code’. For a list of ACH return codes see our Return Codes documentation.
{
    "event": "TransactionFailed",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "CAPTURE_ACH_FAILED",
    "capture_status": "CAPTURE_ACH_FAILED",
    "payout_status": null,
    "clawback_status": null,
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "failed_reason": "Insufficient funds",
    "ach_return_code": "R01",
    "failure_reason": "Insufficient funds",
    "failure_code": "R01",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Transaction Started Event

This webhook is triggered when a transaction has been successfully created in the GrailPay system but ACH processing has not yet begun. It marks the initial step in the transaction lifecycle. When this event is triggered, GrailPay sends a webhook payload to your configured URL with the following structure:
{
    "event": "TransactionStarted",
    "uuid": "b5c337d8-d886-11ed-afa1-0242ac120002",
    "payer_uuid": "aae3664b-db18-428c-9a2f-a876f259a7c3",
    "payee_uuid": "54f964d4-7ade-4cd1-a278-4f21cad18a2b",
    "status": "CAPTURE_PENDING",
    "capture_status": "CAPTURE_PENDING",
    "payout_status": null,
    "clawback_status": null,
    "reverse_payout_status": null,
    "currency": "USD",
    "amount": 12000,
    "transaction_fee": 300,
    "client_reference_id": "",
    "payout_delay_days": 2,
    "type": "api",
    "created_at": "2023-04-11 14:25:26",
    "updated_at": "2023-04-11 18:25:26"
}

Testing

At this time, GrailPay does not support direct simulation of webhook events in the Sandbox environment. However, you can test your webhook integration by registering a webhook URL in Sandbox and performing actions that naturally trigger webhook events. This approach allows you to validate that your endpoint receives and processes real webhook payloads as expected. For more details on testing in Sandbox, refer to our Technical Overview guide.

Questions?

If you’re encountering any issues, please reach out to [email protected].