Skip to main content

Webhooks API

The Webhooks API allows you to receive real-time HTTP notifications when events occur in FireBackup. Configure webhook endpoints to integrate with external systems, trigger workflows, or send alerts.

Endpoints Overview​

MethodEndpointDescription
GET/webhooksList all webhooks
GET/webhooks/:idGet webhook details
POST/webhooksCreate webhook
PUT/webhooks/:idUpdate webhook
DELETE/webhooks/:idDelete webhook
PATCH/webhooks/:id/toggleEnable/disable webhook
POST/webhooks/:id/testTest webhook delivery

List Webhooks​

Get all webhooks for the organization.

GET /api/v1/webhooks
Authorization: Bearer YOUR_TOKEN
X-Organization-Id: YOUR_ORG_ID

Response:

{
"success": true,
"data": [
{
"id": "webhook_abc123",
"name": "Slack Backup Notifications",
"url": "https://hooks.slack.com/services/xxx/yyy/zzz",
"events": ["backup.completed", "backup.failed"],
"enabled": true,
"lastTriggeredAt": "2024-01-15T10:00:45Z",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-15T10:00:45Z"
},
{
"id": "webhook_def456",
"name": "PagerDuty Alerts",
"url": "https://events.pagerduty.com/v2/enqueue",
"events": ["backup.failed", "restore.failed"],
"enabled": true,
"lastTriggeredAt": null,
"createdAt": "2024-01-10T00:00:00Z",
"updatedAt": "2024-01-10T00:00:00Z"
}
]
}

Get Webhook​

Get details of a specific webhook.

GET /api/v1/webhooks/:id
Authorization: Bearer YOUR_TOKEN
X-Organization-Id: YOUR_ORG_ID

Response:

{
"success": true,
"data": {
"id": "webhook_abc123",
"name": "Slack Backup Notifications",
"url": "https://hooks.slack.com/services/xxx/yyy/zzz",
"events": ["backup.completed", "backup.failed"],
"secret": "••••••••",
"enabled": true,
"lastTriggeredAt": "2024-01-15T10:00:45Z",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-15T10:00:45Z"
}
}

Create Webhook​

Create a new webhook endpoint.

POST /api/v1/webhooks
Authorization: Bearer YOUR_TOKEN
X-Organization-Id: YOUR_ORG_ID
Content-Type: application/json

{
"name": "Slack Backup Notifications",
"url": "https://hooks.slack.com/services/xxx/yyy/zzz",
"events": ["backup.completed", "backup.failed"],
"secret": "my-webhook-secret",
"enabled": true
}

Request Body:

FieldTypeRequiredDefaultDescription
namestringYes-Webhook display name
urlstringYes-Endpoint URL to receive notifications
eventsarrayYes-Events to subscribe to
secretstringNo-Secret for HMAC signature verification
enabledbooleanNotrueEnable webhook

Response:

{
"success": true,
"data": {
"id": "webhook_xyz789",
"name": "Slack Backup Notifications",
"url": "https://hooks.slack.com/services/xxx/yyy/zzz",
"events": ["backup.completed", "backup.failed"],
"enabled": true,
"createdAt": "2024-01-15T11:00:00Z"
}
}

Update Webhook​

Update webhook settings.

PUT /api/v1/webhooks/:id
Authorization: Bearer YOUR_TOKEN
X-Organization-Id: YOUR_ORG_ID
Content-Type: application/json

{
"name": "Slack Notifications (Updated)",
"events": ["backup.completed", "backup.failed", "restore.completed"]
}

Request Body:

All fields are optional. Only provided fields are updated.

FieldTypeDescription
namestringWebhook display name
urlstringEndpoint URL
eventsarrayEvents to subscribe to
secretstringSecret for HMAC verification
enabledbooleanEnable/disable webhook

Response:

{
"success": true,
"data": {
"id": "webhook_abc123",
"name": "Slack Notifications (Updated)",
"events": ["backup.completed", "backup.failed", "restore.completed"],
"updatedAt": "2024-01-15T12:00:00Z"
}
}

Delete Webhook​

Delete a webhook.

DELETE /api/v1/webhooks/:id
Authorization: Bearer YOUR_TOKEN
X-Organization-Id: YOUR_ORG_ID

Response:

{
"success": true,
"message": "Webhook deleted successfully"
}

Toggle Webhook​

Enable or disable a webhook.

