Skip to content

Webhooks

Webhooks push new articles to your own endpoint as they are published. Instead of polling the API on a schedule, you register a destination URL once and APITube delivers matching articles to it automatically.

What is a webhook?

A webhook is a saved query with a destination. You give APITube:

  • a URL to deliver to, and
  • a set of filters — the same parameters as /v1/news/everything (language, category, source, sentiment, entities, dates, and more).

Whenever a newly indexed article matches those filters, APITube sends it to your URL with an HTTP POST.

Use cases:

  • Real-time monitoring for a brand, competitor, topic, or person
  • Breaking-news alerts into Slack, Telegram, or email
  • Feeding ingestion pipelines without a polling worker
  • Triggering automations (Zapier / Make / n8n) on matching coverage

Benefits:

  • Push delivery — no polling loop to build or run
  • Same filtering power as /v1/news/everything
  • Signed payloads (HMAC-SHA256) so you can verify authenticity
  • Automatic retries with exponential backoff
  • Full delivery logs in the dashboard

Creating a webhook

Webhooks are created and managed in the dashboard (Webhooks page):

  1. Click Create webhook.
  2. Choose the API key the deliveries are billed to.
  3. Enter the destination URL (HTTPS recommended — payloads contain article data).
  4. Build the filters with the same controls as the API Playground (leave empty to receive every new article).
  5. On creation you are shown the signing secret once — copy and store it. It is used to verify delivery signatures and is never shown again.

TIP

A brand-new webhook starts delivering from the most recent articles forward. Test against an api_test_ key first — test deliveries are masked and do not consume your quota.

Plan limits

The number of webhooks you can have is limited by your subscription plan (counted across your whole account):

PlanWebhooks
Free1
Basic5
Professional20
Corporate100

Delivery format

Each delivery is an HTTP POST to your URL:

http
POST https://your-app.example.com/webhook
Content-Type: application/json
X-Webhook-Signature: sha256=<hmac>
X-Webhook-Id: 42
X-Webhook-Timestamp: 1718800000
json
{
    "event": "articles.new",
    "webhook_id": 1,
    "delivered_at": "2026-06-19T12:00:00.000Z",
    "articles": [
        {
            "id": 3036291250,
            "title": "…",
            "source": { "domain": "reuters.com" }
        }
    ]
}

Each article in articles has the same shape as /v1/news/everything. Up to 100 articles are delivered per request.

HeaderDescription
X-Webhook-Signaturesha256=<hmac> — HMAC-SHA256 signature (see below)
X-Webhook-IdID of the delivery attempt
X-Webhook-TimestampUnix timestamp (seconds) when the delivery was sent

Respond with any 2xx status to acknowledge. A non-2xx response (or a timeout after 30 seconds) marks the delivery as failed and schedules a retry.

Verifying the signature

Every request is signed with HMAC-SHA256 over timestamp + "." + rawBody, using your webhook's signing secret. Verify it before trusting the payload.

javascript
import crypto from 'node:crypto';

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

app.post('/webhook', (req, res) => {
    const ok = verifyWebhook(
        process.env.WEBHOOK_SECRET,
        req.headers['x-webhook-signature'],
        req.headers['x-webhook-timestamp'],
        JSON.stringify(req.body),
    );
    if (!ok) return res.status(401).send('Invalid signature');

    const { articles } = req.body;
    console.log(`Received ${articles.length} articles`);
    res.status(200).send('OK');
});
python
import hmac
import hashlib

def verify_webhook(secret, signature, timestamp, raw_body):
    expected = hmac.new(
        secret.encode(),
        (timestamp + '.' + raw_body).encode(),
        hashlib.sha256,
    ).hexdigest()
    return signature == f'sha256={expected}'

Retries & statuses

If a delivery fails, APITube retries it with exponential backoff:

AttemptDelay
11 minute
25 minutes
330 minutes
42 hours
512 hours

After 5 failed attempts the delivery is marked failed. After several consecutive failed deliveries the webhook is automatically disabled — re-enable it from the dashboard once your endpoint is healthy.

A webhook subscription has one of three statuses:

StatusMeaning
activeDelivering matching articles
pausedPaused by you — no deliveries until resumed
disabledAuto-disabled after repeated delivery failures

You can review every delivery (status, attempts, response code, error) in the dashboard, and re-send a delivery manually.

Managing webhooks via the API

Existing webhooks can be inspected and managed programmatically (creation is done in the dashboard, where plan limits are enforced). Authenticate with X-API-Key.

bash
# List your webhooks
curl -H "X-API-Key: YOUR_API_KEY" https://api.apitube.io/v1/webhooks

# Get one
curl -H "X-API-Key: YOUR_API_KEY" https://api.apitube.io/v1/webhooks/1

# Update url / filters / status (active | paused)
curl -X PATCH -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"status":"paused"}' https://api.apitube.io/v1/webhooks/1

# Delete
curl -X DELETE -H "X-API-Key: YOUR_API_KEY" https://api.apitube.io/v1/webhooks/1

The required scopes are webhooks:read (for GET) and webhooks:write (for PATCH / DELETE).

Billing

Creating or managing a webhook is free. Each delivered article costs 1 point (charged to the key the webhook was created with). Deliveries made with a test key are masked and not billed.