Bank account transaction and statement notifications
Overview
This table summarizes the key differences between the three sources of transaction information.
Transaction notifications | Intraday statements | End-of-day statements | |
---|---|---|---|
Timeliness | Real-time (< 1 minute) or near real-time (< 1 hour) | Multiple times a day (e.g. hourly) | Once a day |
Retrieve with /v1/transactions | Yes | Yes | Yes |
dataSource field | DBS: ICN , IDN Citibank: CAMT054 | DBS: CAMT052 | DBS: CAMT.053 Citibank: CAMT053 |
Number of webhooks | One per transaction | One or more per statement | One per statement |
Webhook event name | transactions.created | transactions.created | statements.created |
Webhook body | Single transaction under object field | Array of transactions under objects field | Statement 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
ordataSource=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.
- Implement a webhook handler for
transactions.created
events. - Each webhook message contains either exactly one transaction in the
object
field, or multiple transactions within an array in theobjects
field. - 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.
- Implement a webhook handler for
statements.created
events. - Each webhook message contains exactly one statement object in the
object
field corresponding to one EOD statement. - Use the statement object ID (e.g.
stmt_0FD6WQVHFM23Q
) to retrieve transactions in the EOD statement via the /v1/transactions API. Use thedataSource=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.
- New: Ensure that your code is able to handle a
dataSource
field with the new valueCAMT052
(for DBS intraday statements). - In the webhook handler for
transactions.created
event:- If the webhook body has an
object
field, process it as a single transaction in the same way as before. - New: If the webhook body has an
objects
field instead, iterate through the array and process each transaction object.
- If the webhook body has an
- In the webhook handler for
statements.created
event:- Retrieve all new transactions (not previously reported through notifications and intraday
statements) using:
GET /v1/transactions?statementId=stmt_...&dataSource=CAMT.053
- Optional: Retrieve the transactions previously processed in Step 2b using:
GET /v1/transactions?statementId=stmt_...&dataSource=CAMT052
- For each transaction, determine if it has already been successfully processed in Step 2b. Otherwise process it.
- This step can be removed once you are confident that Step 2b is correctly handling webhooks containing multiple transactions.
- Retrieve all new transactions (not previously reported through notifications and intraday
statements) using:
- Once the changes above are in place, contact Acme (support@tryacme.com) to enable intraday statements for your Acme API account.