Skip to content
Select theme

Payments API Changelog

When a FedNow payout fails and the money is sent again as a Fast ACH payout, the two payouts are now linked. A new failover object on the payout shows the link in both directions, and the payout-failed webhook is now sent after the replacement has been created, so it already carries it.

An integrator that receives a payout-failed event for a FedNow payout can now find the replacement payout from the event itself, and from the replacement can get back to the original, instead of matching the two by payee and amount. Payouts created before this release are not backfilled, so failover is null on them.

  • failover.superseded_by on the failed payout holds the replacement payout’s UUID; failover.supersedes on the replacement holds the failed payout’s UUID; failover is null when there is no link
  • failover appears in the v3 payout list and fetch responses, v3 payout webhooks, and the legacy payout and transaction webhooks
  • The payout-failed webhook for a FedNow payout is sent after the Fast ACH replacement is created, so it includes the link
  • Older payouts are not backfilled

A person can now be deleted on v3 with DELETE /api/v3/people/{uuid}. The person and their connected bank accounts are marked as scheduled for deletion, and are soft-deleted after 70 days provided there has been no recent activity on their bank accounts.

Partners migrating off the deprecated v1 and v2 delete-user endpoints now have a v3 equivalent. Deletion is deliberately not immediate: the request is accepted with 202, the person is left out of list responses and can no longer transact or be refunded while scheduled, and the removal happens only once the waiting period has passed with no activity, so a person with a return still possible is not removed under it.

  • DELETE /api/v3/people/{uuid} marks the person and their connected bank accounts as scheduled for deletion and returns 202 Accepted
  • A person scheduled for deletion is omitted from v3 list responses and cannot be the party to a new transaction or refund
  • After 70 days the person and their bank accounts are soft-deleted; accounts linked through an aggregator are unlinked or removed at the aggregator where applicable
  • If any of the person’s bank accounts has had activity within the lookback window, the person stays scheduled and is checked again on the next run
  • 403 is returned for a person belonging to another vendor, a token without the delete ability, a user that is not a person, and a person already scheduled for deletion

The POST /api/v3/transactions endpoint now requires payor_uuid in place of payer_uuid, matching the payor object that v3 responses and webhooks already use.

The rename is a breaking change for anyone already calling the v3 Create Transaction endpoint with payer_uuid: the request is rejected until the field is renamed. v1, v2 and third-party transaction creation keep payer_uuid.

  • POST /api/v3/transactions requires payor_uuid instead of payer_uuid; the UUID is looked up the same way as before, a vendor person or business first and then a merchant
  • Validation errors use the payor_uuid field, with messages such as “The payor uuid field is required.”, and the not-found, on-hold and bank account errors for the payor now say “payor”
  • The transaction response and the transaction.created webhook already return a payor object; that is unchanged

The v3 refund resource now includes the parent transaction_uuid at its top level and reports an ACH return code on the leg it belongs to: the capture and payout objects each carry their own ach_return_code.

A refund has two ACH legs, pulling the funds back and sending them to the customer, and either can be returned. With the return code on the leg that failed, an integrator can tell which movement was rejected without comparing timestamps, and with transaction_uuid at the root it can load the original transaction without a search. No existing fields were removed or renamed.

  • transaction_uuid is included at the top level of each refund
  • capture.ach_return_code and payout.ach_return_code carry the return code of whichever leg failed most recently; the other leg’s value is null, and both are null when neither has failed
  • The fields appear in the v3 refund create, list and fetch responses, in the refunds embedded in the v3 transaction response, and in v3 refund webhooks

The clawback resource now includes a payor object. For clawbacks of type reverse_payout and refund, payor identifies the party the funds are recovered from, which is the payer on the original transaction.

For these two clawback types the funds being recovered were returned to the payer, so the payer is the party they are recovered from. An integrator reading a reverse_payout or refund clawback should look at payor for the party involved; payee is populated for transaction and vendor_fee clawbacks.

  • The clawback resource includes a payor object for clawbacks of type reverse_payout and refund, and payee is null for them
  • transaction and vendor_fee clawbacks keep payee and have a null payor
  • Clawbacks of type reverse_payout and refund debit the payer’s bank account associated with the transaction

Refunds and reverse payouts now follow the state of the payment they relate to. A reverse payout or refund is not created for a transaction or payout that has failed, and one that is still pending when that failure arrives is cancelled, with a new reverse_payout.cancelled webhook event and the existing refund cancelled event sent. Where funds have already been returned for a payment that later fails, GrailPay recovers them through a clawback, and the clawback resource now carries the reverse payout or refund it recovers.

Integrators may see a refund or reverse payout cancelled rather than completed when the underlying payment fails, and should subscribe to reverse_payout.cancelled and refund.cancelled to track them. Where funds had already gone out, recovery appears as a clawback with the usual clawback events, so it shows up in the same records and webhooks as any other clawback.

  • A reverse payout is not created when its transaction has failed; a pending reverse payout is cancelled when the transaction fails, and the amount of a reverse payout is the transaction amount minus any refunds already made
  • A refund is not created when its transaction or payout has failed; a refund whose ACH entry has not yet been submitted is cancelled when the transaction or payout fails, with the refund.cancelled event sent
  • New reverse_payout.cancelled webhook event on v3 and ReversePayoutCancelled on v1, sent when a reverse payout is cancelled; the v3 payload carries the reverse payout plus relations.payout and relations.transaction
  • Clawbacks of type reverse_payout or refund are created for funds already returned on a payment that later failed, with the clawback webhook events sent
  • The clawback resource’s relations object now includes reverse_payout and refund alongside transaction and payout, and the API reference for the v3 clawback endpoints covers reverse payout and refund clawbacks

GrailPay has improved the logic that determines when clawbacks, reverse payouts, refunds and processor payouts are considered settled. For refunds, this covers both the refund capture and the refund payout.

Settlement is what moves a payment to its completed state and triggers the completed events integrators act on. Integrators may see these payments reach that state, and receive those events, earlier. The statuses and events themselves are unchanged, and each payment settles once, so completed events are not sent twice.

  • Improved settlement logic for clawbacks, reverse payouts, refunds (capture and payout) and processor payouts
  • Settled statuses and completed events for these payments may arrive earlier
  • No change to the statuses or events themselves; a payment is settled once and its completed events are sent once

Vendors and processors can now look up who they are with GET /api/v3/me, and a vendor, or the processor that owns it, can read a vendor’s details with GET /api/v3/vendors/{uuid}. Vendors with a pre-funded FBO account receive an hourly fbo.account_snapshot webhook with their balance. Routing numbers are now validated before a bank account is accepted, both when adding an account and when onboarding a person, merchant or business with one.

Until now a key could not discover its own vendor or processor identity through the API, and a vendor’s bank accounts and FBO status required separate calls. The snapshot webhook gives a vendor a standing view of its available balance and whether it is in good, review or low status, so it can top up before standalone payouts are affected. Routing number validation reports a bad routing number as a 422 on the request that carried it.

  • New GET /api/v3/vendors/{uuid} returning the vendor’s uuid, name, bank_accounts (masked, with funding and payout purpose and default flags), fbo_account.enabled and created_at; a vendor sees only itself and a processor only the vendors it owns, with unknown or unowned vendors returning 404
  • New GET /api/v3/me returning entity.type (vendor or processor), entity.uuid and entity.name for the authenticated key; other token types receive 403
  • New hourly fbo.account_snapshot webhook for vendors with a pre-funded FBO (and their registered processor), carrying current_balance, pending_payouts, available_balance, balance_status of good, review or low, currency and snapshot_at; sent every hour even when nothing changed, and skipped for vendors without an FBO
  • In-flight FedNow standalone payouts count toward pending_payouts in the snapshot
  • Routing numbers must pass the ABA check digit and be confirmed ACH-enabled when adding a bank account or onboarding a person, merchant or business with one; both failures return the same routing-number-invalid validation message
  • On v3 onboarding the failure is reported on bank_account.routing_number
  • The v3 bank account validate endpoint still checks only that the routing number is 9 digits, since account intelligence validates it there

The v3 onboard and update responses for a person, a business and a merchant now return the full bank account resource for the bank account included in the request.

An integrator that onboards an entity with a bank account can use the account’s UUID straight from the onboarding response, for example to make it the default or to create a transaction, instead of making a second call to look it up.

  • Person, business and merchant onboard and update responses on v3 include a bank_accounts list holding the bank account supplied in the request; other accounts on the entity are not fetched into this list

GrailPay has improved the logic that determines when a payout is considered settled.

Settlement is what moves a payout to its complete state and triggers the completed event integrators act on. Integrators may see payouts reach that state, and receive that event, earlier, so they learn sooner that a payee has been paid. The status and event themselves are unchanged, and a payout settles once, so its completed event is not sent twice.

  • Improved settlement logic for payouts
  • The payout complete status and completed event may arrive earlier
  • No change to the status or event themselves; a payout is settled once and its completed event is sent once

