Webhooks
Receive real-time event notifications from VibeCaaS — set up endpoints, verify signatures, handle retries, and act on deployment and project events.
Webhooks
Webhooks deliver real-time notifications when events happen in VibeCaaS. Register an HTTPS endpoint and VibeCaaS sends it a POST request with event data — enabling automation, integrations, and custom workflows without polling the API.
Quick setup
1. Create an endpoint
Stand up an HTTP endpoint that accepts POST requests and returns 200 OK.
// Express.js
app.post("/webhooks/vibecaas", (req, res) => {
const event = req.body;
console.log("Event received:", event.type);
res.status(200).send("OK");
});2. Register the webhook
curl -X POST https://api.vibecaas.com/v1/webhooks \
-H "Authorization: Bearer vcs_sk_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/webhooks/vibecaas",
"events": ["deployment.succeeded", "deployment.failed"],
"secret": "whsec_abc123..."
}'3. Verify signatures
Always confirm a request actually came from VibeCaaS — see Webhook security below.
Available events
| Category | Events |
|---|---|
| Project | project.created, project.updated, project.deleted, project.transferred |
| Deployment | deployment.started, deployment.succeeded, deployment.failed, deployment.cancelled |
| User & team | user.created, team.member.added, team.member.removed, user.subscription.updated |
| Security | auth.login, auth.logout, auth.failed, api.key.created |
Event payloads
Every event shares a common envelope — an id, a type, a created timestamp, and a data object.
{
"id": "evt_1234567890",
"type": "deployment.succeeded",
"created": "2024-01-15T10:30:00Z",
"data": {
"deployment": {
"id": "dep_abc123",
"project_id": "proj_xyz789",
"environment": "production",
"url": "https://my-app.vibecaas.app",
"commit": {
"sha": "a3f4b2c",
"message": "Fix authentication bug",
"author": "john@example.com"
},
"duration": 45,
"status": "success"
},
"triggered_by": { "type": "manual", "user": "user_123" }
}
}Webhook security
Verify the signature on every request, and reject anything older than a few minutes to prevent replay attacks.
const express = require("express");
const crypto = require("crypto");
const verifyWebhook = (req, res, next) => {
const signature = req.headers["x-vibecaas-signature"];
const timestamp = req.headers["x-vibecaas-timestamp"];
if (!signature || !timestamp) {
return res.status(401).send("Missing signature");
}
// Reject requests older than 5 minutes
const now = Math.floor(Date.now() / 1000);
if (now - parseInt(timestamp) > 300) {
return res.status(401).send("Request too old");
}
const signedPayload = `${timestamp}.${JSON.stringify(req.body)}`;
const expected = crypto
.createHmac("sha256", process.env.WEBHOOK_SECRET)
.update(signedPayload)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send("Invalid signature");
}
next();
};
app.post("/webhooks/vibecaas", express.raw({ type: "application/json" }), verifyWebhook,
async (req, res) => {
const event = req.body;
switch (event.type) {
case "deployment.succeeded":
await handleDeploymentSuccess(event.data);
break;
case "deployment.failed":
await handleDeploymentFailure(event.data);
break;
}
res.status(200).send("OK");
}
);Security checklist: verify signatures, accept HTTPS only, implement idempotency for retries, set up IP whitelisting where possible, and log all events for auditing.
Retry logic
If your endpoint doesn't return a 2xx status (or times out), VibeCaaS retries on a backoff schedule:
| Attempt | Delay |
|---|---|
| 1st retry | After 1 minute |
| 2nd retry | After 5 minutes |
| 3rd retry | After 30 minutes |
| Final retry | After 2 hours |
After all retries are exhausted the webhook is marked failed and you're notified. Webhook config also includes a 30-second timeout, event filtering, and a 100/minute rate limit.
Testing webhooks
# Trigger a test event from the API
curl -X POST https://api.vibecaas.com/v1/webhooks/:id/test
# Or from the CLI
vibecaas webhook test deployment.succeeded --endpoint https://api.example.com/webhookFor local development, expose your machine with a tunnel like ngrok http 3000, or inspect payloads with webhook.site or RequestBin. Delivery attempts and responses are visible in the dashboard webhook logs.
Common use cases
// Deployment notifications to Slack
if (event.type === "deployment.succeeded") {
await slack.send({
text: `Deployment successful for ${event.data.project.name}`,
url: event.data.deployment.url,
});
}
// Audit logging for compliance
await auditLog.create({
event: event.type,
user: event.data.triggered_by.user,
timestamp: event.created,
details: event.data,
});Best practices
- Idempotency — use the webhook ID header to process each event only once, even across retries.
- Async processing — return
200 OKimmediately and process the event in the background to avoid timeouts. - Event filtering — subscribe only to events you actually need.
- Error handling — log failures and alert on critical events.
Next steps
- Pair webhooks with polling endpoints in the API overview.
- Trigger workflows from webhook events with Agent workflows.
- Troubleshoot delivery failures in FAQ & troubleshooting.