API ReferenceCoreWebhooks

Webhooks

Webhooks allow your application to receive real-time notifications about events that occur in your lomi. account.

Setting Up Webhooks

1. Create a Webhook Endpoint

const webhook = await lomi.webhooks.create({
  url: "https://example.com/webhooks",
  authorized_events: ["TRANSACTION_COMPLETED", "REFUND_COMPLETED"],
  metadata: { environment: "production" }
});

2. Verify Webhook Signatures

import { verifyWebhookSignature } from '@lomi/sdk';
 
app.post('/webhooks', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-lomi-signature'];
  
  try {
    const event = verifyWebhookSignature(
      req.body,
      signature,
      webhookSecret
    );
    handleWebhookEvent(event);
    res.json({received: true});
  } catch (err) {
    res.status(400).send('Webhook signature verification failed');
  }
});

Event Types

Transaction Events

EventDescription
TRANSACTION_CREATEDTransaction has been initiated
TRANSACTION_COMPLETEDPayment was successful
TRANSACTION_FAILEDPayment attempt failed
TRANSACTION_EXPIREDPayment session expired

Refund Events

EventDescription
REFUND_CREATEDRefund has been initiated
REFUND_COMPLETEDRefund was successful
REFUND_FAILEDRefund attempt failed

Subscription Events

EventDescription
SUBSCRIPTION_CREATEDNew subscription created
SUBSCRIPTION_UPDATEDSubscription details changed
SUBSCRIPTION_CANCELLEDSubscription was cancelled
SUBSCRIPTION_RENEWEDRecurring payment processed
SUBSCRIPTION_PAYMENT_FAILEDRecurring payment failed

Provider Events

EventDescription
PROVIDER_CONNECTEDNew provider connected
PROVIDER_DISCONNECTEDProvider disconnected
PROVIDER_CREDENTIALS_EXPIREDProvider credentials need renewal

Event Payloads

Transaction Completed

{
  "id": "evt_123",
  "type": "TRANSACTION_COMPLETED",
  "created_at": "2024-01-19T12:00:00Z",
  "data": {
    "transaction_id": "txn_123",
    "merchant_id": "merchant_123",
    "amount": 1000,
    "currency_code": "XOF",
    "status": "completed",
    "provider_code": "ORANGE",
    "payment_method_code": "MOBILE_MONEY"
  }
}

Subscription Renewed

{
  "id": "evt_124",
  "type": "SUBSCRIPTION_RENEWED",
  "created_at": "2024-01-19T12:00:00Z",
  "data": {
    "subscription_id": "sub_123",
    "plan_id": "plan_123",
    "customer_id": "cust_123",
    "transaction_id": "txn_124",
    "amount": 5000,
    "currency_code": "XOF",
    "next_billing_date": "2024-02-19T12:00:00Z"
  }
}

Best Practices

1. Implement Idempotency

app.post('/webhooks', async (req, res) => {
  const eventId = req.body.id;
  
  // Check if event was already processed
  if (await hasProcessedEvent(eventId)) {
    return res.json({received: true});
  }
  
  // Process the event
  await handleWebhookEvent(req.body);
  
  // Mark event as processed
  await markEventProcessed(eventId);
  
  res.json({received: true});
});

2. Handle Retries

app.post('/webhooks', async (req, res) => {
  try {
    await handleWebhookEvent(req.body);
    res.json({received: true});
  } catch (error) {
    // Return 5xx for retryable errors
    if (error.isRetryable) {
      res.status(500).json({error: 'Please retry'});
    } else {
      // Return 200 for non-retryable errors to prevent retries
      res.json({received: true});
    }
  }
});

3. Monitor Webhook Health

// Track failed deliveries
app.post('/webhooks', async (req, res) => {
  try {
    await handleWebhookEvent(req.body);
    await recordWebhookSuccess(req.body.id);
  } catch (error) {
    await recordWebhookFailure(req.body.id, error);
    throw error;
  }
});

Testing Webhooks

Using Test Events

// Create test webhook event
const testEvent = await lomi.webhooks.generateTestEvent({
  type: 'TRANSACTION_COMPLETED',
  data: {
    amount: 1000,
    currency_code: 'XOF'
  }
});

Local Development

We recommend using tools like ngrok for local webhook testing:

# Start ngrok
ngrok http 3000
 
# Update webhook URL
curl -X PATCH "https://api.lomi.africa/v1/webhooks/webhook_123" \
  -H "X-API-KEY: your_api_key" \
  -d '{"url": "https://your-ngrok-url/webhooks"}'

Webhook Logs

View webhook delivery attempts and responses in the Dashboard:

  • Delivery status
  • Response codes
  • Response bodies
  • Retry attempts
  • Timing information