Quiltt Logo


Webhooks enable you to react to changes in our systems without having to poll for data.

Quiltt will notify your system in real-time when a specific event has occured. Example events are when a Connection is synced or enters an error state, or when an Account is is created or verified for payments.

Link to this section#How we use Webhooks

We provide multiple event types you can subscribe to. When relevant events occur, Quiltt will send a notification to the subscribed endpoint via HTTPS. The notification contains a JSON payload with the event types and the events that have occurred. This allows you to execute actions in your system based on changes in Quiltt.

Link to this section#How to manage Webhooks

You can manage your Webhooks in the Quiltt Dashboard, or via the API, using the /webhooks/subscriptions endpoint.

Link to this section#Event Types

Below are some of the events you can subscribe to::

profileAll Profile-related events.
profile.createdA Profile has been created.
connectionAll Connection-related events.
connection.synced.successfulA Connection has synced successfully.
connection.synced.errored.repairableA Connection has entered an error that must be resolved using the Reconnect flow
account.verifiedAn Account has been successfully verified and ACH numbers are now available via API.

Each event payload will return information about the relevant data model and associated Profile. For example, the connection.created event will include information about the created Connection, along with the associated Profile.

You can find the full list of event types and schemas in the Platform API Reference.

Link to this section#How to Subscribe to a Webhook via API

In addition to managing webhooks in the Dashboard, you can subscribe to events via API.


Requests must include the following HTTP headers:

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/quiltt_webhook",
  "eventTypes": ["connection.created"]

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"]

Successful responses will return a 201 HTTP response code.

Link to this section#How to Receive a Webhook

When subscribed events occur, Quiltt will send a POST request to your targetUrl, with a JSON payload.

Your endpoint should respond back with a 2xx HTTP response code to indicate that you've successfully processed the payload. In Production environments, Quiltt will retry sending the request several times until a 2xx response is received, using an exponential backoff between attempts. See Error Handling for more information on the retry behavior.

The JSON payload will contain the relevant data about the event(s) that triggered the webhook.

Link to this section#Webhook Payload

The webhook payload will include a list of eventTypes and a list of events.

environmentobjectrequiredInformation about the Environment.
eventTypesarray of stringsrequiredThe types of events included in the Payload.
eventsarray of objectsrequiredThe events included in this Payload.

Each event is structured as an object with an id, type, and a record object.

idstringrequiredThe ID of the Event.
typestringrequiredThe type of Event that occurred.
profileobjectThe Profile associated with the Event.
recordobjectThe record associated with the Event.

See an example of the JSON payload below:

  "environment": {
    "id": "env_12uGLpOocVGvQYY9sFsOC6",
    "mode": "PRODUCTION",
    "metadata": null
  "eventTypes": ["connection.synced.successful"],
  "events": [
      "id": "evt_12sDfIGkY96vVvNvTqNfn9",
      "type": "connection.synced.successful",
      "profile": {
        "id": "p_12uGLpPexyTkZCcJJntSjb",
        "uuid": "018a72f8-5434-7262-a029-a186fb0c5f33",
        "metadata": null
      "record": {
        "id": "conn_12uGLpQUjSjdQqpIYoEVdQ",
        "status": "SYNCED",
        "metadata": null,
        "createdAt": "2023-09-08T04:06:32Z",
        "updatedAt": "2023-10-03T18:33:03Z"

Link to this section#Webhook Verification

Webhooks are provided with a timestamp and a HMAC256 Signature, with a per subscription key, to allow you to verify that each message is issued by Quiltt, is intended for you, is received unmodified, and is not being repeated.

To verify the message is valid:

  1. Ensure the Unix Epoch time Quiltt-Timestamp is current (within 5 minutes of current time in UTC)
  2. Validate Quiltt-Signature matches a Base64 encoded HMAC-SHA256 of version+timestamp+payload.
    • We are currently using version 1.

Link to this section#Sample Implementation

The following example shows how you could parse the received JSON payload and decide how to process the data of each event, based on its type. This example is using Ruby, but the logic will be similar in your language of choice.

require 'sinatra'
require 'json'

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

  # 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

  # 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")
      response = Net::HTTP.get_response(endpoint, Authorization: "Bearer #{ENV['QUILTT_API_KEY']}")
      puts "Unhandled event #{event['type']}"

  status 204

Link to this section#Error Handling

In the event of a failed delivery, webhooks will automatically retry up to 3 times per attempted delivery, followed by up to 25 times re-delivery attemps, with an exponential backoff between attempts. This is designed to handle both network delivery issues and service outages on the receiver's end.

Note that the re-delivery will only be attempted on PRODUCTION environments.

Link to this section#API Reference

See the Webhooks API Reference for full documentation of the subscription endpoint and the JSON payload we send to you.