Setup

Registering a webhook endpoint

You can accomplish that with the POST /data_api/webhooks endpoint.

In the payload you will need to provide:

  • callback_url: the URL that the events we’ll be POST’ed to
  • secret: the secret to use when generating a HMAC-SHA256 signature to sign the payload

Verifying webhook event with Qonto-SHA256-Signature

In order to verify that a webhook is coming from Qonto, you may compute the HMAC-SHA256 signature of the payload and compare it with the Qonto-SHA256-Signature header.

The secret_key below in the examples is the one configured in your created webhook subscription.

Sample code:

require 'openssl'
require 'json'

response_body_string = JSON.generate(
  {
    "id": "75341dcb-0376-474d-97d7-d2c03ff3973c",
    "event_type": "registrations.pending",
    "resource_type": "registration",
    "resource_id": "525817f7-93e8-4f31-a83d-20319778b4b0",
    "created_at": "2022-08-29T13:17:32Z"
  }
)

OpenSSL::HMAC.hexdigest("SHA256", "secret_key", response_body_string)
# => b0d249e653f1310fa5b7f26d5682548afa1799353b92fcafd4cacbd90312023e
import hashlib
import hmac
import json

response_body_string = json.dumps(
  {
    "id": "75341dcb-0376-474d-97d7-d2c03ff3973c",
    "event_type": "registrations.pending",
    "resource_type": "registration",
    "resource_id": "525817f7-93e8-4f31-a83d-20319778b4b0",
    "created_at": "2022-08-29T13:17:32Z"
  },
  separators=(',', ':')
)

hmac.new(
    key="secret_key".encode('utf-8'),
    msg=response_body_string.encode('utf-8'),
    digestmod=hashlib.sha256
).hexdigest()
# => b0d249e653f1310fa5b7f26d5682548afa1799353b92fcafd4cacbd90312023e

Retries

Qonto employs an exponential backoff strategy, retrying webhook delivery approximately 10 times over 2 days. If delivery fails within this period, the webhook is discarded.

Due to the retry mechanism, you may receive an older event after a newer one, so ensure your system handles this by checking the event_type to manage the event lifecycle properly.


Supported events

The events that are published depend on the flow in which the user is onboarded (company creation or existing company case).

Registration events

Those events will be fired during either flows (company creation / existing company) for the register:

  • registrations.pending: a new registration is created, and is now in pending status
  • registrations.user_started: user started the onboarding flow (login created or existing user logged in)
  • registrations.contract_signed: contract is signed = user has successfully processed payment
  • registrations.completed: Kbis was uploaded in Qonto & KYB is done. User now has an active bank account to use
  • organizations.deleted: an organization was deleted because the associated registration was reset in Qonto (only for company creation flow)

Company Creation / Capital Deposit events

Those events will be fired when the user will actually start and proceed for his capital deposit (after registrations.contract_signed and before registrations.completed)

  • registrations.submitted: registration is submitted = user is in the main app and ready to start capital deposit process
  • registrations.capital_deposit_activated: capital deposit is in progress (email was sent to shareholders to pay their shares and Qonto is waiting to receive the full capital deposit)
  • registrations.capital_deposit_request_signed: shareholders have all paid their shares, have reviewed the documentation to be sent to the notary, notary is preparing the certificate
  • registrations.capital_deposit_certificate_signed: deposit certificate is signed by the notary, sent to the user and available through API
  • registrations.capital_deposit_statement_ready: capital deposit statement is available through API

Whenever receiving a webhook event, the request body will not include the registration object.
If you need further information, you can fetch again the registration.

You will receive webhook events only for registrations with seamless flow type, since only these users will be onboarded through the fast track flow.