Feature

Webhook Callbacks for Notification Delivery

Get real-time delivery status updates pushed directly to your server. Know instantly when a notification is delivered, fails, or gets retried -- and automate your response to each event.

Real-Time Delivery Events, Pushed to You

When you send a notification through the One-Ping REST API, the initial response tells you the message was accepted and queued. But what happens next? Did the Telegram message actually reach the user? Did the email bounce? Did the Slack webhook return an error?

One-Ping webhooks answer these questions in real time. Instead of polling the API or checking the dashboard manually, you register a callback URL and we push delivery events to your server as they happen. Your application stays in sync with the actual delivery status of every notification you send, across every channel.

This is essential for building reliable notification workflows where you need to know whether a message was delivered -- not just that it was sent. Update your database, notify your team, trigger follow-up actions, or escalate to an alternative channel, all automatically based on webhook events.

Available on Pro and Business plans. Webhooks are included with Pro ($9/mo) and Business ($29/mo) plans. Free tier users can monitor delivery status through the dashboard.

How Webhooks Work

The webhook flow is straightforward. When you send a notification, One-Ping processes it and dispatches to the requested channels. As each channel confirms delivery (or reports a failure), One-Ping sends an HTTP POST request to your registered callback URL with the event details.

Register your webhook URL

In your dashboard settings, add a webhook endpoint URL (e.g., https://yourapp.com/webhooks/one-ping). You can also pass a callback_url parameter on each API call to override the default.

Send notifications as usual

Use the POST /send endpoint to send your notifications. No changes to your existing integration are needed -- webhooks work alongside your current setup.

Receive delivery events

One-Ping sends HTTP POST requests to your webhook URL for each delivery event: success, failure, retry, and bounce. Each event includes the notification ID, channel, status, and timestamp.

Respond with 200 OK

Your endpoint should return a 200 status code to acknowledge receipt. If we do not receive a 200, we will retry the webhook delivery (see retry logic below).

Webhook Event Types

One-Ping sends different webhook events depending on what happens with your notification. Each event type is identified by the event field in the payload.

Event Description When It Fires
notification.delivered Notification was successfully delivered to the channel Channel confirms receipt
notification.failed Notification failed to deliver after all retry attempts All retries exhausted
notification.retrying A delivery attempt failed and a retry has been scheduled Before each retry attempt
notification.bounced Email notification bounced (invalid address or inbox full) Email provider reports bounce
notification.fallback Primary channel failed, message sent to a fallback channel Fallback channel is triggered

Webhook Payload Format

Every webhook event is delivered as an HTTP POST request with a JSON body. Here is the full payload structure with an example for a successful delivery.

Delivery Success Event

// POST to your webhook URL
{
  "event": "notification.delivered",
  "notification_id": "msg_a1b2c3d4e5",
  "channel": "telegram",
  "status": "delivered",
  "recipient": "@username",
  "delivered_at": "2025-01-15T10:30:05Z",
  "latency_ms": 245,
  "attempt": 1,
  "metadata": {
    "order_id": "ORD-5678"
  },
  "timestamp": "2025-01-15T10:30:05Z"
}

Delivery Failure Event

{
  "event": "notification.failed",
  "notification_id": "msg_a1b2c3d4e5",
  "channel": "email",
  "status": "failed",
  "recipient": "[email protected]",
  "error": {
    "code": "RECIPIENT_REJECTED",
    "message": "Mailbox not found"
  },
  "attempts": 3,
  "first_attempt_at": "2025-01-15T10:30:00Z",
  "last_attempt_at": "2025-01-15T10:35:00Z",
  "metadata": {},
  "timestamp": "2025-01-15T10:35:01Z"
}

Retry Event

{
  "event": "notification.retrying",
  "notification_id": "msg_a1b2c3d4e5",
  "channel": "slack",
  "status": "retrying",
  "attempt": 2,
  "max_attempts": 3,
  "next_retry_at": "2025-01-15T10:32:00Z",
  "error": {
    "code": "TIMEOUT",
    "message": "Channel did not respond within 10 seconds"
  },
  "timestamp": "2025-01-15T10:31:00Z"
}

Security: Signature Verification

Every webhook request from One-Ping includes a cryptographic signature so you can verify that the request genuinely came from us and was not tampered with in transit. You should always verify webhook signatures in production to prevent spoofed events from affecting your application.

How Signature Verification Works

One-Ping signs each webhook payload using HMAC-SHA256 with your webhook secret key. The signature is included in the X-OnePing-Signature header. To verify the signature, compute the HMAC-SHA256 hash of the raw request body using your secret and compare it with the header value.

// Webhook headers sent by One-Ping
X-OnePing-Signature: sha256=a1b2c3d4e5f6...
X-OnePing-Timestamp: 1705312200
Content-Type: application/json

Verification Example (Node.js)

const crypto = require('crypto');

function verifyWebhook(req, secret) {
  const signature = req.headers['x-oneping-signature'];
  const timestamp = req.headers['x-oneping-timestamp'];

  // Reject requests older than 5 minutes to prevent replay attacks
  const age = Math.abs(Date.now() / 1000 - parseInt(timestamp));
  if (age > 300) return false;

  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(timestamp + '.' + JSON.stringify(req.body))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Verification Example (Python)

import hmac
import hashlib
import time
import json

def verify_webhook(headers, body, secret):
    signature = headers.get('X-OnePing-Signature')
    timestamp = headers.get('X-OnePing-Timestamp')

    # Reject requests older than 5 minutes
    if abs(time.time() - int(timestamp)) > 300:
        return False

    payload = f"{timestamp}.{json.dumps(body)}"
    expected = 'sha256=' + hmac.new(
        secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

Security tip: Always use timing-safe comparison functions when verifying signatures. Standard string comparison (=== or ==) can leak information through timing differences, making your endpoint vulnerable to timing attacks.

Use Cases for Webhooks

Webhooks unlock powerful automation capabilities on top of your notification workflow. Here are the most common patterns our users build with webhook callbacks.

Update Your Database

When a notification is delivered, update the corresponding record in your database. Mark an order as "customer notified" or log the delivery timestamp for compliance and audit trails.

Trigger Follow-Up Actions

Chain notifications together. When a Telegram message is delivered, trigger a follow-up email with additional details. Build multi-step notification sequences.

Escalate on Failure

If a notification fails on all channels, alert your support team via Slack or create an incident in your issue tracker. Never let a critical notification silently disappear.

Analytics and Reporting

Feed webhook events into your own analytics pipeline to build custom dashboards, calculate delivery SLAs, and generate reports beyond what the One-Ping dashboard provides.

Sync with CRM

Update customer records in your CRM when notifications are delivered. Track which customers have been reached and through which channels for better customer communication history.

Billing and Metering

Use delivery confirmation events to track your actual notification usage for internal billing, cost allocation, or usage reporting across different teams or projects.

Webhook Delivery Retry Logic

We understand that your server might not always be available to receive webhooks. If your endpoint does not respond with a 200 status code, One-Ping retries the webhook delivery using exponential backoff.

Attempt Delay After Failure Total Time Elapsed
1st retry 30 seconds 30 seconds
2nd retry 2 minutes 2.5 minutes
3rd retry 10 minutes 12.5 minutes
4th retry 30 minutes 42.5 minutes
5th retry (final) 1 hour ~1 hour 42 minutes

After 5 failed attempts, the webhook event is marked as failed and logged in your dashboard. You can manually re-trigger any failed webhook from the dashboard if needed.

Testing webhooks locally? Use a tunneling tool like ngrok or localtunnel to expose your local development server to the internet. This lets you receive real webhook events while developing and testing your handler.

Best Practices

Ready to simplify your notifications?

Start free with 100 messages/month. No credit card required.

Get started free