Skip to main content

Webhooks

Introduction

For each widget you have configured, you may configure a number of webhooks. When there are updates to one of your user's Topper sessions, we will make a HTTP POST request to your configured URL to provide further information.

During the onboarding process you may provide us with webhook URLs, and the events you wish to receive for each one. We will then provide you with a public key for each URL, which you can use to securely verify the request was sent by Topper.

A webhook request will include the following data:

  • name: Name of the event type.
  • id: UUID of the event which will persist across retries, can be used as an idempotency key.
  • bootstrapTokenId: The jti claim of the bootstrap token used to initiate the session.
  • data: Payload of the event.

Events

Full information about the available events and their associated payloads can be found on the associated Flows page.

FlowEventTrigger
crypto_onramporder:crypto-onramp:committedUser placed an order.
crypto_onramporder:crypto-onramp:chargedUser has been charged for their order.
crypto_onramporder:crypto-onramp:completedUser's order has completed.
crypto_onramporder:crypto-onramp:failedUser's order has failed.
crypto_onramporder:crypto-onramp:refund:completedUser's order has been successfully refunded.

Verifying a request

To help you verify that a request has come from Topper, we include a X-Topper-JWS-Signature header with each request. This header is a JSON Web Signature (JWS) with detached content, meaning the payload portion of the token has been removed. This token can be verified using the public key provided when creating the webhook.

Here is a Node.js snippet to verify a signature using the jsonwebtoken package. Please note that the code below is for illustrative purposes only, and the integration should be adapted to your application.

import { createPublicKey } from 'node:crypto';
import { promisify } from 'node:util';
import jsonwebtoken from 'jsonwebtoken';

// Function that returns a webhook verifier to be reused across requests.
const createWebhookVerifier = jwk => {
const jwkObject = JSON.parse(jwk);
const publicKey = createPublicKey({ format: 'jwk', key: jwkObject });
const options = { algorithms: [jwkObject.alg] }

// Promisify the `jsonwebtoken.verify()` function to use async/await.
const verifyJwt = promisify(jsonwebtoken.verify);

return async (body, jws) => {
// Replace the payload portion of the JWS for verification.
const [header, , signature] = jws.split('.');
const payload = Buffer.from(body).toString('base64url');
const token = `${header}.${payload}.${signature}`;

// Verify the token.
try {
await verifyJwt(token, publicKey, options);
} catch (error) {
if (error instanceof jsonwebtoken.JsonWebTokenError) {
return false;
}

throw error;
}

return true;
};
};

// JWK public key example supplied by Topper.
const jwk = '{"x":"7-INQ150R-MCWlj5X_wyGLRIRYAA-o8NakJiUq7gOGg","y":"dM-GsyJvdDOuALE3l-U9lPL8V3gY_5BPjLH539yTdKU","alg":"ES256","crv":"P-256","kid":"15a5142e-c20f-466e-8132-234dbdae97e7","kty":"EC"}'
// Request body example.
const body = '{"foo":"bar"}';
// X-Topper-JWS-Signature request header example.
const jws = 'eyJhbGciOiJFUzI1NiJ9..2H0Ypm5sVzuSpgyZySdAJan05lYxctqhmO8btghFQQzkisvSlNvNWzQ1kqTPXTLP_dR4zQZrTsSsShAK51I4EQ';

// Example of verifying a webhook request.
const verifyWebhook = createWebhookVerifier(jwk);
const verified = await verifyWebhook(body, jws);

console.log('Verified:', verified);

Timeouts and failures

Requests are made with a 4 second timeout. If a request times out, or if we receive an error response code (408, 409, 429, or 5XX) in that period, the request will be retried several times with exponential backoff. The request will be retried up to 10 times over a period of approximately 3 hours.

IP whitelisting

The following is a list of IP addresses we will use to make webhook requests:

  • 35.188.196.183
  • 104.198.177.219
  • 104.154.232.87
  • 130.211.229.195
  • 104.198.221.24
  • 104.197.27.15
  • 35.194.9.154
  • 104.154.144.51
  • 104.197.210.12
  • 35.225.6.73