Quiltt Logo

Webhooks Setup

Link to this section#How to Subscribe to Events

The easiest way to manage Webhook subscriptions is in the Quiltt Dashboard. You can also interact with your Webhook subscriptions via API, using the /webhooks/subscriptions endpoint.

Link to this section#Subscribing in the Dashboard

  1. Log into the Quiltt Dashboard.
  2. Click on the Webhooks link within your Environment.
  3. Click on the Create Webhook Subscription button.

Link to this section#Subscribing via API

The following endpoint can be used to create a new Webhook subscription via API:

POSThttps://api.quiltt.io/v1/webhooks/subscriptions

The following HTTP headers must be provided:

Authorization: Bearer <API_SECRET_KEY>
Content-Type: application/json

Requests must include a JSON body with the name of your subscription, a list of eventTypes, and the targetUrl that should receive the webhooks.

{
  "name": "Connection Created",
  "targetUrl": "https://example.com/webhooks/quiltt",
  "eventTypes": ["connection.created"]
}

Link to this section#Example

Here is an example request that will create a subscription to account.verified events.

curl --request POST \
  --url 'https://api.quiltt.io/v1/webhooks/subscriptions' \
  --header 'Authorization: Bearer <API_SECRET_KEY>' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "name": "Account Verified",
    "targetUrl": "https://example.com/webhooks/quiltt",
    "eventTypes": ["account.verified", "connection.synced.successful"]
  }'

Successful responses will return a 201 HTTP response code along with the details of the created subscription.

{
  "id": "wh_14OYtCKXE7UeehJCdfPuV6e",
  "name": "ACME Webhook",
  "targetUrl": "https://example.com/webhooks/quiltt",
  "eventTypes": ["account.verified", "connection.synced.successful"],
  "createdAt": "2024-03-18T02:04:37Z",
  "updatedAt": "2024-03-18T02:04:37Z"
}

Link to this section#How to Handle Incoming Events

When a Webhook event is triggered, Quiltt will send a POST request to the targetUrl specified in the subscription. The request will include a JSON payload with the details of the event.

Link to this section#Examples

The following examples show how you could parse the received JSON payload and decide how to process the data of each event, based on its type.

require 'sinatra'
require 'json'

WEBHOOK_SECRET  = '<WEBHOOK_SUBSCRIPTION_SECRET>'
WEBHOOK_VERSION = 1
WEBHOOK_WINDOW  = 300 # Five minutes

# Using Sinatra
post '/quiltt_webhook' do

  # Ensure the Unix Epoch time 'Quiltt-Timestamp' is current (within 5 minutes)
  if (timestamp = request['Quiltt-Timestamp']) < (Time.now.to_i - WEBHOOK_WINDOW)
    halt 204
  end

  # Validate 'Quiltt-Signature' matches a Base64 encoded HMAC-SHA256 of version+timestamp+payload.
  payload   = request.body.read
  signature = OpenSSL::HMAC.base64digest(
    'SHA256', WEBHOOK_SECRET, "#{WEBHOOK_VERSION}#{timestamp}#{payload}"
  )

  # @note Abort if payload fails signature verification
  if request['Quiltt-Signature'] != signature
    halt 204
  end

  # Parse verified webhook payload
  webhook = JSON.parse(payload)

  # Handle each event
  webhook['events'].each do |event|
    case event['type']
    when 'connection.synced.successful' # Connection has synced successfully
      connection = event['record']

      puts "Connection with ID #{connection['id']} has synced successfully!"
      # Fetch the latest data on associated accounts or transactions
      # ...
    when 'account.verified' # Account has been verified for payment processing
      account    = event['record']
      account_id = account['id']
      puts "Account with ID #{account_id} is ready for payment processing!"

      # Fetch the ACH numbers to pass to your payment provider
      endpoint = URI("https://api.quiltt.io/v1/#{account_id}/ach_numbers")
      response = Net::HTTP.get_response(endpoint, Authorization: "Bearer #{ENV['QUILTT_API_KEY']}")
    else
      puts "Unhandled event #{event['type']}"
    end
  end

  status 204
end