Skip to content

Webhooks

FluxiQ delivers real-time event notifications to your application via webhooks.

Overview

EndpointMethodDescription
/api/v1/webhooksPOSTRegister a webhook endpoint
/api/v1/webhooksGETList webhook endpoints
/api/v1/webhooks/:idGETGet webhook details
/api/v1/webhooks/:idDELETEDelete a webhook
/api/v1/webhooks/:id/testPOSTSend a test event

Register a Webhook

http
POST /api/v1/webhooks
Authorization: Bearer {token}
Content-Type: application/json

{
  "url": "https://your-app.com/webhooks/fluxiq",
  "events": ["pix.charge.paid", "pix.payout.confirmed", "pix.payout.failed"],
  "secret": "whsec_your_webhook_secret_key"
}

Response:

json
{
  "data": {
    "id": "whk_01HQGX...",
    "url": "https://your-app.com/webhooks/fluxiq",
    "events": ["pix.charge.paid", "pix.payout.confirmed", "pix.payout.failed"],
    "status": "active",
    "created_at": "2026-02-03T12:00:00Z"
  }
}

Event Types

PIX Events

EventDescription
pix.charge.createdA new charge was created
pix.charge.paidA charge was paid
pix.charge.expiredA charge expired without payment
pix.charge.cancelledA charge was cancelled
pix.payout.processingA payout is being processed
pix.payout.confirmedA payout was confirmed
pix.payout.failedA payout failed
pix.payout.returnedA payout was returned
pix.refund.requestedA refund was requested
pix.refund.completedA refund was completed

Account Events

EventDescription
account.createdA new account was created
account.updatedAccount details were updated
account.blockedAn account was blocked
transfer.completedAn internal transfer completed
transfer.failedAn internal transfer failed

Webhook Payload

All webhook deliveries follow this format:

json
{
  "id": "evt_01HQGX...",
  "type": "pix.charge.paid",
  "created_at": "2026-02-03T12:01:30Z",
  "data": {
    "id": "chg_01HQGX...",
    "status": "paid",
    "amount": 15000,
    "paid_amount": 15000,
    "end_to_end_id": "E1234567820260203120000000001",
    "payer": {
      "name": "Maria Silva",
      "document": "***456789**"
    },
    "paid_at": "2026-02-03T12:01:30Z"
  }
}

Signature Verification

Every webhook delivery includes a signature header:

http
X-FluxiQ-Signature: sha256=a1b2c3d4e5f6...
X-FluxiQ-Timestamp: 1706961600
X-FluxiQ-Event-Id: evt_01HQGX...

Verification Examples

JavaScript:

javascript
const crypto = require('crypto');

function verifyWebhook(payload, signature, timestamp, secret) {
  const signedContent = `${timestamp}.${payload}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedContent)
    .digest('hex');
  return `sha256=${expected}` === signature;
}

Elixir:

elixir
def verify_webhook(payload, signature, timestamp, secret) do
  signed_content = "#{timestamp}.#{payload}"
  expected = :crypto.mac(:hmac, :sha256, secret, signed_content)
             |> Base.encode16(case: :lower)
  "sha256=#{expected}" == signature
end

WARNING

Always verify webhook signatures before processing events. Reject any delivery with an invalid signature.

Retry Policy

Failed webhook deliveries are retried with exponential backoff:

AttemptDelayTotal Elapsed
1Immediate0s
230 seconds30s
32 minutes2.5 min
410 minutes12.5 min
530 minutes42.5 min
61 hour1h 42min
72 hours3h 42min
84 hours7h 42min

After 8 failed attempts, the event is marked as failed and no further retries are made.

Best Practices

  1. Respond quickly — Return a 200 status within 5 seconds. Process the event asynchronously.
  2. Handle duplicates — Use X-FluxiQ-Event-Id to deduplicate.
  3. Verify signatures — Always validate the X-FluxiQ-Signature header.
  4. Use HTTPS — Webhook URLs must use HTTPS in production.
  5. Monitor failures — Set up alerts for webhook delivery failures.

FluxiQ Core - PIX Payment Gateway