Skip to main content

Bank account transaction and statement notifications

Overview

This table summarizes the key differences between the three sources of transaction information.

Transaction notificationsIntraday statementsEnd-of-day statements
TimelinessReal-time (< 1 minute) or near real-time (< 1 hour)Multiple times a day (e.g. hourly)Once a day
Retrieve with /v1/transactionsYesYesYes
dataSource fieldDBS: ICN, IDN
Citibank: CAMT054
DBS: CAMT052DBS: CAMT.053
Citibank: CAMT053
Number of webhooksOne per transactionOne or more per statementOne per statement
Webhook event nametransactions.createdtransactions.createdstatements.created
Webhook bodySingle transaction under object fieldArray of transactions under objects fieldStatement ID under object.id field.

Retrieve transactions with GET /v1/transactions

Transaction notifications

Your bank may provide real-time or near real-time transaction notifications when new transactions land in your bank accounts. If you are subscribed to transaction notifications, you can retrieve the transaction details with /v1/transactions. New transactions are available in our API immediately after Acme has received and processed the transaction notifications from your bank.

Transaction notifications are available for the following banks, and can be identified by the dataSource field. These transaction notifications may not cover all transaction types. Reach out to Acme for more details.

  • DBS: dataSource=ICN or dataSource=IDN
  • Citibank: dataSource=CAMT054

Retrieving transaction details

You can retrieve transaction details with /v1/transactions.

Request example:

GET /v1/transactions?order=DESC&limit=10

Response example:

{
"data": [
{
"id": "txn_0CQ8BSQEMZKBB",
"dataSource": "ICN",
"transactionType": "PAYNOW",
"bankReference": "20231011OCBCSGSGBRT1801732",
"description": "Invoice 123",
"customerReference": "Invoice 123",
"remittanceInformation": null,
"additionalInformation": null,
"amount": 4200,
"currency": "SGD",
"direction": "CREDIT",
"counterparty": {
"name": "John Doe",
"bank": "OCBCSGSGXXX",
"bankAccountNumber": ""
},
"bankAccount": {
"id": "intacc_0DW79C1K6Z2Y9",
"bank": "DBSSSGSGXXX",
"bankAccountNumber": "9876543210"
},
"virtualAccountNumber": null,
"transactionDate": "2023-06-19",
"statementId": null,
"createdAt": "2023-06-19T07:37:13.845549Z",
"updatedAt": "2023-06-19T07:37:13.845549Z"
}
],
"hasMore": false
}

Use the after query parameter with the last transaction ID to retrieve newer transactions, if there are any.

Request example:

GET /v1/transactions?order=DESC&limit=10&after=txn_0CQ8BSQEMZKBB

If a credit transaction was sent to a Virtual Account number that you own, the Virtual Account number will be set in the virtualAccountNumber field.

Response example:

{
"id": "txn_0CQ8BSQEMZKBB",
"bankAccount": {
"id": "intacc_0DW79C1K6Z2Y9",
"bank": "DBSSSGSGXXX",
"bankAccountNumber": "9876543210"
},
"virtualAccountNumber": "885123000456",
"...": "..."
}

Transaction webhooks

If you have registered a webhook endpoint with Acme, you will receive webhooks for these transactions with the event name transactions.created.

Webhook body example:

{
"id": "wbh_0DW0YCJGWHWH2",
"mode": "LIVE",
"event": "transactions.created",
"createdAt": "2023-10-11T08:41:56.673471Z",
"object": {
"id": "txn_0DW0Y1JXMJQR8",
"dataSource": "ICN",
"transactionType": "PAYNOW",
"bankReference": "20230911UOVBSGSGBRT3173409",
"description": "Invoice 123",
"customerReference": "Invoice 123",
"remittanceInformation": null,
"additionalInformation": null,
"amount": 2104,
"currency": "SGD",
"direction": "CREDIT",
"counterparty": {
"name": "John Doe",
"bank": "UOVBSGSGXXX",
"bankAccountNumber": ""
},
"bankAccount": {
"id": "intacc_0CSETTM8Y9SJ9",
"bank": "DBSSSGSGXXX",
"bankAccountNumber": "9876543210"
},
"virtualAccountNumber": null,
"transactionDate": "2023-10-11",
"statementId": null,
"createdAt": "2023-10-11T08:41:56.594852Z",
"updatedAt": "2023-10-11T08:41:56.594852Z"
}
}

