Getting Started

Webhooks

Configuration and usage of Flow Payments webhooks

Webhook Configuration

Creating a Webhook

  1. Log in to your Flow Payments dashboard
  2. Navigate to APIWebhooks
  3. Click Add Webhook
  4. Configure your webhook:
    • URL: Your server endpoint that will receive notifications
    • Events: Select the events you want to receive
    • Signing Key: Automatically generated to secure your webhooks

!IMPORTANT Your webhook endpoint must be publicly accessible via HTTPS and respond with a 2xx status code to confirm receipt.

Event List

Flow Payments sends webhooks for the following events:

Invoice Events

EventDescription
invoice.createdA new invoice has been created
invoice.confirmedAn invoice has received its first blockchain confirmation
invoice.paidAn invoice has been successfully paid (sufficient confirmations)
invoice.expiredAn invoice has expired without being paid

Transaction Events

EventDescription
transaction.pendingA payment deposit has been detected on the blockchain
transaction.confirmedA payment deposit has received additional confirmations

Payout Events

EventDescription
payout.completedA payout has been successfully completed

Payload Structure

Each webhook sent contains the following information:

{
  "event": "invoice.paid",
  "data": {
    "id": 123,
    "external_id": "order_456",
    "amount_fiat": "100.00",
    "currency_fiat": "USD",
    "status": "paid",
    "asset": {
      "id": 1,
      "symbol": "BTC",
      "name": "Bitcoin",
      "chain": "bitcoin"
    },
    "address": {
      "address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
    },
    "created_at": "2024-12-04T16:30:00.000000Z",
    "expires_at": "2024-12-04T18:30:00.000000Z"
  }
}

Signature Verification

To ensure that webhooks actually come from Flow Payments, each webhook request includes an HMAC-SHA256 signature in the Signature header.

How to Verify the Signature

The signature is calculated using your signing key (provided when creating the webhook) and the request body.

Example in PHP

<?php

function verifyWebhookSignature($payload, $signature, $signingKey) {
    $computedSignature = hash_hmac('sha256', $payload, $signingKey);
    
    return hash_equals($computedSignature, $signature);
}

// In your webhook endpoint
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_SIGNATURE'] ?? '';
$signingKey = 'your_signing_key';

if (!verifyWebhookSignature($payload, $signature, $signingKey)) {
    http_response_code(401);
    die('Invalid signature');
}

// Process the webhook
$data = json_decode($payload, true);
// ...

Example in Node.js

const crypto = require('crypto');
const express = require('express');

const app = express();

app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['signature'];
  const signingKey = 'your_signing_key';
  
  const computedSignature = crypto
    .createHmac('sha256', signingKey)
    .update(req.body)
    .digest('hex');
  
  if (signature !== computedSignature) {
    return res.status(401).send('Invalid signature');
  }
  
  // Process the webhook
  const event = JSON.parse(req.body);
  console.log('Event:', event.event);
  
  res.status(200).send('OK');
});

!CAUTION Always verify the signature before processing a webhook. Never trust unverified data.

Retry Mechanism

If your endpoint does not respond with a 2xx status code, Flow Payments will attempt to resend the webhook according to the following schedule:

  1. Immediately
  2. After 1 minute
  3. After 5 minutes
  4. After 30 minutes
  5. After 2 hours
  6. After 6 hours

!NOTE After 6 failed attempts, the webhook will be marked as failed and will no longer be resent. You can view failed webhooks in your dashboard.

Best Practices

1. Respond Quickly

Your endpoint should respond quickly (< 5 seconds) with a 2xx code. If you need to perform long processing:

// Respond immediately
http_response_code(200);
echo 'OK';
fastcgi_finish_request(); // Close the connection

// Process the webhook asynchronously
processWebhookAsync($data);

2. Idempotency

Webhooks can be sent multiple times. Ensure your code is idempotent:

// Use a unique identifier to avoid double processing
$eventId = $data['data']['id'];
$eventType = $data['event'];

if (hasProcessedEvent($eventId, $eventType)) {
    return; // Already processed
}

processEvent($data);
markEventAsProcessed($eventId, $eventType);

3. Error Handling

Log all errors to facilitate debugging:

try {
    processWebhook($data);
} catch (Exception $e) {
    error_log("Webhook error: " . $e->getMessage());
    http_response_code(500);
}

4. Testing Webhooks

Use tools like webhook.site or ngrok to test your webhooks in development.

Debugging Webhooks

Webhook Logs

View webhook logs in your dashboard:

  • APIWebhooksLogs

You will find:

  • The triggered event
  • The sent payload
  • Your server's response
  • The status (success/failure)
  • Retry attempts

Resending a Webhook

You can manually resend a failed webhook from the dashboard:

  1. Access webhook logs
  2. Find the failed webhook
  3. Click Resend