Customers can list their individual billing items and a billing summary on v3, for merchants, businesses and persons. Each billing item now carries a nested entity (name, UUID, type and client reference ID) and a source describing the event that was billed, and both endpoints filter by entity UUID, billable event name, processor MID and date range. Separately, v3 fetch endpoints now return person, merchant, business and bank account records even when the person is not approved or the merchant is deactivated.

With the billed entity identified in one consistent shape, including the client reference ID provided at onboarding, an integrator can map every billing item to its own records without joining on names. The read change means an integration can inspect an on-hold person or a deactivated merchant, and their bank accounts, to see why that party cannot transact; creating transactions and changing bank accounts for them is still refused.

  • GET /api/v3/billing/items returns each item with billed_at, amount, billable_event_name, a nested entity (name, uuid, type, nullable client_reference_id) and a source (type, uuid); the flat merchant name, merchant UUID and client reference fields are replaced by entity
  • GET /api/v3/billing/items and GET /api/v3/billing/summary accept filter[entity_uuid], filter[billable_event_name], filter[processor_mid], filter[start_date] and filter[end_date]; filter[merchant_uuid] is no longer accepted
  • GET /api/v3/people/{uuid}, GET /api/v3/merchants/{uuid}, GET /api/v3/businesses/{uuid}, and the v3 bank account list, fetch, balance and history endpoints return 200 for an on-hold person or a deactivated merchant, including the nested bank accounts and the status, is_active and deactivated_reason fields
  • Creating a transaction with an on-hold party or deactivated merchant is still rejected, bank account changes for a not-approved entity still return 403, and entities scheduled for deletion still return 403 on fetch

Vendors now receive the same compliance status webhooks for person KYC that they already receive for merchant KYB. No new event names were added, and merchant KYB and beneficial owner payloads are unchanged.

Until now a person verified through the standalone KYC endpoint produced no compliance status events, so an integrator had to poll to learn the outcome. Subscribers to compliance_status.processing, compliance_status.approved and compliance_status.rejected now get person KYC results pushed the same way as merchant results, with the payload identifying the person rather than a merchant.

  • compliance_status.processing is sent after a person KYC request has been successfully started; compliance_status.approved or compliance_status.rejected is sent when the verification provider reports a pass or fail
  • The existing onboarding ComplianceStatusChanged webhook is also sent for those person KYC status updates
  • The payload identifies a person: entity.type is person, entity.uuid is the person’s UUID, and compliance holds a single kyc status rather than kyb and a beneficial owner list
  • These webhooks are not sent for external KYC, when provider user creation fails, for a duplicate KYC re-registration, or when the person already has an identity token

Vendors can now fund their pre-funded FBO account through the API. A new endpoint originates a same-day ACH debit from one of the vendor’s funding bank accounts into the FBO, a second endpoint cancels a funding transfer while it is still pending, and five new fbo.funding_* webhook events report the transfer’s lifecycle. Funding is separate from merchant payments: it creates no merchant payout, refund or fraud check.

Standalone payouts draw on the vendor’s pre-funded FBO, and until now topping it up happened outside the API. With a funding endpoint, a vendor can keep its FBO funded programmatically, for example in response to the balance it sees in its payouts, and track each transfer from creation to settlement through webhooks rather than polling. Because funding is isolated from the merchant transaction flows, nothing about merchant payments, refunds or returns changes.

  • New POST /api/v3/vendors/{uuid}/fbo/funding requesting a same-day ACH debit into the vendor’s pre-funded FBO; amount (integer cents) is required, and source_account may be omitted to use the default funding account, carry the uuid of an existing funding account, or carry new bank details, which are saved as a funding account
  • The request is accepted immediately with 201 and the transfer’s uuid and amount; the ACH entry is originated in the background, and the FBO balance is credited only once it is
  • Vendor keys only: processor keys receive 403, and a vendor can fund only its own FBO; a request with the same idempotency key but a different body returns 409; funding returns 422 when the vendor has no pre-funded FBO or no usable funding account, and payout-purpose accounts cannot be the source
  • New DELETE /api/v3/vendors/{uuid}/fbo/funding/{funding_uuid} cancels a transfer while it is still pending; once the ACH entry is in progress, settled, failed or already cancelled the cancel is refused, and funding transfers cannot be cancelled, paused, resumed or refunded through the merchant transaction endpoints
  • When a funding ACH entry settles, the funds stay in the vendor FBO; if it is returned or rejected the funding is marked failed, settled funds are moved back out of the vendor FBO, and return billing is charged to the vendor
  • New webhook events for the vendor and its registered processor: fbo.funding_created when the request is saved, fbo.funding_processing when the ACH entry is originated, fbo.funding_completed when it settles, fbo.funding_failed when it is returned or rejected, and fbo.funding_canceled when it is cancelled, each with a dedicated funding payload

GrailPay has improved how payment statuses are kept up to date. The improvement covers ACH status changes on transactions, payouts, processor payouts, reverse payouts, clawbacks and refunds, and FedNow status changes on payouts and processor payouts.

Status fields and timestamps move closer to real time, so what an integrator reads from the API or receives in webhooks reflects a payment’s current state sooner, for sent, processed, failed, cancelled and other states. The lifecycle rules are unchanged: a status still moves only through its valid states.

  • Faster status updates for ACH payments: transactions, payouts, processor payouts, reverse payouts, clawbacks and refunds
  • Faster status updates for FedNow payouts and processor payouts, refreshing status and timing fields and leaving other fields unchanged
  • Statuses still move only through valid lifecycle states

GrailPay has improved the logic that determines when a capture payment is considered settled.

Settlement is what moves a capture forward and triggers the events that follow it. Integrators may see captures reach their settled state, and receive those events, earlier. A capture still settles once, and a failed or cancelled capture keeps its status.

  • Improved settlement logic for capture payments
  • Settled status and the events that follow settlement may arrive earlier
  • A capture is settled once and its completed events are sent once; failed and cancelled captures keep their status

Refunds and reverse payouts now wait a configurable number of business days before they are processed. The delay can be set per vendor or per processor payout configuration, and it applies when a refund is captured, when a refund is paid out, and when a reverse payout is processed. Delays are counted in business days, taking bank holidays into account.

The delay gives the underlying transaction time to settle before funds move back out. A client that needs a longer or shorter hold than the platform default can have it configured for its vendor, and a processor can set one for all of its vendors; where neither is configured the platform default applies. Integrators should expect refund and reverse payout timing to follow business days rather than calendar days.

  • Delay periods for refund capture, refund payout and reverse payout processing are configurable per vendor and per processor payout configuration
  • A vendor-level delay takes precedence, then a processor-level delay, then the platform default
  • Delays are calculated in business days, excluding bank holidays
  • All v3 list and fetch endpoints (business, merchant, person, clawbacks, payouts, refunds, transactions and reverse payouts) load related records more efficiently, improving response times

Reverse payouts can now be listed and fetched individually on v3, so funds returned to payers can be tracked directly through the API. Fetching a single reverse payout also returns its related transaction and payout. On the reverse payout resource, the trace_id field has been replaced by bank_identifiers, which reports the bank ID and trace number under the same names used elsewhere in v3.

Until now a reverse payout could only be seen through the transaction it belonged to. With a list endpoint and filters, an integrator can monitor every reverse payout across transactions, narrow them by status, return code, date or amount, and reconcile each one from its bank identifiers. Consumers of the reverse payout resource that read trace_id need to switch to bank_identifiers.

  • New v3 endpoints to list reverse payouts and fetch one by UUID
  • The list filters by status, ACH return code, transaction, date range and amount (with comparison operators), and sorts by date or amount
  • Fetching a single reverse payout includes its related transaction and payout in the same response
  • trace_id on the reverse payout resource is replaced by bank_identifiers, carrying the bank ID and trace number

Vendors can now add, list, switch and remove funding bank accounts on their vendor profile through four new v3 endpoints. Funding accounts are kept separate from payout accounts, so a vendor can have one default account for funding its FBO and a different default account for receiving payouts. Vendor fee payouts and the clawbacks of those fees now use the vendor’s designated payout account.