Intraday statements

Your bank may provide intraday statements. These statements are available multiple times each day, and each intraday statement covers new transactions since the previous intraday statement.

If you are subscribed to intraday statements, Acme will send webhooks for the new transactions reported in the intraday statements. Transactions that have already arrived via transaction notifications will not be processed again. These transactions will also be available at /v1/transactions.

Intraday statements are available for the following banks, and can be identified by the dataSource field.

  • DBS: dataSourc=CAMT052

Intraday statements may contain a large number of transactions. Instead of a single transaction object in the webhook's object field, you will find one or more transaction objects under the objects field. Each webhook will contain up to 10 transactions (this limit is subjected to future changes). Hence you may receive multiple webhooks for each intraday statement that Acme processes.

Webhook body example:

{
"id": "wbh_0DW0YCJGWHWH2",
"mode": "LIVE",
"event": "transactions.created",
"createdAt": "2023-10-11T08:41:56.673471Z",
"objects": [
{
"id": "txn_0DW0Y1JXMJQR8",
"dataSource": "CAMT052",
"...": "..."
},
{
"id": "txn_0EH0Y1NX8J6R0",
"dataSource": "CAMT.052",
"...": "..."
}
]
}

End-of-day statements

End-of-day statements (EOD) from your bank cover all new transactions in your bank since the previous EOD statement. Each EOD statement typically covers one day's worth of transactions.

When Acme processes these EOD statements, only new transactions (not already received through transaction notification or intraday statements) will be ingested. EOD statements are available for the following banks, and can be identified by the dataSource field.

  • DBS: dataSourc=CAMT.053
  • Citibank: dataSource=CAMT053

Retrieving new transactions

New transactions from EOD statements can be retrieved at /v1/transactions. You can filter for them using the dataSource query parameter.

Request example:

GET /v1/transactions?dataSource=CAMT.053

Statement webhooks

If you have registered a webhook endpoint with Acme, you will receive a webhook with the event name statements.created for each of your accounts when its statement has been processed. EOD statements may contain a large number of transactions. Hence Acme does not send transactions.created webhooks for these transactions.

Webhook body example:

{
"id": "wbh_0DW112C6G4FWG",
"mode": "LIVE",
"event": "statements.created",
"createdAt": "2023-10-11T08:04:50.673471589Z",
"object": {
"id": "stmt_0DW113CKX3S0V",
"statementDate": "2023-10-10",
"type": "CAMT.053",
"bankAccount": {
"id": "intacc_0DW114DZWY7WJ",
"bank": "DBSSSGSGXXX",
"bankAccountNumber": "1234567890"
},
"createdAt": "2023-10-11T08:04:50.943436Z",
"updatedAt": "2023-10-11T08:04:50.943436Z"
}
}

In response to this webhook, you can retrieve all the transactions reported in this statement with /v1/transactions by filtering with the statementId query parameter. Specify the statement ID found in the object.id field of the webhook message.

Request:

GET /v1/transactions?statementId=stmt_0DW113CKX3S0V

The response will include transactions previously received through transactions notifications and intraday statements. To exclude them, use the filter dataSource=CAMT.053 for DBS or dataSource=CAMT053 for Citibank.

Request example:

GET /v1/transactions?statementId=stmt_0DW113CKX3S0V&dataSource=CAMT.053

Statements API

Use the /v1/statements API to look up the details of a statement.

Request example:

GET /v1/statements/stmt_0DW7JWV8A80EM

Response example:

{
"id": "stmt_0DW7JWV8A80EM",
"statementDate": "2023-10-11",
"type": "CAMT.053",
"bankAccount": {
"id": "intacc_0DW114DZWY7WJ",
"bank": "DBSSSGSGXXX",
"bankAccountNumber": "1234567890"
},
"createdAt": "2023-10-11T04:19:44.147038Z",
"updatedAt": "2023-10-11T04:19:44.147038Z"
}