PATCH /api/v1/webhooks/:id/toggle
Authorization: Bearer YOUR_TOKEN
X-Organization-Id: YOUR_ORG_ID
Content-Type: application/json

{
"enabled": false
}

Request Body:

FieldTypeRequiredDescription
enabledbooleanYesEnable or disable webhook

Response:

{
"success": true,
"data": {
"id": "webhook_abc123",
"enabled": false,
"updatedAt": "2024-01-15T12:00:00Z"
}
}

Test Webhook​

Send a test payload to verify webhook configuration.

POST /api/v1/webhooks/:id/test
Authorization: Bearer YOUR_TOKEN
X-Organization-Id: YOUR_ORG_ID

Response:

{
"success": true,
"data": {
"webhookId": "webhook_abc123",
"webhookName": "Slack Backup Notifications",
"event": "backup.completed",
"url": "https://hooks.slack.com/services/xxx/yyy/zzz",
"success": true,
"statusCode": 200,
"duration": 245
}
}

Test Failure Response​

{
"success": true,
"data": {
"webhookId": "webhook_abc123",
"webhookName": "Slack Backup Notifications",
"event": "backup.completed",
"url": "https://hooks.slack.com/services/xxx/yyy/zzz",
"success": false,
"statusCode": 404,
"error": "Request failed with status code 404",
"duration": 150
}
}

Webhook Events​

Backup Events​

EventDescription
backup.startedBackup job started
backup.completedBackup completed successfully
backup.failedBackup failed

Restore Events​

EventDescription
restore.startedRestore job started
restore.completedRestore completed successfully
restore.failedRestore failed

Schedule Events​

EventDescription
schedule.createdSchedule was created
schedule.updatedSchedule was updated
schedule.deletedSchedule was deleted

Webhook Payload Format​

All webhook deliveries use the following payload format:

{
"event": "backup.completed",
"timestamp": "2024-01-15T10:00:45Z",
"data": {
// Event-specific data
}
}

Backup Events Payload​

{
"event": "backup.completed",
"timestamp": "2024-01-15T10:00:45Z",
"data": {
"backupId": "bkp_abc123",
"projectId": "proj_xyz789",
"projectName": "Production App",
"type": "full",
"status": "completed",
"documentsCount": 15000,
"collectionsCount": 12,
"originalSize": 45000000,
"compressedSize": 6200000,
"duration": 45,
"triggeredBy": "schedule",
"scheduleId": "sched_abc123",
"createdAt": "2024-01-15T10:00:00Z",
"completedAt": "2024-01-15T10:00:45Z"
}
}

Backup Failed Payload​

{
"event": "backup.failed",
"timestamp": "2024-01-15T10:00:45Z",
"data": {
"backupId": "bkp_abc123",
"projectId": "proj_xyz789",
"projectName": "Production App",
"type": "full",
"status": "failed",
"error": "Failed to connect to Firebase: Token expired",
"triggeredBy": "schedule",
"scheduleId": "sched_abc123",
"createdAt": "2024-01-15T10:00:00Z",
"failedAt": "2024-01-15T10:00:15Z"
}
}

Restore Events Payload​

{
"event": "restore.completed",
"timestamp": "2024-01-15T11:02:30Z",
"data": {
"restoreJobId": "restore_abc123",
"backupId": "bkp_xyz789",
"projectId": "proj_abc123",
"projectName": "Production App",
"targetProjectId": "proj_def456",
"targetProjectName": "Staging App",
"status": "completed",
"documentsRestored": 10000,
"collectionsRestored": 5,
"mergeMode": "overwrite",
"duration": 150,
"createdAt": "2024-01-15T11:00:00Z",
"completedAt": "2024-01-15T11:02:30Z"
}
}

Schedule Events Payload​

{
"event": "schedule.created",
"timestamp": "2024-01-15T11:00:00Z",
"data": {
"scheduleId": "sched_abc123",
"name": "Daily Production Backup",
"projectId": "proj_xyz789",
"projectName": "Production App",
"cronExpression": "0 2 * * *",
"timezone": "America/New_York",
"enabled": true,
"nextRunAt": "2024-01-16T07:00:00Z",
"createdBy": {
"id": "user_abc123",
"email": "admin@example.com"
}
}
}

Webhook Headers​

Each webhook request includes the following headers:

HeaderDescription
Content-Typeapplication/json
X-Webhook-EventEvent type (e.g., backup.completed)
X-Webhook-TimestampISO 8601 timestamp
X-Webhook-IdWebhook configuration ID
X-Webhook-SignatureHMAC-SHA256 signature (if secret configured)