A vendor that pre-funds an FBO needs a bank account to fund it from, and that account is often not the one it wants fees paid into. Keeping the two purposes apart, each with its own default, lets a vendor manage both through the API without one setting overriding the other, and keeps fee payments flowing to the payout account even after a funding account is added. Processor and merchant payout behavior is unchanged.

  • New POST /api/v3/vendors/{uuid}/bank-accounts to attach a funding bank account, taking account_number, routing_number, account_type, account_name, optional client_reference_id and purposes.funding.enabled; the first funding account becomes the default automatically, resubmitting the same account reuses it with a 200 instead of a duplicate, and payout accounts cannot be added here
  • New GET /api/v3/vendors/{uuid}/bank-accounts listing the vendor’s accounts with masked account numbers and purposes.funding and purposes.payout flags showing which account is the default for each purpose; an empty list is returned when there are none
  • New PUT /api/v3/vendors/{uuid}/bank-accounts/{bank_account_uuid}/default to make an existing funding account the default funding source
  • New DELETE /api/v3/vendors/{uuid}/bank-accounts/{bank_account_uuid} to remove a funding account; removal returns 422 if the account was used within the recent-activity window (30 days by default), and if the removed account was the default another funding account is promoted
  • All four endpoints accept vendor keys only: processor keys receive 403, and an unknown or unowned vendor UUID returns 404
  • Vendor fee payouts and clawbacks of vendor fees use the vendor’s designated payout account; processor and merchant payout behavior is unchanged

The v3 payout endpoints now serve processor payouts as well as regular payouts, v3 transactions can be filtered by the payout they belong to, and v3 billing items return the merchant’s client reference ID.

A processor can now manage its own payouts through the same v3 interface as everything else, and any integrator can go from a payout, processor or regular, to the transactions it covers with one filtered request. The client reference ID on billing items lets billing records be mapped to the integrator’s own records using the reference it supplied at onboarding. Note that the v3 payout detail response now returns the related transaction’s UUID instead of the whole transaction object.

  • GET /api/v3/payouts accepts filter[payout_type]=processor to list processor payouts, and the fetch endpoint returns a processor payout by its UUID; processor payouts are available to processor users only
  • The v3 payout detail response returns the related transaction’s UUID instead of the complete transaction object, for both regular and processor payouts
  • GET /api/v3/transactions accepts filter[payout_uuid], returning the transactions associated with a regular or processor payout
  • GET /api/v3/billing/items returns client_reference_id, the merchant’s reference supplied at onboarding, or null when none is configured; existing fields are unchanged

The SEC code of each ACH entry is now returned across the v3 API. A sec_code field (ccd, web or ppd) appears on transactions, payouts, processor payouts, clawbacks and reverse payouts, and on both the capture and payout sides of a refund, wherever those resources are returned by v3 endpoints or webhook events. The v3 refund resource has also been simplified: batch membership now lives only in the nested batch object.

An integrator that reconciles or reports on ACH activity can now read the SEC code directly from each resource and event instead of inferring it, and the same field appears in the same place across every payment type. The refund change removes two redundant fields, so refund consumers should read batch membership from batch alone.

  • sec_code added to the v3 transaction, payout, processor payout, clawback and reverse payout resources, and to the capture and payout sections of the v3 refund resource, with values ccd, web or ppd (or null)
  • The field is carried wherever those resources appear, including every v3 webhook event that embeds them
  • The v3 refund resource no longer includes top-level is_batch or batch_uuid; a non-batched refund returns "batch": null, and a batched refund’s batch object holds uuid, refund_count and total_amount, placed after timestamps
  • filter[is_batch] and filter[batch_uuid] on the v3 refund list are unchanged
  • The batch_refund webhook’s data.batch_refund.uuid is the shared batch UUID
  • The API reference documents the refund amount as an integer in cents

GrailPay has improved how reverse payouts are originated after a payout is returned, so a reverse payout can begin sooner. Separately, merchant onboarding on v2 and v3 now creates the merchant and its beneficial owners even when business verification cannot be reached at the time of the request.

Funds can start their way back to the payer sooner after a return, with no change to the amount, the payer-facing behavior or notification timing. On onboarding, the availability of business verification does not block the integrator’s onboarding call.

  • Reverse payouts are originated sooner after a payout return
  • Reverse payout amounts, payer-facing behavior and notification timing are unchanged
  • v2 and v3 merchant onboarding create the merchant and its beneficial owners even if business verification is unavailable at the time

Refunds can now be created on v3 with POST /api/v3/refunds. Refund creation on both v1 and v3 is now asynchronous: a new refund is accepted with a QUEUED status and processed in the background, and a refund that would exceed the origination limit waits for capacity instead of being rejected. The v3 refund list and fetch responses also expose batch membership.

Until now a refund request that reached the origination limit came back as an error the integrator had to retry itself. With queued processing, the request is accepted immediately and GrailPay retries it when capacity is available, so creating a refund is a single call regardless of volume. QUEUED is the first state a refund passes through, so integrators that drive workflows from refund status should expect it before REFUND_PENDING. On v3, the batch fields and filters make it possible to find every refund that was captured together.

  • New POST /api/v3/refunds taking transaction_uuid, amount (integer) and an optional client_reference_id; returns 201 with the full refund resource in QUEUED status and supports the standard idempotency header
  • Eligibility checks (ownership, refundable transaction, remaining refundable amount) return 422 with field-level errors
  • On both v1 and v3, refunds are created QUEUED and processed asynchronously; v1 now returns 201 with status QUEUED instead of 429 when the origination limit is reached
  • A refund that exceeds the origination limit stays QUEUED and is retried until capacity is available, then moves to REFUND_PENDING
  • Queued refunds count toward a transaction’s remaining refundable amount
  • v3 refund list and fetch responses include is_batch and an embedded batch summary; the list accepts filter[batch_uuid] and filter[is_batch]
  • The API reference documents the v3 refund endpoints, the batch fields and filters, and the QUEUED status

Transactions can now be created on v3 with POST /api/v3/transactions, identifying the payer and payee by UUID. The request accepts an optional modality object that sets the payment rail and speed for the debit and for the payout separately, across ACH standard, ACH same day and, where it is enabled for the vendor, FedNow. Transaction responses and transaction and payout webhook payloads now include a modality object alongside the existing speed field.

With creation on v3, the whole transaction lifecycle lives on one API version, and the modality object gives explicit control over how each leg moves, so a debit and its payout can run on different rails or speeds. Existing consumers are unaffected: speed is still populated, now derived from the chosen modality.

  • New POST /api/v3/transactions with payer_uuid, payee_uuid and amount required, plus optional transaction_fee, client_reference_id, company_name, description, addenda, source_bank_account_uuid and destination_bank_account_uuid; the transaction is queued and returned with 201
  • Optional modality object with transaction and payout legs, each taking a payment_rail and speed; FedNow is accepted only for vendors allowed to use it
  • modality.payout is rejected for vendors whose payouts go out through processor batch payouts
  • Transaction responses (list, fetch and create) include a modality object with transaction and payout legs; the existing speed field remains
  • Transaction and payout webhook events include a modality object with payment_rail and speed; speed is still present and derived from the modality
  • The API reference documents the new endpoint, including the modality object and all response codes

The global API rate limit has been raised to 2,000 requests per minute. It was previously 400.

High-volume clients, such as those submitting recurring autopay batches, now have more room during peak minutes. The limit still protects the platform: requests beyond it are rejected with a 429 and the message “Too many attempts”.

  • Global API throttle raised from 400 to 2,000 requests per minute across environments
  • The limit applies per user ID or IP address; requests over it receive a 429 “Too many attempts” response

Clawbacks are now created for payouts sent through FedNow, both processor payouts and individual payouts, in the same way as for ACH payouts.

A client paying out through FedNow now gets the same recovery workflow as on ACH: when a payout needs to be recovered, a clawback is generated and shows up in the same clawback records, responses and webhook events, so reconciliation does not depend on which rail the payout used.

  • Clawback creation covers FedNow payouts, for both processor and individual payouts

Every v3 payment resource and every v3 webhook payload now carries a standardized bank_identifiers object holding the bank ID and trace ID for the money movement it represents. The same object has been added to the remaining v1 webhook events, completing its rollout across the v1 webhook suite.

Bank identifiers are what tie a GrailPay record to the entry on a bank statement. With one object in one shape on every payment resource and every event, an integrator can reconcile transactions, payouts, refunds and clawbacks with a single piece of parsing code, whether the data arrives from an API call or a webhook.

  • bank_identifiers added to the v3 List and Fetch endpoints for transactions, payouts, refunds and clawbacks
  • bank_identifiers added to all v3 transaction, payout, processor payout, refund, batch refund, reverse payout and clawback webhook events
  • bank_identifiers added to the v1 Payout, Reverse Payout, Refund, Batch Refund and Batch Payout webhook events, so every v1 payment webhook now carries it
  • The object holds both the bank ID and the trace ID, and the API reference and resource documentation describe its fields

The standardized bank_identifiers object now appears in the v1 processor payout webhook events, in the v1 and v2 Batch Payout API responses, and in clawback webhook events.

