IntroductionAuthentication TestingPOST raw transactions (V1)EndpointBodyExample Request objectIdempotency/deduplication
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 has 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