Signature Verification​

When a secret is configured, FireBackup includes an HMAC-SHA256 signature to verify authenticity.

Signature Format​

X-Webhook-Signature: sha256=abc123def456...

Verification Example (Node.js)​

const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = 'sha256=' +
crypto.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');

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

// Express middleware example
app.post('/webhook', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const isValid = verifyWebhookSignature(req.body, signature, 'your-secret');

if (!isValid) {
return res.status(401).json({ error: 'Invalid signature' });
}

// Process webhook
console.log('Received event:', req.body.event);
res.status(200).json({ received: true });
});

Verification Example (Python)​

import hmac
import hashlib
import json

def verify_webhook_signature(payload, signature, secret):
expected_signature = 'sha256=' + hmac.new(
secret.encode(),
json.dumps(payload).encode(),
hashlib.sha256
).hexdigest()

return hmac.compare_digest(signature, expected_signature)

# Flask example
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-Webhook-Signature')
is_valid = verify_webhook_signature(
request.json,
signature,
'your-secret'
)

if not is_valid:
return {'error': 'Invalid signature'}, 401

# Process webhook
print(f"Received event: {request.json['event']}")
return {'received': True}, 200

Delivery Behavior​

Timeouts​

Webhook requests have a 30-second timeout. Ensure your endpoint responds quickly.

Retry Policy​

Currently, FireBackup does not retry failed webhook deliveries. Implement your own reliability by:

  1. Responding quickly (under 30 seconds)
  2. Processing webhooks asynchronously
  3. Returning 2xx status codes for successful receipt

Response Expectations​

Response CodeInterpretation
2xxSuccessful delivery
3xxRedirect (not followed)
4xxClient error (delivery failed)
5xxServer error (delivery failed)

Integration Examples​

Slack Integration​

{
"name": "Slack Notifications",
"url": "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX",
"events": ["backup.completed", "backup.failed"]
}

You'll need a middleware to transform FireBackup payloads to Slack format.

Discord Integration​

{
"name": "Discord Alerts",
"url": "https://discord.com/api/webhooks/000000000000000000/xxxx",
"events": ["backup.failed", "restore.failed"]
}

PagerDuty Integration​

{
"name": "PagerDuty Incidents",
"url": "https://events.pagerduty.com/v2/enqueue",
"events": ["backup.failed"]
}

Custom Endpoint​

{
"name": "Custom Backend",
"url": "https://api.yourcompany.com/firebackup-webhooks",
"events": ["backup.started", "backup.completed", "backup.failed"],
"secret": "your-secret-key-here"
}

Best Practices​

Security​

  1. Always use HTTPS - Never use HTTP URLs in production
  2. Configure secrets - Enable HMAC verification for all webhooks
  3. Validate signatures - Verify every incoming webhook
  4. Use short-lived tokens - If forwarding to other services

Performance​

  1. Respond quickly - Return 200 immediately, process async
  2. Handle duplicates - Implement idempotency
  3. Monitor failures - Track webhook delivery status

Reliability​

  1. Log payloads - Store received webhooks for debugging
  2. Queue processing - Use message queues for complex workflows
  3. Alert on failures - Monitor your webhook endpoints

Webhook Object​

FieldTypeDescription
idstringUnique webhook ID
namestringDisplay name
urlstringEndpoint URL
eventsarraySubscribed events
secretstringHMAC secret (masked)
enabledbooleanWhether webhook is active
lastTriggeredAtstringLast delivery timestamp
createdAtstringISO 8601 timestamp
updatedAtstringISO 8601 timestamp

Error Responses​

Webhook Not Found​

{
"success": false,
"error": {
"code": "WEBHOOK_NOT_FOUND",
"message": "Webhook not found"
}
}

Invalid URL​

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid URL format",
"details": {
"field": "url",
"reason": "Must be a valid HTTPS URL"
}
}
}

Invalid Events​

{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid event type",
"details": {
"field": "events",
"invalidValues": ["invalid.event"],
"allowedValues": [
"backup.started",
"backup.completed",
"backup.failed",
"restore.started",
"restore.completed",
"restore.failed",
"schedule.created",
"schedule.updated",
"schedule.deleted"
]
}
}
}

Delivery Failed​

{
"success": true,
"data": {
"webhookId": "webhook_abc123",
"success": false,
"error": "Connection timed out",
"duration": 30000
}
}