You can retrieve the list of statements available to you with the /v1/statements API.

Request example:

GET /v1/statements?order=DESC&limit=10

Response example:

{
"data": [
{
"id": "stmt_0DW7JWV8A80EM",
"statementDate": "2023-10-11",
"type": "CAMT.053",
"bankAccount": {
"id": "intacc_0CNMTDA6BS8BC",
"bank": "DBSSSGSGXXX",
"bankAccountNumber": "1234567890"
},
"createdAt": "2023-10-11T04:19:44.147038Z",
"updatedAt": "2023-10-11T04:19:44.147038Z"
}
],
"hasMore": false
}

The statementDateSince and statementDateUntil query parameters can be used to narrow down the results.

Request example:

GET /v1/statements?statementDateSince=2023-09-15

Deduplication across different data sources

The same transaction may be reported multiple times. For example, once as a transaction notification, again in the next intraday statement, and finally in the EOD statement. The transaction will only show up once in /v1/transactions, and Acme will only send one transactions.created webhook for it.

Acme does this by identifying the same transactions across all data sources: transaction notifications, intraday statements, and EOD statements.

It is not uncommon for transactions in statements to be missing important fields (e.g. customer reference), or have certain fields altered (e.g. symbols may be replaced with spaces). In such scenarios we may fail to match them with previously received transactions, and consequently double-report them in /v1/transactions (as well as through webhooks). Please reach out to Acme at support@tryacme when you notice such duplicates, and we will improve the deduplication logic where possible.

Implementation guides

Combining multiple data sources

Transaction notifications and intraday statements

You will receive one transactions.created webhook message for each new transaction from your bank's transaction notifications.

If you are subscribed to intraday statements, you will also receive transactions.created webhooks for new transactions in the intraday statements. This excludes transactions already reported by transaction notifications.

  1. Implement a webhook handler for transactions.created events.
  2. Each webhook message contains either exactly one transaction in the object field, or multiple transactions within an array in the objects field.
  3. As webhooks are not guaranteed to be delivered once-and-only-once, use the transaction object IDs (e.g. txn_0FD6S8C7YD1H8) to detect duplicate webhooks.

End-of-day statements

When an end-of-day (EOD) statement has been processed by Acme, you will be notified by a statements.created webhook. Use the /v1/transactions API to retrieve new transactions from this EOD statement.

  1. Implement a webhook handler for statements.created events.
  2. Each webhook message contains exactly one statement object in the object field corresponding to one EOD statement.
  3. Use the statement object ID (e.g. stmt_0FD6WQVHFM23Q) to retrieve transactions in the EOD statement via the /v1/transactions API. Use the dataSource=CAMT.053 query parameter to exclude transactions already reported by transaction notifications and intraday statements.
    GET /v1/transactions?statementId=stmt_0FD6WQVHFM23Q&dataSource=CAMT.053&order=DESC&limit=10

Enabling intraday statements

If you are currently consuming only transaction notifications and EOD statements, and your bank has enabled intraday statements, you can start consuming intraday statements by following the strategy below.

  1. New: Ensure that your code is able to handle a dataSource field with the new value CAMT052 (for DBS intraday statements).
  2. In the webhook handler for transactions.created event:
    1. If the webhook body has an object field, process it as a single transaction in the same way as before.
    2. New: If the webhook body has an objects field instead, iterate through the array and process each transaction object.
  3. In the webhook handler for statements.created event:
    1. Retrieve all new transactions (not previously reported through notifications and intraday statements) using:
      GET /v1/transactions?statementId=stmt_...&dataSource=CAMT.053
    2. Optional: Retrieve the transactions previously processed in Step 2b using:
      GET /v1/transactions?statementId=stmt_...&dataSource=CAMT052
      1. For each transaction, determine if it has already been successfully processed in Step 2b. Otherwise process it.
      2. This step can be removed once you are confident that Step 2b is correctly handling webhooks containing multiple transactions.
  4. Once the changes above are in place, contact Acme (support@tryacme.com) to enable intraday statements for your Acme API account.