Processors and batch payout consumers previously had to read bank identifiers from version-specific fields or look them up separately. With the same bank_identifiers object in these payloads, the identifiers needed to match a payout or clawback to bank activity arrive in one consistent shape, and existing payload fields are untouched.

  • v1 processor payout webhook events (BatchPayout, ProcessorPayoutCreated, ProcessorPayoutCompleted, ProcessorPayoutFailed) include bank_identifiers with credit_bank_id and credit_trace_id
  • v1 and v2 Batch Payout endpoints return a bank_identifiers object on each payout; identifiers that are not yet available are returned as null rather than omitted
  • Clawback webhook events include a bank_identifiers object with both internal and external identifiers; existing payload fields are preserved

The v3 payout endpoints are now publicly available and documented in the API reference. Vendors can retrieve payouts with their existing tokens, provided the token carries the transactions fetch ability.

With GET /api/v3/payouts and GET /api/v3/payouts/{uuid} open, an integrator can list and inspect payouts directly, including standalone payouts, using the filters, sorting, pagination and includes described in the reference, without needing a new token.

  • GET /api/v3/payouts and GET /api/v3/payouts/{uuid} are publicly available
  • The API reference documents both endpoints, including filters, sorting, pagination and include parameters, with standalone payouts in the examples
  • A vendor token with the transactions fetch ability can call them; no new ability is required

The v2 List Transactions and Fetch Transaction responses now include a bank_identifiers object that gathers the bank and trace identifiers for a transaction and every payment activity related to it. All v1 transaction webhook events carry a bank_identifiers object as well. On the v3 Returns endpoint, the generic bank_id and trace_id fields have been replaced by direction-specific names.

Reconciling a transaction against bank activity has meant collecting identifiers from several places, since the debit, the payout, any clawback, reverse payout or refund each has its own. With them grouped under bank_identifiers, an integrator reads them from one object in one response or one webhook. On Returns, the directional names make clear whether an identifier belongs to the debit or the credit side, so a return can be matched without guessing.

  • v2 List Transactions and Fetch Transaction include bank_identifiers with transaction (debit_bank_id, debit_trace_id), payout (credit_bank_id, credit_trace_id), clawback, reverse_payout, and refunds with separate capture and payout sections
  • All v1 transaction webhook events (TransactionStarted, TransactionCaptureStarted, TransactionCompleted, TransactionFailed, TransactionCanceled, TransactionPaused, TransactionResumed, TransactionDeclined, TransactionAwaitingCancellation) include bank_identifiers with debit_bank_id and debit_trace_id
  • On GET /api/v3/returns, bank_id and trace_id are replaced by debit_bank_id, credit_bank_id, debit_trace_id and credit_trace_id, depending on the leg the return occurred on
  • When a paused transaction is resumed and a replacement ACH entry is created, the transaction’s bank identifier is updated to reference the new entry

The v3 Clawback List and Show endpoints are now documented in the API reference, and their relations.payout object includes the payout’s uuid, trace_id and status. Passing ?include=payout still returns the full payout resource.

Most clawback consumers need the related payout’s identity and state, not its whole record. Having uuid, trace_id and status inline avoids a second request for the common case, while include=payout remains for callers that want everything. Only new fields were added, so existing consumers are unaffected.

  • v3 Clawback List and Show are documented in the API reference, including filters, sorting, includes and the response structure
  • relations.payout on a clawback now includes uuid, trace_id and status
  • ?include=payout continues to return the full payout resource

A new GET /api/v3/returns endpoint lists every ACH return visible to the authenticated entity in one place, regardless of which leg of a transaction the return occurred on.

Until now an ACH return had to be found through the transaction or payout it belonged to, which meant checking several places to see everything that had come back. The Returns endpoint merges returns from both the debit and the payout side into a single paginated list, so an integrator can monitor returns with one query and filter down to a specific transaction, payout, clawback, reverse payout, entity or bank reference when needed.

  • GET /api/v3/returns returns a paginated list of ACH returns across transactions and payouts for the authenticated entity
  • Filters cover the leg of the transaction the return occurred on, ACH return codes, amount with comparison operators, the related transaction, payout, clawback or reverse payout UUID, the entity UUID, the vendor, and the bank or trace identifier
  • The endpoint is documented in the API reference

The standalone Person KYC endpoint is now documented in the API reference.

Integrators verifying individuals outside of merchant onboarding can now work from the published request and response definitions for the endpoint instead of relying on guidance supplied directly.

  • The Person KYC endpoint’s request, response and error definitions are published in the API reference

When a transaction fails, any reverse payout for it that is still pending is cancelled automatically. If the reverse payout had already initiated its ACH entry, that entry is cancelled as well.

A reverse payout exists to send funds back for a transaction, so once that transaction has failed there is nothing left to reverse. Cancelling it automatically means an integrator does not have to watch for the failure and cancel the reverse payout itself, and the reverse payout’s records and status stay consistent with the transaction’s outcome.

  • A pending reverse payout is cancelled when its transaction fails, including when the failure arrives through a return
  • If the reverse payout had already initiated an ACH entry, the entry is cancelled too; the cancellation is recorded with a reason
  • Cancellation applies only to eligible reverse payouts, and the reverse payout is left unchanged if its ACH entry cannot be cancelled

The failure_simulation parameter has been removed from the v1 Create Transaction endpoint and from its documentation. The API reference for the v1 Add Bank Account endpoint now also documents the 200 OK response returned when the account already exists.

Integrators that still send failure_simulation on v1 Create Transaction can remove it from their requests. The documented 200 OK lets an integrator handle the already-exists case on Add Bank Account deliberately rather than treating anything but 201 as an error.

  • failure_simulation is no longer accepted or documented on the v1 Create Transaction endpoint
  • POST /3p/api/v1/bank-account/{user_uuid} documents a 200 OK response for an account that already exists, alongside the existing 201 Created

The v3 bank account API is now complete. Alongside the existing list, fetch and balance endpoints, v3 gains endpoints to add a bank account, switch an entity’s default account, delete an account and read an account’s transaction history. The balance endpoint now also serves accounts linked through the previous aggregator, and the API reference carries full specifications for every v3 bank account endpoint.

Until now, managing bank accounts meant mixing v3 reads with v1 or v2 writes. With add, switch default and delete on v3, an integrator can handle the whole bank account lifecycle on one API version, with the same entity model, masking rules and response envelope throughout, and read balances and transaction history for the accounts it manages there.

  • New POST /api/v3/bank-accounts to add a manually entered or aggregator-linked bank account to a person, business or merchant; adding an account that already exists returns the existing account instead of a duplicate
  • New PUT /api/v3/bank-accounts/{uuid}/default to make an account the entity’s default, with a distinct response when it already is
  • New DELETE /api/v3/bank-accounts/{uuid}, which cleans up the provider link, reassigns the default account if needed and emits the bank account removed webhook event
  • New GET /api/v3/bank-accounts/{uuid}/history returning the account’s transactions with pagination, a next_cursor where applicable, and optional start_date and end_date filters
  • GET /api/v3/bank-accounts/{uuid}/balance returns available balance and currency for accounts linked through the previous aggregator as well as the current one
  • Accounts whose linking has not completed are excluded from list responses
  • The API reference now documents every v3 bank account endpoint under a “V3 Bank Accounts” tag, with standardized success and error envelopes

Vendors can now process person-to-person (P2P) transactions, where both the payer and the payee are persons. P2P is enabled per vendor by GrailPay, and a P2P transaction is accepted only when the payee has an approved KYC status.

Until now a transaction had to involve a merchant or business on at least one side. With P2P enabled, an integrator can move funds between two onboarded persons through the same v1 Create Transaction request it already uses, and the KYC requirement on the payee keeps those transfers within the platform’s compliance rules. Merchant and business transaction flows are unchanged.

  • A transaction whose payer and payee are both persons is treated as a P2P transaction on the v1 Create Transaction endpoint
  • P2P transactions require the vendor’s P2P capability to be enabled by GrailPay; it is off by default
  • The payee must have an approved KYC status, and the payer and payee cannot be the same person
  • Each of these conditions returns its own validation error when not met

Webhook subscribers are now notified when a Notification of Change (NOC) is received, not only when it has been processed. A new noc.received event (v3) and NocReceived event (v1) fire as soon as a NOC request is created, and noc.processed (v3) and NocProcessed (v1) fire once the NOC has been processed, whether that happened automatically or through GrailPay’s operators.

A NOC means the bank has told GrailPay that an account’s details are changing. With a received event, an integrator learns about the change as soon as it arrives and can start tracking it, instead of only hearing about it after the change has been applied. The processed event then confirms that the updated banking details are in place, so downstream records can be synchronized at the right moment.

  • New noc.received webhook event for v3 subscribers and NocReceived for v1 subscribers, sent when a NOC request is received
  • noc.processed (v3) and NocProcessed (v1) are sent when a NOC request has been processed successfully, whether automatically or by GrailPay
  • Processed events are sent only after processing succeeds; nothing is sent if processing fails or is rolled back

