> ## Documentation Index
> Fetch the complete documentation index at: https://docs.postsider.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks: Get Notified When Posts Publish

> Volta sends webhook events to your URL when posts are published, fail, or change status. Verify payloads with HMAC SHA-256 signatures.

Volta webhooks let you trigger real-time actions in external systems the moment a publishing event occurs. When a post is published or fails to publish, Volta sends an HTTP POST request to the URL you configure — carrying a signed JSON payload describing what happened. Use webhooks to update a CMS, notify a Slack channel, sync a dashboard, or kick off any downstream automation.

## What triggers a webhook

Volta fires webhook events for the following publishing outcomes:

* **`post.published`** — the post was successfully published to the social platform
* **`post.failed`** — Volta attempted to publish the post but the platform returned an error

## Setting up a webhook

<Steps>
  <Step title="Go to Settings → Webhooks">
    In the dashboard, open **Settings** in the left sidebar, then click the **Webhooks** tab.
  </Step>

  <Step title="Enter your endpoint URL">
    Click **Add Webhook** and paste in the public HTTPS URL where you want Volta to send events — for example, `https://your-app.com/hooks/volta`. The URL must be publicly reachable from the internet.
  </Step>

  <Step title="Save the webhook">
    Click **Save**. Volta will start sending POST requests to your URL immediately when the next qualifying event occurs.
  </Step>
</Steps>

<Warning>
  Webhook URLs must be publicly reachable HTTPS endpoints. Volta blocks URLs pointing to `localhost`, private IP ranges (RFC 1918 addresses such as `192.168.x.x`, `10.x.x.x`, and `172.16–31.x.x`), and link-local addresses. Registering a local or internal URL will result in delivery failures.
</Warning>

## Webhook payload

Every webhook request is a `POST` with a `Content-Type: application/json` body. Here's an example payload for a published event:

```json theme={null}
{
  "event": "post.published",
  "postId": "abc123",
  "channelId": "ch_xyz",
  "publishedAt": "2025-01-15T10:00:00Z"
}
```

For a failed post the `event` field will be `post.failed` and a `reason` field may be present with additional context from the platform.

## Verifying webhook signatures

Every request Volta sends includes an `X-Postsider-Signature` header. Its value is `sha256=<hex>`, where the hex string is an HMAC-SHA256 digest of the raw request body, signed with your webhook secret. Always verify this signature before processing the payload.

Here's how to verify it using the official SDK:

```typescript theme={null}
import Postsider from '@postsider/node';

// In your webhook handler:
const signature = req.headers['x-postsider-signature'] as string;
const rawBody = JSON.stringify(req.body);
const secret = 'your-webhook-secret';

const isValid = Postsider.verifyWebhookSignature(signature, rawBody, secret);

if (!isValid) {
  // Reject the request — it didn't come from Volta
  res.status(401).send('Invalid signature');
  return;
}

// Safe to process the event
console.log('Verified event:', req.body.event);
```

If you prefer to verify manually without the SDK, compute `sha256=` followed by the hex-encoded `HMAC-SHA256(secret, rawBody)` and compare it to the header value using a constant-time comparison to prevent timing attacks.

<Note>
  Use `JSON.stringify(req.body)` only if your framework parses JSON automatically. If you have access to the raw request bytes, use those instead — parsing and re-serializing JSON can change byte ordering and break the signature check.
</Note>

## Retry behavior

If your endpoint returns a non-2xx HTTP status code or fails to respond within 10 seconds, Volta will retry the delivery automatically:

| Attempt   | Delay        |
| --------- | ------------ |
| 1st retry | \~30 seconds |
| 2nd retry | \~2 minutes  |
| 3rd retry | \~10 minutes |

After three failed retries the delivery is abandoned. Make your endpoint idempotent — Volta may deliver the same event more than once in failure scenarios, and you should handle duplicate events gracefully using the `postId` as a deduplication key.

## Security and SSRF protection

Volta validates every webhook URL before sending and blocks requests to:

* Private IP ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`)
* Loopback addresses (`127.0.0.1`, `::1`, `localhost`)
* Link-local addresses (`169.254.x.x`)
* Non-HTTP protocols (`file:`, `ftp:`, `data:`, `javascript:`)

This SSRF (Server-Side Request Forgery) protection ensures that a misconfigured or malicious webhook URL cannot be used to probe your internal network. Every registered webhook must be a publicly routable HTTPS endpoint.
