Using webhooks
Webhooks
Our service provides a webhook mechanism, allowing an integrator to be notified of some business events. These events will be sent on a URL communicated by the integrator. This URL must be an https URL (mutual TLS can optionally be set up). The events will be sent with POST requests.
The events are serialized in json. The different fields are:
field | description |
---|---|
id | The unique id of the event. |
event_type | The type of event, among: UDPATED , CREATED , DELETED .The event type specifies what happened on the resource the event is related to. The only event type implemented for now is UPDATED . |
resource_type | The type of the resource this event is related to. The only value for now is CONNECTIONS . |
creation_date | Creation time of the event (timestamp in seconds). |
channel_definition_id | See below (A). |
resource | A representation of the resource this event is related to. See below (B). |
new_transactions | A boolean field specifying whether the synchronization brought new transactions. This field is specific to CONNECTIONS UPDATED events. |
(A) The channel_definition_id
field was added as part of the changes of our API v2.1, made to handle PSD2 APIs and REDIRECT
authentication. In API v2.1, a connection may have:
- a
REDIRECT
channel, allowing getting payment accounts through PSD2 APIs - and/or an
EMBEDDED
channel, allowing getting other accounts through scraping (savings accounts, loans, etc).
A webhook event will be fired everytime a channel synchronization finishes. So, we will possibly have
2 events for a single synchronization of a connection. The channel_definition_id
field is here to
specify which channel the event is related to.
(B) For connection resources (the only resource type implemented for now), the resource
field is very similar to connection resources returned by API endpoints 'GET /connections endpoint' or 'GET /connections/{connection_id}'.
The only difference is the presence of two additional fields:
field | description |
---|---|
account_count | An integer field specifying the number of accounts included in the connection. This is the number of accounts returned by 'GET /accounts?connectionid={connection_id}'. |
accounts | An array field, containing the accounts included in the connection, as they are returned by API endpoints 'GET /accounts' or 'GET /accounts/{connection_id}' . |
Important note
When a connection has more than 100 accounts:
- the
accounts
array field will be empty - the
account_count
field will contain the number of accounts included in the connection
It is up to the integrator to handle this specific case: API call(s) to 'get the whole account list' should be done (possibly several calls depending on pagination parameters). We strongly recommend not to hard code the 100 limit, which could change in the future. Having an account_count
greater than 0 with an empty list of accounts is the right way to detect this case.
(C) The connection_updated
field contains only one field, named new_transactions
. This field is a boolean field specifying whether the synchronization brought new transactions.
Here is a full example of event, for a connection with 2 accounts:
{
"id": "abc123456",
"event_type" : "UPDATED",
"resource_type" : "CONNECTIONS",
"creation_date": 1509955448,
"channel_definition_id" : "24601",
"resource" : {
"id" : "123",
"user_id" : "321",
"provider_id" : "246",
"name" : "Caisse d'Epargne",
"status" : "SUCCESS",
"creation_date" : 1286641695,
"auto_sync" : true,
"logo_url" : "https://static.oxlin.io/common/pictures/providers_logos/246.png",
"channels" : [
{
"channel_definition_id" : "24600",
"mode" : "EMBEDDED",
"status" : "SUCCESS",
"last_success_date" : 1607106094,
"last_end_date" : 1607106094,
"credentials" : [
{
"id" : "2460000",
"masked_value" : "*****1234"
}
],
"account_types" : [ "CHECKINGS", "SAVINGS", "LOAN", "CREDIT_CARD" ],
"channel_definition_unavailable" : false
},
{
"channel_definition_id" : "24601",
"mode" : "REDIRECT",
"expires" : 1609943012,
"status" : "SUCCESS",
"last_success_date" : 1607106070,
"last_end_date" : 1607106070,
"credentials" : [ ],
"account_types" : [ "CHECKINGS", "CREDIT_CARD" ],
"channel_definition_unavailable" : false
}
],
"owner" : {
"name" : "M JEAN DUPONT"
},
"consent_per_account" : false,
"account_count" : 2,
"accounts" : [
{
"id": "222",
"connection_id": "123",
"name": "Compte Courant",
"currency": "EUR",
"balance": 1234.56,
"balance_date": 1607353181,
"iban": "FR7612345678901234567890123",
"status": "ACTIVE",
"type": "CHECKINGS",
"creation_date": 1286641717,
"account_number": "12345678901",
"owner": {
"name": "Mr Jean Dupont"
},
"usage": "PERSONAL",
"last_channel_definition_id": "24601"
},
{
"id": "111",
"connection_id": "123",
"name": "Livret A",
"currency": "EUR",
"balance": 10000,
"balance_date": 1607310062,
"iban": "FR7609876543210987654321098",
"status": "SUCCESS",
"type": "SAVINGS",
"creation_date": 1286641717,
"account_number": "09876543210",
"owner": {
"name": "Mr Jean Dupont"
},
"usage": "PERSONAL",
"savings": {
"type": "LIVA",
"savings_type": "LIQUID",
"yield_rate": 0.5
},
"last_channel_definition_id": "24600"
}
]
},
"connection_updated" : {
"new_transactions" : true
}
}
And another full example of event, for a connection with 102 accounts:
{
"id": "abc123456",
"event_type" : "UPDATED",
"resource_type" : "CONNECTIONS",
"creation_date": 1509955448,
"channel_definition_id" : "24601",
"resource" : {
"id" : "123",
"user_id" : "321",
"provider_id" : "246",
"name" : "Caisse d'Epargne",
"status" : "SUCCESS",
"creation_date" : 1286641695,
"auto_sync" : true,
"logo_url" : "https://static.oxlin.io/common/pictures/providers_logos/246.png",
"channels" : [
{
"channel_definition_id" : "24600",
"mode" : "EMBEDDED",
"status" : "SUCCESS",
"last_success_date" : 1607106094,
"last_end_date" : 1607106094,
"credentials" : [
{
"id" : "2460000",
"masked_value" : "*****1234"
}
],
"account_types" : [ "CHECKINGS", "SAVINGS", "LOAN", "CREDIT_CARD" ],
"channel_definition_unavailable" : false
},
{
"channel_definition_id" : "24601",
"mode" : "REDIRECT",
"expires" : 1609943012,
"status" : "SUCCESS",
"last_success_date" : 1607106070,
"last_end_date" : 1607106070,
"credentials" : [ ],
"account_types" : [ "CHECKINGS", "CREDIT_CARD" ],
"channel_definition_unavailable" : false
}
],
"owner" : {
"name" : "M JEAN DUPONT"
},
"consent_per_account" : false,
"account_count" : 102,
"accounts" : [
]
},
"connection_updated" : {
"new_transactions" : true
}
}
Using webhooks to get new transactions
Webhooks can be used to get new transactions on the fly: every time a "connection updated" event
is received by the integrator, it can call the 'GET /transactions'
endpoint. The integrator can use the new_transactions
flag to know whether there are new
transactions to get.
This has to be done on a per account basis. For each account, the integrator must use the import date of the last transaction the integrator previously got for this account.
Since there is one "connection updated" event per channel, for each event, the integrator can get
the new transactions for the accounts currently attached to the channel of the event. The link
between an account and a channel is specified by the last_channel_definition_id
field in the
accounts (see 'GET /accounts endpoint').
Example:
`GET /transactions?account_id=abc123&start_import_date=1574767574`
Limitation
Our current webhook implementation does not provide any retry mechanism. If a "connection updated" event is not received properly by the integrator, it is currently lost. It is thus important not to rely on the webhooks only to get new transactions.