The BatchPayout and BatchRefund webhook events now include a trace_id in their payloads.

The trace identifier is what lets an integrator match the webhook event to the entry on its bank statement and to its own records. Having it in the payload removes a lookup step from reconciliation.

  • trace_id added to the BatchPayout webhook event payload
  • trace_id added to the BatchRefund webhook event payload

The v3 Fetch Transaction response now includes a clawback object at its root, alongside the existing payout and refunds objects, holding the transaction’s clawback when one exists and null otherwise. In clawback webhook events, the clawback_bank_identifier field has been renamed to clawback_trace_id, matching the trace ID naming used elsewhere in the API.

An integrator reading a transaction can now see its clawback in the same response instead of looking it up separately. The rename is a breaking change for webhook consumers: the clawback_bank_identifier key is no longer sent, so any code reading it from ClawbackCaptureStarted, ClawbackFailed or ClawbackCompleted events must switch to clawback_trace_id.

  • v3 Fetch Transaction returns a clawback object at the root of the response, in the standard clawback response format, or null when the transaction has no clawback
  • Clawback webhook events (ClawbackCaptureStarted, ClawbackFailed, ClawbackCompleted) now send clawback_trace_id in place of clawback_bank_identifier; the old key is no longer included

The v2 Fetch Transaction and List Transactions endpoints now return a clawback_trace_id inside each transaction’s trace_ids object when the transaction has a clawback.

With clawback_trace_id in trace_ids, an integrator can match a transaction’s clawback to the corresponding bank entry from the transaction record alone.

  • trace_ids.clawback_trace_id added to the v2 Fetch Transaction and List Transactions responses, present when a related clawback exists

The financing product has been retired and its API surface removed. The financing API, the v1 invoice endpoints under /users/{user_uuid}/invoices, the financing_credit_balance field on business responses, and the financing token types and abilities are gone.

No live integrations were calling the financing or invoice endpoints, so the removal should not affect current clients. Any code still reading financing_credit_balance from a business response should stop expecting it. Transactions that were created under the financing product are no longer subject to its cancellation restriction.

  • The financing API routes and the v1 third-party invoice endpoints (/users/{user_uuid}/invoices and related) have been removed
  • financing_credit_balance is no longer returned on v2 and v1 business responses
  • Financing token types and authorization abilities have been removed
  • The cancellation restriction that applied to financing transactions has been removed; the financing transaction type and status values are kept for historical records

A vendor can now have a preferred batch payout modality configured, either ACH same day or ACH standard. When it is set, every eligible transaction for a payee is consolidated into a single payout at that speed, instead of one payout per speed.

Until now batch payouts were grouped by transaction speed, so a payee with both standard and same-day transactions received two payouts. With a modality configured, that payee receives one payout at the vendor’s chosen speed, which simplifies reconciliation for the payee and makes payout timing predictable for the vendor. Vendors without a configured modality keep the current behavior.

  • Vendor-level batch payout modality setting, configured by GrailPay, with ach.sameday and ach.standard as the supported values
  • When set, all eligible transactions for a payee are aggregated into a single payout at the configured speed; no separate payout is created for the other speed
  • Applies to merchant, business and person batch payouts, independently per vendor
  • Vendors without a configured modality keep the existing behavior, one payout per speed

Clawback webhook events now carry a clawback_bank_identifier, the bank-side identifier of the ACH entry created for the clawback.

Until now clawback events gave no way to tie the event to the ACH record behind it, so reconciling a clawback against bank activity meant extra lookups. With the identifier in the payload, an integrator can correlate each clawback event with the corresponding ACH entry directly. All existing payload fields are unchanged.

  • clawback_bank_identifier added to every clawback webhook event
  • It is null on ClawbackStarted, before the ACH entry exists, and carries the ACH identifier on ClawbackCaptureStarted, ClawbackCompleted and ClawbackFailed
  • Existing clawback payload fields are unchanged

The v1 and v2 bank account endpoints now support accounts linked through the new Bank Link aggregator. Account balance (v1 and v2), cashflow prediction (v1) and transaction history (v2) work for these accounts.

Integrators on v1 and v2 do not need to move to v3 to work with accounts linked through the current Bank Link SDK. The endpoints they already call read balances, cashflow predictions and transaction history for those accounts, and keep working for accounts added any other way.

  • Get account balance (v1 and v2) returns balances for accounts linked through the new aggregator, provided the account is connected
  • Cashflow prediction (v1) and transaction history (v2) support accounts linked through the new aggregator
  • Existing response structure and pagination behavior are preserved

Processors can now activate and deactivate merchants that belong to their vendors, using the existing v3 merchant activation and deactivation endpoints with a processor token that has been granted the corresponding ability.

A processor that deactivates a merchant on its own side can now mirror that change in GrailPay through the API, keeping merchant status consistent across both systems without asking the vendor to do it. Ownership checks ensure a processor can only act on merchants under its own vendors.

  • Processor tokens can call the v3 activate and deactivate merchant endpoints for merchants of their associated vendors
  • A new token ability covers these actions and must be granted to the processor token
  • Ownership and business-type checks apply, so a processor cannot act on another processor’s vendors or merchants

Vendors can now send standalone payouts, which are payouts with no associated transaction, funded from the vendor’s own pre-funded FBO account. A new v3 endpoint creates them, and another returns the vendor’s FBO account details and current balance so the vendor can tell when the account needs a top-up. Standalone payouts flow through the same processing, status tracking, reporting and payout webhooks as transaction-backed payouts.

Until now every payout was tied to a transaction, so a vendor had no way to pay a person, business or merchant through GrailPay for anything that was not a payment it had collected. Standalone payouts open that up, and because they draw on the vendor’s pre-funded account, the FBO endpoint matters: an integrator can watch the balance and keep it funded, and a payout that would exceed it is rejected rather than attempted. Failed standalone payouts are handled for the vendor automatically.

  • New POST /api/v3/payouts/standalone creating a payout to an entity’s default bank account; entity_uuid, amount and speed are required, and speed accepts standard, fast or fednow
  • Standalone payouts must be enabled for the vendor by GrailPay, the vendor must have a pre-funded FBO account, and the token needs the standalone payout ability; otherwise the request returns 403
  • Requests are idempotent through the x-gp-request-id header, so a replay returns the original response instead of creating a second payout
  • A payout larger than the vendor’s available pre-funded balance is rejected; the minimum amount is 10 (amounts are integers in cents)
  • fednow is accepted only for vendors with FedNow enabled; otherwise the request is rejected with a message that FedNow is not available on the account
  • New GET /api/v3/vendors/{uuid}/fbo returning the vendor’s FBO account: bank name, name on account, full routing and account numbers, balance in cents, currency and the time the balance was last refreshed; vendor tokens only
  • Standalone payouts appear in the v3 list and fetch payout endpoints with transactions: [], and can be filtered with ?payout_type=standalone
  • Standalone payout responses include the recipient’s bank account details
  • Existing payout webhook events cover standalone payouts, attributed to the owning vendor
  • A failed ACH standalone payout returns the funds to the vendor’s pre-funded account; a failed FedNow standalone payout is automatically re-sent as an ACH standalone payout to the same recipient for the same amount

The company name that appears on batch payouts can now be set per vendor. Vendors without a configured name keep the default, GrailPay.

A vendor that wants its own name rather than GrailPay’s on its batch payouts can have it configured, while every other vendor’s payouts are unchanged.

  • Vendor-specific company name for batch payouts, configured by GrailPay; the default remains GrailPay when none is set
  • Originator names on payouts are sanitized and formatted automatically

API responses that list an entity’s bank accounts now include only accounts that are fully connected and active. An account whose bank linking has not yet completed is not returned until it is.

A partially linked account cannot be used for a payment, so showing it alongside usable accounts invites a bad selection. With pending accounts hidden until linking completes, an integrator can treat every account in a response as ready to use.

  • Bank account lists across the bank account endpoints return only connected, active accounts; pending accounts appear once the bank linking process has completed
  • Existing filtering and pagination behavior is unchanged

v3 webhook payloads for clawback, payout, processor payout, refund and reverse payout events now carry the related transaction and payout as embedded objects under a relations key. The clawback and reverse payout objects themselves no longer nest those relationships at the top level.

Until now these payloads exposed mostly identifiers for related records, so acting on an event meant a follow-up API call to fetch the transaction or payout it belonged to. With the related objects embedded, an integrator can process the event from the webhook alone. Consumers that read related records from the old top-level fields need to move to the relations object.

  • Clawback, payout, processor payout, refund and reverse payout webhook events include a relations object holding the related transaction and payout
  • Clawback and reverse payout objects no longer include nested relationship fields at the top level; read them from relations instead

