Create your Webhook Endpoint
The first thing you must do to use the Fintoc webhooks is to build your own webhook endpoint. Building a webhook endpoint is similar to building any endpoint for your application, but we think it's important to have a few considerations in mind before actually writing any code.
We also recommend that you read our guide about good practices for implementing webhooks.
Key considerations
For every event that happens on Fintoc, a JSON HTTP (POST) request will be sent to every registered webhook endpoint. From that request, you can parse the whole event detail using the JSON body.
Your webhook endpoint, then, must be able to receive POST request, handle the event information and then respond with any HTTP response code that belongs to the family of success codes (2XX).
Saving the received event
Every event sent by Fintoc as a webhook has a unique id
. It is important to at least save the id
corresponding to each event in your application's database. This way, you can ensure idempotency in the received events.
Returning 2XX quickly
To confirm that an event was successfully received, your application must respond with an 2XX HTTP status code. Any response with a status code other than that will be considered a failed attempt.
If Fintoc does not receive a 2XX status code, we will attempt to notify the event again. After multiple days and failed attempts, Fintoc will stop sending the event to that webhook endpoint.
It is very important that you respond with a 2XX status code as quickly as possible. Any complex logic on your application triggered by the reception of a webhook should be executed asynchronously. This way, we avoid notifying you multiple times about events that have already been received, but that failed to respond with a 2XX status code due to an HTTP timeout.
Testing the webhook
Due to notifications to the webhook endpoint occur only under specific circumstances, it is possible that some bugs of the reception of a webhook stay unnoticed until it's too late. That's why we always recommend that you test your endpoints when:
- Creating a webhook endpoint
- Registering a webhook endpoint
- Performing any change that can affect the reception of the webhook
Sample code
require 'json'
# Using Sinatra
post '/webhook' do
payload = request.body.read
event = nil
begin
event = JSON.parse(payload)
rescue JSON::ParserError => e
# Invalid payload
status 400
return
end
# idempotency using sinatra-activerecord
seen_event = WebhookEvent.find_by(fintoc_event_id: event['id'])
if seen_event
status 200
return
end
# save new event for idempotency
new_event = WebhookEvent.create!(
fintoc_event_id: event['id'],
type: event['type'],
data: event['data']
)
# Handle the event
case event['type']
when 'link.credentials_changed'
link_id = event['data']['id']
# Then define and call a method to handle the event.
when 'link.refresh_intent.succeeded'
link_id = event['data']['refreshed_object_id']
# Then define and call a method to handle the link refreshed event.
when 'account.refresh_intent.succeeded'
account_id = event['data']['refreshed_object_id']
# Then define and call a method to handle the account refreshed event.
# ... handle other event types
else
# Unexpected event type
puts "Unhandled event type: #{event.type}"
end
status 200
end
import json
import os
from flask import Flask, jsonify, request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
event = None
payload = request.data
try:
event = json.loads(payload)
except:
return jsonify(success=False)
# Add idempotency using the ORM being used by your app.
# Handle the event
if event and event['type'] == 'link.credentials_changed':
link_id = event['data']['id']
# Then define and call a method to handle the credentials changed event.
elif event and event['type'] == 'link.refresh_intent.succeeded':
link_id = event['data']['refreshed_object_id']
# Then define and call a method to handle the link refreshed event.
elif event and event['type'] == 'account.refresh_intent.succeeded':
account_id = event['data']['refreshed_object_id']
# Then define and call a method to handle the account refreshed event.
# ... handle other event types
else:
# Unexpected event type
print('Unhandled event type {}'.format(event['type']))
return jsonify(success=True)
// This example uses Express to receive webhooks
const app = require('express')();
// Use body-parser to retrieve the raw body as a buffer
const bodyParser = require('body-parser');
app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => {
const event = request.body;
// Add idempotency using the ORM being used by your app.
// Handle the event
switch (event.type) {
case 'link.credentials_changed':
const linkId = event.data.id;
// Then define and call a method to handle the ceredentilas changed event.
break;
case 'link.refresh_intent.succeeded':
const linkId = event.data.id;
// Then define and call a method to handle the link refreshed event.
break;
case 'account.refresh_intent.succeeded':
const accountId = event.data.id;
// Then define and call a method to handle the account refreshed event.
break;
// ... handle other event types
default:
// Unexpected event type
console.log(`Unhandled event type ${event.type}`);
}
// Return a response to acknowledge receipt of the event
response.json({received: true});
});
app.listen(8000, () => console.log('Running on port 8000'));
Updated about 2 months ago