IntroductionAuthentication TestingPOST raw transactions (V1)EndpointBodyExample Request objectIdempotency/deduplicationGET raw transactions (V1)Constructing the requestEndpointBodyQuery parameters Example Request objectPaginationBest practicesResponse Example
Introduction
The Actuals raw transactions API provides a mechanism to send transactions directly to Actuals (from the source e.g. website or mobile app where the transaction is created). By doing this as real time as possible when the transaction is created, Actuals provides companies with an independent source of expectations that can be used to match transactions against from other sources.
The Actuals (REST) API allows for real-time transaction sending by extending a company’s IT infrastructure with a small script. This script should send transactions to the Actuals platform once they are definitive. It is recommended to do this asynchronously to avoid impacting the primary workflow. The Actuals API follows a Representational State Transfer (REST) architecture.
Authentication
API keys are used to authenticate and authorize API requests made by your application or backend systems. They're like secure passwords that identify your application to different systems.
The first thing you need is a administration. For an administration you can create a Production API key and a Test API key.
While building and testing your integration, use the Test API key and once you are ready to start processing real transactions, switch out your test key to the Live API key.
To authenticate your request add your API key as Request Header to the “token” parameter.
javascriptPOST 'https://api.actuals.io/v1/raw_transactions' \ --header 'token: ••••••' \
Testing
You can interact with the Actuals API in test and production mode, which allows safe experimentation without affecting production data or triggering real-world operations. The mode of your request. Test or production, is determined by the API key used for authentication.
You can easily identify which key you are using by the prefix of the API key:
test_for test mode
prod_for production mode
POST raw transactions (V1)
Endpoint
To create a new raw transaction inside the Actuals platform you perform a POST api call to the
raw_transactions endpoint. Each request must target a single resource. The Actuals API does not support bulk operations. javascriptPOST 'https://api.actuals.io/v1/raw_transactions'
Body
The body is semi structured. It contains a couple of standardized fields and an object field that can contain a custom json structure determined by the user of the API Endpoint.
Property | Mandatory | Description |
type | yes | the type of data that get’s shared. For example orders, invoices, payments. Each type can get their own processing logic. |
external_id | yes | a unique reference to this transaction. This id will be only processed once to the Actuals platform. |
timestamp | yes | the timestamp of this object in format ‘YYYY-MM-DDTHH24:MI:SSZ’ according to iso 8601 standard. |
object | yes | A json representation of the raw content you want to share. |
Example:
json{ "type": "order", "external_id": "123456", "timestamp": "2025-01-01T00:00:00Z", "object": { "my_custom_object_key1": "my_custom_object_value1", "my_custom_object_key2": "my_custom_object_value2" } }
Example Request object
jsoncurl --location 'https://api.actuals.io/v1/raw_transactions' \ --header 'Content-Type: application/json' \ --header 'token: ••••••' \ --data '{ "type": "order", "external_id": "123456", "timestamp": "2025-01-01T00:00:00Z", "object": { "my_custom_object_key1": "my_custom_object_value1", "my_custom_object_key2": "my_custom_object_value2" } }'
Idempotency/deduplication
When processing API calls we categorize the API calls into three different statuses:
- NEW
- IGNORED
- ERROR
Usually the platform is configured to only process NEW transactions. Others are not processed but kept for debugging purposes.
flowchart TD
subgraph database
ingest_record_new
ingest_record_ignored
ingest_record_error
end
received_api_call --> |upon succesful response| compare_external_id{compare external id}
compare_external_id --> |new| ingest_record_new
compare_external_id --> |existing| comparison_content{compare contents}
comparison_content --> |identical| ingest_record_ignored
comparison_content --> |different| ingest_record_error
GET raw transactions (V1)
To validate the number of transactions and which raw transactions that were received via the API Actuals the raw transactions GET endpoint can be used. It provides a self-service way to confirm data completeness during daily operations, month-end, year-end and audits.
Key capabilities:
- Query received transactions via GET
/api/v1/raw_transactions
- Filter results using business event timestamps (not ingestion time), aligning reconciliation with accounting periods, financial reporting, and audit expectations.
- Query any time range in any year, with a clearly enforced maximum window of 32 days per request
- Pagination to retrieve large result sets in a controlled and predictable way
- This endpoint doesn’t support concurrency. Limit the number of concurrent requests to 1.
- Transactions become available for validation within 4 hours after they have been posted.
Constructing the request
Endpoint
To retrieve the number of transactions and their id’s inside the Actuals platform you perform a GET api call to the raw_transactions endpoint.
javascriptGET 'https://api.actuals.io/v1/raw_transactions'
Body
Not Required.
Query parameters
Query Parameter | required | Description |
timestamp_gte | yes | Provide the start timestamp (greater than equal) that will be included in the response. Results will be filtered based on the timestamp provided in the POST call (not the Actuals ingestion timestamp).
Provide value in ISO 8601 standard (example “2025-01-30T23:59:59” ) |
timestamp_lt | yes | Provide the end timestamp (less than) for which the results will be included in the response. Results will be filtered based on the timestamp provided in the POST call (not the Actuals ingestion timestamp). Provide value in ISO 8601 standard (example “2025-01-30T23:59:59” ).
The maximum timeframe (time between timestamp_gte and timestamp_lt) for a single request is limited to 1 month. |
type | optional | When provided it will only return results for the type provided (see post endpoint type property). If not provided it will return results for all types. |
expand | optional | This property allows to return more information besides the count of transactions in the given timeframe. Default value is none. If set to none it will not return additional details.
If set to raw_transactions it will return the raw_transactions details (external_id, type and timestamp) |
limit | optional | Property used for pagination in combination with the expand parameter. The maximum value is 500. |
cursor | optional | Property used for pagination. When the total results are higher than the set limit. In the first response the cursor for the next page will be returned. When this custor will be provided as parameter the results will be returned for the next page. |
Example Request object
jsoncurl --location 'https://api.actuals.io/v1/raw_transactions?timestamp_gte=2025-01-01T00%3A00%3A00×tamp_lt=2025-01-02T00%3A00%3A00&limit=500&expand=raw_transactions' \ --header 'token: ••••••' \ }'
Pagination
The API endpoints use the so-called cursor pagination method. You can get the next page of objects by taken the
next_cursor value from the initial response body and provide it as cursor query parameter in you next request.Best practices
Actuals suggests to implement a periodic validation (for example daily) to verify the totals received by Actuals are in line with the customers database.
Use a CRON job once a day has completed to retrieve the totals received by Actuals. Compare these totals to your backend. If the total aligns validation is successful. If the total doesn’t align call the API once more now with the “expand” parameter set to raw_transactions. This returns the list of all external_id’s (see post endpoint) received by Actuals. Allowing you to identify on id level which transactions are missing. Allowing you to resend these specific events.
Consider data freshness: It can take up to 4 hours before transactions become available via the GET endpoint after the post request has been received. As a best practice we suggest to perform the validation for a period at least 4 hours after sending in the last request for the validation period.
Response Example
json{ "timestamp_gte": "2025-01-01T00:00:00", "timestamp_lt": "2025-01-02T00:00:00", "raw_transaction_count": 5, "limit":2, "next_cursor":"eyJ0cyI6IjIwMjUtMDEtMDFUMDM6MDU6NTIiL", "raw_transactions": [ { "external_id": "ORD-123", "type":"order", "timestamp": "2025-01-01T00:00:10" }, { "external_id": "INV-234", "type":"invoice", "timestamp": "2025-01-01T10:00:10" } ] }