The v3 Get All Transactions and Get Transaction endpoints are now public routes, available to any authenticated client.

Authorized clients can now read transaction data directly from v3, under the same authentication and authorization rules as the rest of the API.

  • GET /api/v3/transactions and GET /api/v3/transactions/{uuid} are publicly accessible, with the existing authentication and authorization rules
  • The API reference for the v3 transaction endpoints now documents the ACH timestamps schema

The v2 Delete Bank Account endpoint now supports bank accounts linked through the new Bank Link aggregator. These accounts can be removed through the same API flow used for every other bank account provider.

Deletion now behaves the same way across providers, and the existing validation rules and ownership checks apply unchanged.

  • The v2 Delete Bank Account endpoint identifies and processes accounts linked through the new Bank Link aggregator
  • Deletion behavior is aligned across supported bank linking providers; existing validation rules and ownership checks still apply

Bank accounts linked through the new Bank Link aggregator can now be used for payments. They are accepted as the source or destination of a v1 transaction and in v1 refunds, and they appear in the payer and payee details of transaction, payout, refund, clawback, merchant, business and person responses across v1, v2 and v3, as well as in webhook payloads.

With these accounts accepted everywhere the existing account types are, an integrator can link an entity’s bank account through the current SDK and create transactions, payouts and refunds against it without any provider-specific handling. Responses keep the same structure for every provider, so nothing changes for accounts linked another way.

  • Accounts linked through the new aggregator are accepted as the source and destination of a v1 Create Transaction request, alongside manually entered and previously linked accounts
  • Refunds can be created for transactions and payouts that involve these accounts
  • Transaction, payout, refund, clawback, merchant, business and person responses include these accounts in their payer and payee bank account details, with a consistent structure across providers
  • Webhook payloads include the bank account details for these accounts
  • Account and routing numbers for these accounts are masked in responses outside the bank account endpoints and in webhook payloads
  • The payer and payee UUIDs on a transaction may reference either a person or a merchant

GrailPay has upgraded the v3 webhook system. A much wider set of events is delivered in real time across transactions, payouts, refunds, clawbacks, reverse payouts, bank accounts, persons, merchants, businesses and compliance status. Delivery is queued with automatic retries and backoff, and every attempt is logged.

With event coverage for the whole payment lifecycle, an integrator can drive its own workflows from events instead of polling, and because failed deliveries are retried, a temporarily unavailable endpoint does not miss notifications. A webhook whose deliveries keep failing is deactivated automatically, so endpoint health is worth monitoring.

  • Payloads are versioned (event_version 3) and carry an event UUID and timestamp
  • Failed deliveries are retried automatically on a backoff schedule; a webhook that keeps failing is deactivated
  • Transaction events: transaction.created, transaction.processing, transaction.completed, transaction.failed, transaction.paused, transaction.resumed, transaction.awaiting_cancellation, transaction.cancelled, transaction.declined
  • Payout events: payout.created, payout.processing, payout.completed, payout.failed, and the same four stages for processor_payout, clawback and reverse_payout
  • Refund events: refund.created, refund.cancelled, batch_refund, refund.capture_processing, refund.capture_completed, refund.capture_failed, refund.payout_processing, refund.payout_completed, refund.payout_failed
  • Entity events: person.created, person.updated, person.status_changed, merchant.created, merchant.updated, business.created, business.updated
  • Compliance events: compliance_status.processing, compliance_status.in_review, compliance_status.approved, compliance_status.rejected
  • Bank account events: bank_account.link_success, bank_account.link_failed (with a failed_reason), bank_account.removed, and noc.processed carrying the previous and current account details
  • Payout responses include a payout_failure_reason when an ACH return code is present
  • Refund responses include batch identifiers and bank transaction tracking references
  • Every delivery attempt, retry and failure is logged for troubleshooting

The v3 Get All Refunds and Get Refund endpoints are now public. The list endpoint supports filtering by status, amount (with comparison operators), dates and ACH identifiers, plus sorting and pagination, and a single refund’s response includes its parent transaction.

Until now the v3 refund endpoints were not public. With the list endpoint open, an integrator can query refunds across transactions with filters and pagination, and read each refund together with its parent transaction and batch identifier in one call.

  • GET /api/v3/refunds is publicly available, with filtering by status, amount with operators, dates and ACH identifiers, plus sorting and pagination
  • GET /api/v3/refunds/{uuid} is publicly available and includes the parent transaction
  • Refund responses document a nullable batch_uuid and expanded inline bank_account fields
  • The API reference for the v3 bank account list and fetch endpoints now documents client_reference_id and person_uuid in the entity object

Refunds can now be created for transactions whose processor payout was completed through FedNow.

A client that pays out through FedNow can refund those payments through the same refund endpoints it already uses, with no separate handling for the payout rail.

  • Refund requests are accepted for settled transactions whose processor payout completed through FedNow

The v3 API gains a bank account balance endpoint, which returns the available and current balance of a linked bank account on demand. Bank accounts also accept an optional client_reference_id when they are linked, and the value is returned in bank account and entity responses.

A client can now check available funds before initiating a transaction against a linked account. And with client_reference_id stored on the bank account as well as the entity, an integrator can reconcile GrailPay records against its own identifiers without keeping a separate mapping.

  • New GET /api/v3/bank-accounts/{uuid}/balance returning uuid, provider, the available and current balances, limit, currency and as_of
  • The balance endpoint is available for accounts linked through the new Bank Link aggregator; it returns 403 when the token lacks the required ability, 422 for a provider that does not support balance checks, and 404 for an account whose connection is not yet complete
  • Bank accounts accept an optional client_reference_id (up to 255 characters) at linking time, returned in bank account, entity and session responses

Bank Link can now run on a vendor’s own bank aggregator configuration. A client with its own aggregator credentials and environment can have them configured for its vendor, so the bank linking experience carries the client’s branding and runs in its own environment. Existing integrations continue on GrailPay’s default configuration with no changes required.

A client that wants its own branding in the bank linking flow, or needs its aggregator environment kept separate from other vendors, can now have that without changing how it calls the API. Webhooks from the aggregator are validated with the vendor’s own secret when one is configured, so each vendor’s integration stays isolated from the others.

  • Vendor-specific bank aggregator configuration, so a client can use its own credentials, environment and branding for bank linking
  • Configured by GrailPay per vendor; vendors without their own configuration fall back to GrailPay’s default, so existing integrations keep working unchanged
  • Aggregator webhooks are validated with the vendor’s own secret when one is configured, with the same fallback, improving isolation between vendor integrations
  • Credentials and webhook secrets are stored encrypted

The v3 bank account endpoints now return the full routing number and account number for each bank account. Previously these fields carried only the last four digits.

An integrator that reads a linked bank account through the v3 API now gets the complete account and routing numbers in the same response, so production integrations that depend on the full values can rely on the v3 endpoints.

  • The v3 list and fetch bank account endpoints return the full account_number and routing_number values

The Bank Link SDK now runs on a new bank aggregation integration that supports multiple aggregators through one interface, with feature parity and backward compatibility for every existing callback and configuration option. Alongside it, the v3 API gains endpoints for listing bank accounts, fetching a single bank account, and retrieving the verified owners of a linked account.

Until now there was no v3 endpoint for reading linked bank accounts back out of the API. An integrator can now list an entity’s accounts, fetch one by its UUID, read its owners, and see from its status whether the account and routing numbers have been retrieved yet. Because the aggregator migration keeps every existing callback and configuration option working, current Bank Link integrations need no changes to benefit from the improved institution coverage.

  • The Bank Link SDK has migrated to a new bank aggregator integration, with feature parity and backward compatibility for all existing callbacks and configuration options
  • New v3 endpoint to list bank accounts, with filtering by entity, account type, default status, provider and name, sorting, and pagination
  • New v3 endpoint to fetch a single bank account by UUID, returning masked account and routing numbers, the owning entity, and timestamps
  • New v3 endpoint to retrieve the owners of a linked bank account, with each owner’s name returned as a structured names object
  • Bank account responses include a status of pending, connected or failed, reflecting whether account and routing numbers have been retrieved; failed retrievals are retried automatically
  • Account verification is supported through the new integration, and the bank name is now stored for each linked account
  • Processors can access bank accounts belonging to their associated vendors
  • Improved performance and consistency in bank account retrieval

GrailPay now enforces transaction rules when a transaction is created and while it is processed. A rule can add a settlement delay or decline the transaction outright, and rules apply either globally or to a specific vendor. Declined transactions carry a new declined status, with declined_reason and declined_at in transaction responses, and a new TransactionDeclined webhook event is sent whenever a decline occurs.

