Webhooks
Webhooks allow you to receive real-time notifications when events occur in your Outstand account. Instead of polling our API for updates, webhooks push data to your endpoint as soon as something happens.
Overview
When you configure a webhook endpoint, Outstand will send an HTTP POST request to your specified URL whenever a subscribed event occurs. This enables you to:
- Get instant notifications when posts are published successfully
- Be alerted immediately when publishing errors occur
- Build automated workflows based on Outstand events
- Integrate with your existing systems and dashboards
Setting Up Webhooks
Creating a Webhook Endpoint
- Navigate to Settings in the Outstand web application
- Click on Webhooks in the sidebar
- Click the Add Webhook button
- Fill in the webhook configuration form:
| Field | Description | Required |
|---|---|---|
| Name | A friendly name to identify this webhook (e.g., "Production Notifications") | Yes |
| Endpoint URL | The HTTPS URL where Outstand will send webhook payloads | Yes |
| Signing Secret | A secret key used to sign payloads with HMAC-SHA256 | No |
| Custom Headers | Additional HTTP headers to include in webhook requests | No |
| Events | Which events should trigger this webhook | Yes |
- Select the events you want to subscribe to
- Click Create to save the webhook
Managing Webhooks
From the Webhooks settings page, you can:
- Enable/Disable a webhook using the toggle switch
- Edit a webhook's configuration by clicking the Edit button
- Test a webhook to verify your endpoint is working
- Delete a webhook when it's no longer needed
Available Events
| Event | Description |
|---|---|
post.published | Triggered when a post is successfully published to at least one social account |
post.error | Triggered when a post fails to publish to all targeted social accounts |
Webhook Payload Format
All webhook payloads are sent as JSON with the following structure:
Headers
Content-Type: application/json
User-Agent: Outstand-Webhooks/1.0
X-Outstand-Signature: sha256=<signature> (if signing secret is configured)Plus any custom headers you configured.
post.published Event
Sent when a post is successfully published to at least one social account.
{
"event": "post.published",
"timestamp": "2024-12-29T10:30:00.000Z",
"data": {
"postId": "9dyJS",
"orgId": "org_abc123",
"socialAccounts": [
{
"network": "threads",
"username": "@myaccount",
"platformPostId": "12345678901234567"
},
{
"network": "linkedin",
"username": "John Doe",
"platformPostId": "urn:li:share:7654321"
}
]
}
}post.error Event
Sent when a post fails to publish to all targeted social accounts.
{
"event": "post.error",
"timestamp": "2024-12-29T10:30:00.000Z",
"data": {
"postId": "9dyJS",
"orgId": "org_abc123",
"socialAccounts": [
{
"network": "threads",
"username": "@myaccount",
"error": "Rate limit exceeded. Please try again later."
},
{
"network": "instagram",
"username": "@myinsta",
"error": "Access token has expired"
}
]
}
}Verifying Webhook Signatures
If you configure a signing secret, Outstand will include an X-Outstand-Signature header with each request. This allows you to verify that the webhook came from Outstand and wasn't tampered with.
The signature is computed as an HMAC-SHA256 hash of the raw request body using your signing secret:
// Node.js example
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expectedSignature = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
// In your webhook handler
app.post('/webhook', (req, res) => {
const signature = req.headers['x-outstand-signature'];
const isValid = verifySignature(
JSON.stringify(req.body),
signature,
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process the webhook...
res.status(200).send('OK');
});# Python example
import hmac
import hashlib
def verify_signature(payload: str, signature: str, secret: str) -> bool:
expected = 'sha256=' + hmac.new(
secret.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# In your webhook handler
@app.route('/webhook', methods=['POST'])
def handle_webhook():
signature = request.headers.get('X-Outstand-Signature')
is_valid = verify_signature(
request.get_data(as_text=True),
signature,
os.environ['WEBHOOK_SECRET']
)
if not is_valid:
return 'Invalid signature', 401
# Process the webhook...
return 'OK', 200Delivery & Retries
Outstand provides a scalable and reliable delivery mechanism to deliver webhooks, which provides:
- Automatic retries: Failed deliveries are retried up to 5 times with exponential backoff
- Retry intervals: Starting at 10 seconds, increasing up to 5 minutes between attempts
- Timeout: Each delivery attempt has a 30-second timeout
Response Requirements
Your endpoint should:
- Return a
2xxstatus code (200-299) to acknowledge receipt - Respond within 30 seconds
- Be idempotent (handle duplicate deliveries gracefully)
If your endpoint returns a 4xx or 5xx status code, or times out, the delivery will be retried.
Best Practices
- Always verify signatures if you've configured a signing secret
- Respond quickly - do heavy processing asynchronously after acknowledging the webhook
- Handle duplicates - use the
postIdandtimestampto deduplicate if needed - Use HTTPS - webhook endpoints must use HTTPS for security
- Test your endpoint - use the Test button in the UI before going live
- Monitor failures - set up alerting for failed webhook deliveries on your end
Testing Webhooks
You can test your webhook configuration directly from the Outstand UI:
- Go to Settings → Webhooks
- Find the webhook you want to test
- Click the Test button
This will send a test payload to your endpoint:
{
"event": "test",
"timestamp": "2024-12-29T10:30:00.000Z",
"data": {
"message": "This is a test webhook from Outstand",
"endpointId": 123
}
}The test result will show you the HTTP status code returned by your endpoint.