# Payment Webhooks (https://docs.tryacme.com/reference/webhooks-payments)

> For AI agents: the documentation index is at [llms.txt](https://docs.tryacme.com/llms.txt), with every page in one file at [llms-full.txt](https://docs.tryacme.com/llms-full.txt). Each page is also available as Markdown by appending `.md` to its URL.

Example webhook bodies for payments, batch payments, maker-checker approvals and refunds.

See [how to read the webhook examples](https://docs.tryacme.com/guides/webhook-examples). The values are made up, but every
field, its order and its format match what Acme sends.

## Payments [#payments]

Successful payment (`payments.succeeded`):

<CodeBlockTabs defaultValue="Singapore FAST">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="Singapore FAST">
      Singapore FAST
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Singapore PayNow">
      Singapore PayNow
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Telegraphic transfer">
      Telegraphic transfer
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Malaysia DuitNow">
      Malaysia DuitNow
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Hong Kong FPS">
      Hong Kong FPS
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="Singapore FAST">
    ```json
    {
      "id": "wbh_0RWF7FTX5Y711",
      "createdAt": "2026-10-08T02:11:46.917522108Z",
      "mode": "LIVE",
      "event": "payments.succeeded",
      "object": {
        "id": "pymt_0RWF7FTTNY6RR",
        "type": "FAST",
        "amount": 245000,
        "currency": "SGD",
        "customerReference": "INV-2026-10-0412",
        "senderAccountId": "intacc_0QK7M2D4XH1PZ",
        "receiver": {
          "name": "TAN WEI MING",
          "bank": "OCBCSGSGXXX",
          "bankAccountNumber": "5012846731"
        },
        "paymentDetails": "Invoice 0412 payment",
        "currencyExchange": {
          "fxContractId": null
        },
        "senderAccountCurrency": "SGD",
        "status": "COMPLETED",
        "resultCode": null,
        "bankReference": null,
        "bankReferences": {},
        "createdAt": "2026-10-08T02:11:40.318Z",
        "updatedAt": "2026-10-08T02:11:46.902Z"
      }
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Singapore PayNow">
    ```json
    {
      "id": "wbh_0RWF7FV65Y6JH",
      "createdAt": "2026-10-08T02:15:03.004118392Z",
      "mode": "LIVE",
      "event": "payments.succeeded",
      "object": {
        "id": "pymt_0RWF7FV5XY4PP",
        "type": "PAYNOW",
        "amount": 8800,
        "currency": "SGD",
        "customerReference": "REFUND-77120",
        "senderAccountId": "intacc_0QK7M2D4XH1PZ",
        "receiver": {
          "name": "LIM HUI LING",
          "proxyType": "MOBILE",
          "proxyValue": "+6591234567"
        },
        "paymentDetails": "Refund order 77120",
        "currencyExchange": {
          "fxContractId": null
        },
        "senderAccountCurrency": "SGD",
        "status": "COMPLETED",
        "resultCode": null,
        "bankReference": null,
        "bankReferences": {},
        "createdAt": "2026-10-08T02:14:58.771Z",
        "updatedAt": "2026-10-08T02:15:02.990Z"
      }
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Telegraphic transfer">
    ```json
    {
      "id": "wbh_0RWF7FV6NY5F6",
      "createdAt": "2026-10-08T09:47:31.660285914Z",
      "mode": "LIVE",
      "event": "payments.succeeded",
      "object": {
        "id": "pymt_0RWF7FV6DY5AE",
        "type": "TT",
        "amount": 1250000,
        "currency": "USD",
        "customerReference": "PO-2026-5521",
        "senderAccountId": "intacc_0QK7M2D4XH1PZ",
        "receiver": {
          "name": "SHENZHEN BRIGHT ELECTRONICS CO LTD",
          "bank": "CMBCCNBSXXX",
          "bankAccountNumber": "755912345610801",
          "intermediaryBank": "CITIUS33XXX",
          "address": {
            "line1": "Room 1203, Tower B, Keyuan Road",
            "line2": "Nanshan District",
            "city": "Shenzhen",
            "state": "Guangdong",
            "postalCode": "518057",
            "country": "CN"
          }
        },
        "bankChargeBearer": "SHARED",
        "instructionForSenderBank": "Please process urgently",
        "paymentDetails": "Payment for PO 5521",
        "currencyExchange": {
          "fxContractId": null
        },
        "senderAccountCurrency": "USD",
        "status": "COMPLETED",
        "resultCode": null,
        "bankReference": null,
        "bankReferences": {},
        "createdAt": "2026-10-08T01:05:22.640Z",
        "updatedAt": "2026-10-08T09:47:31.646Z"
      }
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Malaysia DuitNow">
    ```json
    {
      "id": "wbh_0RWF7FV89Y6N3",
      "createdAt": "2026-10-08T04:02:19.318804211Z",
      "mode": "LIVE",
      "event": "payments.succeeded",
      "object": {
        "id": "pymt_0RWF7FV7NY4R0",
        "type": "MY_DUITNOW",
        "amount": 32000,
        "currency": "MYR",
        "customerReference": "INV-MY-24017",
        "senderAccountId": "intacc_0QK7M2D4XH1PZ",
        "receiver": {
          "name": "AHMAD BIN HASSAN",
          "proxyType": "MOBILE",
          "proxyValue": "+60123456789"
        },
        "paymentDetails": "Invoice 24017",
        "currencyExchange": {
          "fxContractId": null
        },
        "senderAccountCurrency": "MYR",
        "status": "COMPLETED",
        "resultCode": null,
        "bankReference": "260810894262",
        "bankReferences": {
          "refNo": "260810894262"
        },
        "createdAt": "2026-10-08T04:02:11.208Z",
        "updatedAt": "2026-10-08T04:02:19.305Z"
      }
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Hong Kong FPS">
    ```json
    {
      "id": "wbh_0RWF7FV8HY56B",
      "createdAt": "2026-10-08T05:33:58.774120053Z",
      "mode": "LIVE",
      "event": "payments.succeeded",
      "object": {
        "id": "pymt_0RWF7FV8HY569",
        "type": "HK_FPS_PROXY",
        "amount": 156000,
        "currency": "HKD",
        "customerReference": "HK-INV-3391",
        "senderAccountId": "intacc_0QK7M2D4XH1PZ",
        "receiver": {
          "name": "CHAN TAI MAN",
          "proxyType": "FPS_ID",
          "proxyValue": "167382945",
          "address": {
            "city": "Hong Kong",
            "country": "HK"
          }
        },
        "bankChargeBearer": "SENDER",
        "paymentDetails": "Invoice 3391",
        "currencyExchange": {
          "fxContractId": null
        },
        "senderAccountCurrency": "HKD",
        "status": "COMPLETED",
        "resultCode": null,
        "bankReference": null,
        "bankReferences": {},
        "createdAt": "2026-10-08T05:33:51.027Z",
        "updatedAt": "2026-10-08T05:33:58.760Z"
      }
    }
    ```
  </CodeBlockTab>
</CodeBlockTabs>

These fields are left out when they have no value:

* In `receiver`: any field without a value, such as `bank` and `bankAccountNumber` for a proxy
  payment, or `proxyType` and `proxyValue` for an account payment
* `bankChargeBearer`, `instructionForSenderBank`, `underlyingErrorMessage` and `paymentAdviceEmails`
* `batchId` and `paymentDate`, for a payment that is not part of a batch
* `actualPaymentDate`, `bankChargeAmount` and `bankChargeCurrency`, which are sent for a payment in a
  batch once the bank reports them
* `review`, which is sent only with the four [maker-checker](#maker-checker-flow) events

Other details you sent when you created the payment, such as `purposeCode`, are also returned as
extra fields in the payment and in `receiver`.

`bankReference` and `bankReferences` are filled only when the bank returns a reference. The keys in
`bankReferences` are the bank's own field names.

Failed payment (`payments.failed`):

```json
{
  "id": "wbh_0RWF7FV9NY7AF",
  "createdAt": "2026-10-08T02:12:05.115370442Z",
  "mode": "LIVE",
  "event": "payments.failed",
  "object": {
    "id": "pymt_0RWF7FV9DY443",
    "type": "FAST",
    "amount": 245000,
    "currency": "SGD",
    "customerReference": "INV-2026-10-0413",
    "senderAccountId": "intacc_0QK7M2D4XH1PZ",
    "receiver": {
      "name": "TAN WEI MING",
      "bank": "OCBCSGSGXXX",
      "bankAccountNumber": "5012846739"
    },
    "paymentDetails": "Invoice 0413 payment",
    "currencyExchange": {
      "fxContractId": null
    },
    "senderAccountCurrency": "SGD",
    "status": "FAILED",
    "resultCode": "INVALID_ACCOUNT",
    "underlyingErrorMessage": "1010 Payer/payee account is incorrect",
    "bankReference": null,
    "bankReferences": {},
    "createdAt": "2026-10-08T02:11:58.404Z",
    "updatedAt": "2026-10-08T02:12:05.101Z"
  }
}
```

### Payments in a batch [#payments-in-a-batch]

Payments in a [batch](#batch-payments) are sent with `payments.succeeded` or `payments.failed`:

* They are sent when Acme processes the bank's acknowledgement file, with several payments under
  `objects`.
* One webhook carries up to 100 payments. A larger batch is split across several webhooks.
* The bank can confirm some payments before others. Each webhook then carries the payments confirmed
  so far, and the rest arrive in later webhooks.
* A webhook can also carry a single payment under `object`. Accept both `object` and `objects`.
* Process each payment on its own, by its `id`. Do not rely on its position in the array.

```json
{
  "id": "wbh_0RWF7FVA9Y6FQ",
  "createdAt": "2026-10-09T01:12:44.873519027Z",
  "mode": "LIVE",
  "event": "payments.succeeded",
  "objects": [
    {
      "id": "pymt_0RWF7FVA5Y52Q",
      "type": "GIRO",
      "amount": 420000,
      "currency": "SGD",
      "customerReference": "SAL-OCT26-0001",
      "senderAccountId": "intacc_0QK7M2D4XH1PZ",
      "receiver": {
        "name": "TAN WEI MING",
        "bank": "OCBCSGSGXXX",
        "bankAccountNumber": "5012846731"
      },
      "batchId": "bpmt_0QK7N8V2FB3RT",
      "paymentDate": "2026-10-09",
      "paymentDetails": "Salary Oct 2026",
      "currencyExchange": {
        "fxContractId": null
      },
      "senderAccountCurrency": "SGD",
      "status": "COMPLETED",
      "resultCode": null,
      "bankReference": null,
      "bankReferences": {},
      "createdAt": "2026-10-08T09:02:11.481Z",
      "updatedAt": "2026-10-09T01:12:44.861Z"
    },
    {
      "id": "pymt_0RWF7FVA5Y52S",
      "type": "GIRO",
      "amount": 385000,
      "currency": "SGD",
      "customerReference": "SAL-OCT26-0002",
      "senderAccountId": "intacc_0QK7M2D4XH1PZ",
      "receiver": {
        "name": "NUR AISYAH BINTE RAHMAN",
        "bank": "UOVBSGSGXXX",
        "bankAccountNumber": "3609127745"
      },
      "batchId": "bpmt_0QK7N8V2FB3RT",
      "paymentDate": "2026-10-09",
      "paymentDetails": "Salary Oct 2026",
      "currencyExchange": {
        "fxContractId": null
      },
      "senderAccountCurrency": "SGD",
      "status": "COMPLETED",
      "resultCode": null,
      "bankReference": null,
      "bankReferences": {},
      "createdAt": "2026-10-08T09:02:11.481Z",
      "updatedAt": "2026-10-09T01:12:44.861Z"
    }
  ]
}
```

### Maker-checker flow [#maker-checker-flow]

Payment waiting for approval (`payments.pending-approval`):

```json
{
  "id": "wbh_0RWF7FVB1Y5CA",
  "createdAt": "2026-10-08T03:41:28.376879315Z",
  "mode": "LIVE",
  "event": "payments.pending-approval",
  "object": {
    "id": "pymt_0RWF7FVAXY5ZZ",
    "type": "FAST",
    "amount": 1100000,
    "currency": "SGD",
    "customerReference": "INV-2026-0429",
    "senderAccountId": "intacc_0QK7M2D4XH1PZ",
    "receiver": {
      "name": "SUNRISE LOGISTICS PTE LTD",
      "bank": "DBSSSGSGXXX",
      "bankAccountNumber": "0039182746"
    },
    "paymentDetails": "Invoice 0429 payment",
    "currencyExchange": {
      "fxContractId": null
    },
    "senderAccountCurrency": "SGD",
    "status": "PENDING_APPROVAL",
    "resultCode": null,
    "bankReference": null,
    "bankReferences": {},
    "createdAt": "2026-10-08T03:41:26.929Z",
    "updatedAt": "2026-10-08T03:41:26.929Z",
    "review": {
      "requestedBy": "ak_finance_maker",
      "approvedAt": null,
      "approvedBy": null,
      "rejectedAt": null,
      "rejectedBy": null,
      "rejectionReason": null,
      "expiresAt": "2026-10-09T03:41:26.929745Z"
    }
  }
}
```

Payment approved (`payments.approved`). It carries the payment as it stands after Acme submits it to
the bank:

* `status` is usually `PROCESSING`. A `payments.succeeded` or `payments.failed` webhook follows when the
  bank settles the payment.
* When the bank answers at once, `status` can already be `COMPLETED` or `FAILED`. The
  `payments.succeeded` or `payments.failed` webhook can then arrive before this one.
* When Acme could not submit the payment, `status` can still be `PENDING_APPROVAL`.

```json
{
  "id": "wbh_0RWF7FVBNY6D4",
  "createdAt": "2026-10-08T04:12:55.110044791Z",
  "mode": "LIVE",
  "event": "payments.approved",
  "object": {
    "id": "pymt_0RWF7FVAXY5ZZ",
    "type": "FAST",
    "amount": 1100000,
    "currency": "SGD",
    "customerReference": "INV-2026-0429",
    "senderAccountId": "intacc_0QK7M2D4XH1PZ",
    "receiver": {
      "name": "SUNRISE LOGISTICS PTE LTD",
      "bank": "DBSSSGSGXXX",
      "bankAccountNumber": "0039182746"
    },
    "paymentDetails": "Invoice 0429 payment",
    "currencyExchange": {
      "fxContractId": null
    },
    "senderAccountCurrency": "SGD",
    "status": "PROCESSING",
    "resultCode": null,
    "bankReference": null,
    "bankReferences": {},
    "createdAt": "2026-10-08T03:41:26.929Z",
    "updatedAt": "2026-10-08T04:12:55.004Z",
    "review": {
      "requestedBy": "ak_finance_maker",
      "approvedAt": "2026-10-08T04:12:54.882011Z",
      "approvedBy": "Jane Lim",
      "rejectedAt": null,
      "rejectedBy": null,
      "rejectionReason": null,
      "expiresAt": "2026-10-09T03:41:26.929745Z"
    }
  }
}
```

Approval rejected (`payments.approval-rejected`):

```json
{
  "id": "wbh_0RWF7FVBSY56Q",
  "createdAt": "2026-10-08T04:30:12.554302178Z",
  "mode": "LIVE",
  "event": "payments.approval-rejected",
  "object": {
    "id": "pymt_0RWF7FVAXY5ZZ",
    "type": "FAST",
    "amount": 1100000,
    "currency": "SGD",
    "customerReference": "INV-2026-0429",
    "senderAccountId": "intacc_0QK7M2D4XH1PZ",
    "receiver": {
      "name": "SUNRISE LOGISTICS PTE LTD",
      "bank": "DBSSSGSGXXX",
      "bankAccountNumber": "0039182746"
    },
    "paymentDetails": "Invoice 0429 payment",
    "currencyExchange": {
      "fxContractId": null
    },
    "senderAccountCurrency": "SGD",
    "status": "APPROVAL_REJECTED",
    "resultCode": null,
    "bankReference": null,
    "bankReferences": {},
    "createdAt": "2026-10-08T03:41:26.929Z",
    "updatedAt": "2026-10-08T04:30:12.231Z",
    "review": {
      "requestedBy": "ak_finance_maker",
      "approvedAt": null,
      "approvedBy": null,
      "rejectedAt": "2026-10-08T04:30:12.231019Z",
      "rejectedBy": "Jane Lim",
      "rejectionReason": "Beneficiary not on approved vendor list",
      "expiresAt": "2026-10-09T03:41:26.929745Z"
    }
  }
}
```

Approval expired (`payments.approval-expired`):

```json
{
  "id": "wbh_0RWF7FVBXY6F9",
  "createdAt": "2026-10-09T03:41:30.001284507Z",
  "mode": "LIVE",
  "event": "payments.approval-expired",
  "object": {
    "id": "pymt_0RWF7FVAXY5ZZ",
    "type": "FAST",
    "amount": 1100000,
    "currency": "SGD",
    "customerReference": "INV-2026-0429",
    "senderAccountId": "intacc_0QK7M2D4XH1PZ",
    "receiver": {
      "name": "SUNRISE LOGISTICS PTE LTD",
      "bank": "DBSSSGSGXXX",
      "bankAccountNumber": "0039182746"
    },
    "paymentDetails": "Invoice 0429 payment",
    "currencyExchange": {
      "fxContractId": null
    },
    "senderAccountCurrency": "SGD",
    "status": "APPROVAL_EXPIRED",
    "resultCode": null,
    "bankReference": null,
    "bankReferences": {},
    "createdAt": "2026-10-08T03:41:26.929Z",
    "updatedAt": "2026-10-09T03:41:30.001Z",
    "review": {
      "requestedBy": "ak_finance_maker",
      "approvedAt": null,
      "approvedBy": null,
      "rejectedAt": null,
      "rejectedBy": null,
      "rejectionReason": null,
      "expiresAt": "2026-10-09T03:41:26.929745Z"
    }
  }
}
```

In `review`, `requestedBy`, `approvedBy` and `rejectedBy` say who took that step:

* For an API key, its name, or its ID when the key has no name.
* For a dashboard user, their name, or their email until they have set a name.

## Batch Payments [#batch-payments]

Batch payment submitted (`payment-batches.submitted`):

```json
{
  "id": "wbh_0RWF7FVP1Y763",
  "createdAt": "2026-10-08T09:05:37.218394502Z",
  "mode": "LIVE",
  "event": "payment-batches.submitted",
  "object": {
    "id": "bpmt_0QK7N8V2FB3RT",
    "type": "GIRO",
    "paymentDate": "2026-10-09",
    "senderAccountId": "intacc_0QK7M2D4XH1PZ",
    "senderAccountCurrency": "SGD",
    "currency": "SGD",
    "status": "SUBMITTED",
    "metadata": {
      "fileName": "UFF1_ROCKETSG01_20261008_0905.txt"
    },
    "createdAt": "2026-10-08T09:02:11.481Z",
    "updatedAt": "2026-10-08T09:05:37.206Z"
  }
}
```

Batch payment rejected (`payment-batches.rejected`). `underlyingErrorMessage` is the bank's reason:

```json
{
  "id": "wbh_0RWF7FVPSY5H8",
  "createdAt": "2026-10-08T09:21:03.790126518Z",
  "mode": "LIVE",
  "event": "payment-batches.rejected",
  "object": {
    "id": "bpmt_0QK7N8V2FB3RT",
    "type": "GIRO",
    "paymentDate": "2026-10-09",
    "senderAccountId": "intacc_0QK7M2D4XH1PZ",
    "senderAccountCurrency": "SGD",
    "currency": "SGD",
    "status": "FAILED",
    "underlyingErrorMessage": "ACK2007 Duplicate BatchId",
    "metadata": {
      "fileName": "UFF1_ROCKETSG01_20261008_0905.txt"
    },
    "createdAt": "2026-10-08T09:02:11.481Z",
    "updatedAt": "2026-10-08T09:21:03.774Z"
  }
}
```

## Refunds [#refunds]

Successful refund (`refunds.succeeded`):

```json
{
  "id": "wbh_0RWF7FVRSY4SH",
  "createdAt": "2026-10-08T09:50:25.426288002Z",
  "mode": "LIVE",
  "event": "refunds.succeeded",
  "object": {
    "id": "rfnd_0RWF7FVRHY6GG",
    "transactionId": "txn_0QK6ZB1R4T8WM",
    "amount": 1240,
    "currency": "SGD",
    "status": "SUCCEEDED",
    "resultCode": null,
    "createdAt": "2026-10-08T09:50:20.414Z",
    "updatedAt": "2026-10-08T09:50:25.421Z"
  }
}
```

Failed refund (`refunds.failed`):

```json
{
  "id": "wbh_0RWF7FVSNY74X",
  "createdAt": "2026-10-08T09:50:58.068242142Z",
  "mode": "LIVE",
  "event": "refunds.failed",
  "object": {
    "id": "rfnd_0RWF7FVSDY7D4",
    "transactionId": "txn_0QK6ZC7X2N5DE",
    "amount": 15000,
    "currency": "SGD",
    "status": "FAILED",
    "resultCode": "REQUESTED_REFUND_AMOUNT_EXCEEDS_REFUNDABLE_AMOUNT",
    "createdAt": "2026-10-08T09:50:53.053Z",
    "updatedAt": "2026-10-08T09:50:58.059Z"
  }
}
```