A transaction can now be declined before it ever reaches the processing queue, so an integrator may see a declined status immediately after creation rather than a failure later in the lifecycle. Declined transactions cannot be cancelled, paused, resumed or refunded, and no payout, clawback or reverse payout is created for them, so declined should be treated as a terminal state and TransactionDeclined is the event to subscribe to for it. Delay rules also mean that a transaction may settle later than it otherwise would.

  • New declined transaction status, with declined_reason and declined_at included in transaction responses and webhook payloads
  • New TransactionDeclined webhook event, sent when a rule declines a transaction
  • Declines happen before the transaction is added to the processing queue; the API response and webhook carry a standard decline message, and the detailed reason is kept internally
  • Declined transactions cannot be cancelled, paused, resumed or refunded; those requests return HTTP 403 with a decline-specific error message
  • No payout, clawback or reverse payout is created for a declined transaction
  • Fraud-related returns place the affected payer or payee on hold and send a PersonStatusChanged webhook event
  • GrailPay can configure additional rules for an individual vendor that add delays or decline transactions
  • Rules run either at transaction creation or asynchronously after the transaction is queued

GrailPay now supports standalone KYC verification for persons, independent of any merchant or business onboarding flow. A new API allows clients to verify individuals directly, with support for both GrailPay-managed and externally provided verification.

Previously, KYC verification was only available as part of the merchant onboarding process. With standalone Person KYC, clients who need to verify individuals outside of a business context—or ahead of onboarding—can now do so through a dedicated API. This provides greater flexibility in how and when identity verification is performed while maintaining consistent compliance tracking.

  • New API endpoint for verifying persons independently, without requiring a merchant or business association
  • Supports two verification methods: GrailPay-managed verification (via OneFootprint) or externally verified data provided by clients or partners
  • Intelligent duplicate detection using identity details such as TIN and personal information
  • KYC results are automatically shared with the Identity service for connected users
  • Compliance status updates are processed consistently, ensuring accurate tracking and reliable notifications with no disruption to existing integrations

GrailPay has made significant improvements to how payments are created and processed. The system now responds faster, handles errors more gracefully, and provides greater visibility into payment status—all without impacting the experience for end users or merchants.

Payment processing reliability is the foundation of any payments platform. These improvements ensure that payments move through the system more predictably, recover automatically from temporary failures, and provide clear audit trails for operations and support teams. For integration partners, faster API responses and better error messaging mean a smoother development experience.

  • Payment creation now returns an immediate response—processing is handled asynchronously in the background for a noticeably faster experience
  • Payments follow a clearer lifecycle: created → queued → processed, making it easier to track status at any point
  • Failed processing attempts are automatically retried in the next available window, with each attempt logged with a reason and timestamp
  • Processing limits are checked before submission—payments wait for the next window rather than failing outright
  • Stronger upfront validation ensures payer and payee are valid, active, compliant, and have the correct bank accounts before a payment is created
  • Cancelled or paused payments are handled correctly in the queue—cancelled payments will not proceed, and resumed payments pick up where they left off without duplicates
  • Updated API documentation with a full list of possible error messages and their meanings
  • Improved system logging and monitoring to reduce edge-case issues in production

This release resolves an issue that prevented clients from subscribing to the NocProcessed webhook event.

The NocProcessed event is essential for receiving real-time notifications when a Notification of Change (NOC) has been processed. This fix ensures that the event can be successfully registered during webhook setup.

  • Fixed an issue where the NocProcessed webhook event was rejected as invalid during registration despite being a supported event type

GrailPay now supports onboarding Beneficial Owners using an Individual Tax Identification Number (ITIN) in place of a traditional Social Security Number (SSN).

Not all beneficial owners have a Social Security Number. By accepting ITINs, GrailPay enables a broader range of legitimate business owners to complete onboarding and pass KYC verification— expanding access to the platform while maintaining compliance standards.

  • Beneficial Owners can now be onboarded using an ITIN (tax IDs in the 900–999 range)
  • ITIN values are validated against IRS formatting rules, with clear error messaging for invalid entries
  • Updated SSN validation messaging to accurately reflect accepted formats

Phase 2 of the KYB Compliance Refactor and Beneficial Owner Migration is now complete. Merchant compliance is no longer stored as a static flag—it is now dynamically computed based on the latest KYB result from verification providers and the KYC results of all associated Beneficial Owners. A new compliance_status object and ComplianceStatusChanged webhook event have been introduced to give you full visibility into a Merchant’s compliance posture.

With compliance status now computed in real time, approval decisions always reflect the most current verification data. This eliminates the risk of stale or outdated compliance states and ensures that only Merchants with approved KYB and fully verified Beneficial Owners can transact. The new compliance_status object consolidates KYB and KYC information into a single view, and the ComplianceStatusChanged webhook keeps you informed the moment anything changes.

  • Merchant compliance is now dynamically computed—a Merchant is approved only when KYB status is approved and all Beneficial Owners have approved KYC statuses
  • Merchants processed by third parties are recorded with a status of approved_externally
  • New compliance_status object added to V3 API Merchant responses and webhook payloads, showing the latest KYB status and KYC status of each Beneficial Owner
  • New ComplianceStatusChanged webhook event fires whenever KYB or KYC status changes — all clients must subscribe to this event
  • Updates to Merchant or Beneficial Owner data automatically retrigger compliance checks
  • All legacy compliance logic and deprecated approval handling have been removed

GrailPay now provides full merchant status management and compliance enforcement, giving you direct control over merchant activation and ensuring only active, compliant merchants can process transactions.

Managing merchant eligibility is essential for reducing risk and maintaining regulatory compliance. With dedicated activation and deactivation endpoints—combined with automatic compliance validation—you can confidently control which merchants are allowed to transact, with full transparency into status changes and block reasons.

  • New Activate and Deactivate Merchant API endpoints with optional deactivation reason support
  • Merchants have a clear active / inactive status, with deactivation reasons and timestamps recorded
  • Compliance enforcement ensures only merchants with an approved compliance status can process transactions
  • Transactions are blocked with clear error responses when a merchant is inactive or non-compliant
  • Both conditions—active status and approved compliance—must be met before a transaction is allowed

This release improves error messaging when attempting to delete a bank account that is not yet eligible for deletion.

Clear and actionable error messages help you understand why a request was rejected and what conditions must be met before proceeding—reducing confusion and support overhead.

  • Improved error messaging for bank account deletion requests when the account is not yet eligible for removal

Clawback APIs are now available in GrailPay V3, providing programmatic access to view and track clawbacks alongside your other financial resources.

Clawbacks are a critical part of payment operations, and until now lacked dedicated API support in V3. With these new endpoints, you can retrieve and monitor clawbacks with the same consistency and reliability you expect from the rest of the GrailPay API—streamlining reconciliation and reporting.

  • New V3 Clawback API endpoints for viewing and tracking clawbacks
  • Consistent resource structure aligned with other V3 financial APIs
  • Enables programmatic access for improved reconciliation and reporting workflows

The V3 Account Validation API now supports multiple versions of Account Intelligence, giving you the flexibility to choose between V1, V2, or V3 intelligence models when validating bank accounts and routing numbers.

Each version of Account Intelligence offers different levels of insight and decisioning capability. With version selection, you can adopt newer models at your own pace—leveraging enhanced risk signals and validation accuracy when you’re ready, while maintaining compatibility with existing integrations.

  • V3 Account Validation endpoint now accepts a version parameter for Account Intelligence
  • Choose between V1, V2, or V3 intelligence models per request
  • Newer model versions provide enhanced insights and improved validation accuracy
  • Full backward compatibility with existing validation workflows

GrailPay now automatically falls back from FedNow to Fast ACH (same-day) when a FedNow payout fails, ensuring funds are still delivered without delay.

FedNow payouts can occasionally fail due to network issues or recipient bank limitations. Rather than requiring manual intervention or leaving a payout in a failed state, the platform now automatically retries via Fast ACH—keeping your payment operations running smoothly and your vendors paid on time.

  • Automatic failover from FedNow to Fast ACH (same-day) for failed individual payouts
  • Ensures uninterrupted fund delivery without manual intervention
  • Failover is seamless and requires no action on your end

The Bank Link flow has been enhanced to ensure reliable OAuth redirection for mobile applications.

During bank linking, users are redirected to their bank’s OAuth flow to authorize account access. Previously, mobile applications could experience session loss after completing OAuth, interrupting the linking process. This fix ensures a seamless return to the Bank Link flow after authorization.

  • Improved OAuth redirect handling for mobile Bank Link sessions
  • Prevents session loss after OAuth completion, allowing the bank linking process to continue without interruption

Processor payouts exceeding $1,000,000 are now automatically split into multiple smaller payouts to ensure successful processing without hitting banking or partner-imposed limits.

Large processor payouts can fail or be rejected when they exceed thresholds set by banking partners. Automatic splitting removes this risk, ensuring high-value payouts process reliably without requiring manual intervention.

  • Processor payouts exceeding $1M are automatically divided into multiple payouts, each below the threshold
  • Applies to both ACH and FedNow processor payouts
  • Processing is seamless with no action required on your end

This release includes an update to the Swagger API documentation security schema.

Keeping our OpenAPI specification compliant with validation standards ensures a consistent and warning-free experience when testing authenticated endpoints through the Swagger UI.

  • Updated the Swagger security schema naming to comply with OpenAPI validation rules, eliminating documentation warnings

GrailPay now supports FedNow for processor payouts, along with new webhook events and a standardized modality response object to give you full visibility into how processor-level payouts are processed.

Processor payouts can involve high volumes of batched transactions, making transparency into their status and payment rail critical. These additions enable real-time tracking of processor payout lifecycles and provide clear insight into whether funds were sent via ACH or FedNow—improving reconciliation and confidence in your payout operations.

  • FedNow is now supported as a payment rail for processor payouts
  • New webhook events for processor payout lifecycle tracking:
  • ProcessorPayoutCreated
  • ProcessorPayoutCompleted
  • ProcessorPayoutFailed
  • A modality object is now included in batch payout responses, indicating the payment rail (ACH or FedNow) and processing speed
  • Historical payout records have been backfilled with modality data for full consistency

This release resolves issues with our Swagger API documentation that were causing validation failures.

Accurate and reliable API documentation is essential for a smooth integration experience. These fixes ensure the Swagger UI remains a dependable reference for building against the GrailPay API.

  • Resolved OpenAPI specification issues that were causing Swagger validation failures in production
  • API documentation now passes all validation checks, ensuring accuracy for developers and integrators using the Swagger UI

This release includes fixes to improve the developer experience when working with the GrailPay API.

These updates reduce friction when testing API endpoints and submitting data, helping you integrate more quickly and avoid common validation errors.

  • Fixed an issue where Swagger UI was not correctly passing the Authorization: Bearer header on authenticated requests — tokens entered in the Authorize section now work as expected
  • Improved phone number validation messaging to clearly indicate that values must contain exactly 10 digits without the +1 prefix or special characters

GrailPay now supports FedNow payouts, enabling instant, around-the-clock payout processing for eligible transactions. Clients approved for FedNow will automatically receive payouts via the FedNow network once their associated transaction debits have settled.

Traditional ACH payouts are limited to banking hours and standard processing windows. With FedNow support, your vendors can receive funds in real time—24 hours a day, 7 days a week—reducing settlement delays and improving cash flow for your payment operations.

  • Instant payouts via the FedNow network for enabled vendors
  • True 24/7 payout processing with no dependency on banking hours
  • Automatic routing ensures FedNow-eligible transactions are processed separately from standard ACH payouts

We’ve introduced three new Person statuses and a new webhook event to improve visibility into why a person may be placed on hold.

These additions provide clearer insight into hold reasons—whether related to sanctions or suspected fraud—so you can take appropriate action and maintain compliance. The new webhook event ensures real-time notification when a person’s status changes.

  • New person statuses:
  • ON_HOLD_SANCTIONS
  • ON_HOLD_FRAUD_PAYER
  • ON_HOLD_FRAUD_PAYEE
  • New PersonStatusChanged webhook event triggers whenever a person enters or exits one of these statuses
  • Enhances transparency and traceability for risk-related holds

We’ve added full transaction lifecycle management to the GrailPay API with three new V3 endpoints: Pause, Resume, and Cancel.

These new controls give vendors and processors more flexibility and control over transaction processing. Whether halting a transaction for compliance review or canceling a transfer in progress, this release adds powerful capabilities with complete auditability and real-time notifications.

Please view our updated Manage Transactions guide for full details on using these new endpoints and understanding their behavior.

  • New V3 endpoints for pausing, resuming, and canceling transactions
  • New transaction statuses: PAUSED and AWAITING_CANCELLATION, with full timestamp tracking
    • Pause halts the ACH processing for a transaction in progress
    • Resume re-initiates ACH or syncs with bank state depending on prior progress
    • Cancel either halts the transaction immediately or initiates a reverse payout if debit has been settled
  • Three new webhook events: TransactionPaused, TransactionResumed, and TransactionAwaitingCancellation

We’ve fixed an issue where the MerchantUpdated webhook event was not being triggered when a merchant transitioned to the IN_REVIEW state.

Merchants moving into review—either due to failed KYC or updates from Middesk—will now properly emit webhook notifications. This ensures platforms receive real-time updates and can accurately reflect onboarding status in their workflows.

  • Fixed bug preventing MerchantUpdated webhook from triggering on IN_REVIEW transitions
  • Webhooks now trigger on KYC failure when KYB status moves to IN_REVIEW
  • Middesk-originated IN_REVIEW changes also emit update notifications

No new features were released in this update.

We’ve made backend improvements to ensure data integrity and consistency across V3 listing endpoints, especially when handling relational data like linked bank accounts.

  • Fixed binding issues between collection objects and resource transformers
  • Ensured relational data (e.g., bank accounts) is preserved during transformation
  • Added safeguards to prevent data loss during response transformation

We’ve made several enhancements to the V3 API, including unified bank account data across key endpoints and a new onboarding flow for adding bank accounts to persons.

These updates give you greater visibility into linked bank accounts, improve onboarding flexibility, and enable support for additional payment rails like FedNow. You can now onboard and validate accounts via Plaid or manually—all with consistent structure and improved intelligence.

  • Unified Bank Account Objects: Bank account details are now included in all V3 listing and detail API responses for People, Merchants, and Businesses.
  • New V3 Bank Account Onboarding Endpoint: New v3 API endpoint for adding bank accounts with account intelligence of various versions. This includes:
    • Support for both Plaid-based and manual bank account onboarding
    • Comprehensive account validation including account holder name verification
    • Duplicate detection for manual accounts
  • Cleaner Timestamp Responses: Removed unused updated_at fields for a more streamlined response format.

We’ve added a new status field to all Person-related V3 API responses, including List, Fetch, Onboard, and Update, as well as the PersonCreated and PersonUpdated webhook event payloads.

You can now immediately see the current status of any user in your system. This makes it easier to confirm that a person is in a valid state to transact before initiating a transfer, helping reduce failed attempts and streamline your integration logic.

  • New status parameter added to V3 API responses for People (List, Fetch, Onboard, Update)
  • Included in webhook payloads for both person creation and updates
  • Improves visibility into user state and transactional readiness across the platform

We’ve added a new kyb_rejected_reason field to both the Merchant Create and Merchant Update API responses, as well as the corresponding MerchantCreated and MerchantUpdated webhook event payloads.

You can now see the specific reason a merchant’s KYB (Know Your Business) verification failed. This provides greater transparency and helps streamline your onboarding and support workflows.

  • New kyb_rejected_reason parameter added to API responses ( Onboard, Update, List, Fetch )
  • Included in webhook payloads for both merchant creation and updates
  • Ensures consistent, actionable KYB feedback across the API and webhooks
  • OpenAPI Documentation Updates: Fixed an issue with the Webhook Registration OpenAPI documentation to specify that the webhook_url field should be passed as an array to allow for multiple webhook URLs.
  • Optimized Business & Merchant Response Payloads:
    • Responses: Removed full Person objects from create and update responses
    • Relations Object: Responses now include a clean relations object containing only the Person UUID
  • OpenAPI Documentation Updates: Updated OpenAPI documentation for Business and Merchant onboarding and update endpoints to reflect the new relational data structure.
  • Vendor Object in Relations: Resolved an issue where the vendor object was incorrectly appearing in List Person and List Merchant API responses. The relations attribute now correctly returns only allowed UUID references, ensuring consistency across all V3 endpoints.
  • V3 API Response Standardization: All V3 APIs of List and Showing (Person, Business, and Merchant) now follow a unified response contract with consistent structure. Error responses are now standardized across all endpoints, providing clearer, more consumer-friendly messages with proper attribute naming in validation errors.
  • Enhanced Relational Data: We’ve introduced a new relations object across all V3 endpoints, making it easier to understand entity relationships:
    • Person responses now include related Business or Merchant UUIDs.
    • Business responses include the associated Person UUID.
    • Merchant responses include the associated Person UUID.
  • Webhook Enhancements: Updated Person and Merchant webhook responses to include the new relations object structure, providing cleaner, more relevant information for integrations.
  • Billing Improvements: Fixed filter inconsistencies in Billing Item and Summary endpoints, ensuring accurate and reliable query results across both endpoints with consistent behavior.

Maintained by EkLine