AstroCal
Guides

Webhooks

Receive real-time HTTP notifications when booking events occur.

Webhooks let you receive real-time HTTP POST notifications when events occur in your AstroCal account. Instead of polling the API, register a webhook endpoint and AstroCal will push events to your server as they happen.

Event Types

EventTrigger
booking.createdA new booking is confirmed
booking.cancelledAn existing booking is cancelled
booking.rescheduledAn existing booking is rescheduled

Creating a Webhook Endpoint

Register a URL to receive events:

curl -X POST https://api.astrocal.dev/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/astrocal",
    "events": ["booking.created", "booking.cancelled"]
  }'

The response includes a secret field — save this immediately. The secret is only shown once at creation time and is used to verify webhook signatures.

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://your-app.com/webhooks/astrocal",
  "events": ["booking.created", "booking.cancelled"],
  "secret": "whsec_abc123...",
  "active": true,
  "created_at": "2026-03-01T10:00:00.000Z",
  "updated_at": "2026-03-01T10:00:00.000Z"
}

Payload Format

Each webhook delivery sends a JSON payload with this structure:

{
  "event": "booking.created",
  "data": {
    "id": "770e8400-e29b-41d4-a716-446655440000",
    "organization_id": "550e8400-e29b-41d4-a716-446655440000",
    "event_type_id": "660e8400-e29b-41d4-a716-446655440000",
    "status": "confirmed",
    "start_time": "2026-03-15T14:00:00.000Z",
    "end_time": "2026-03-15T14:30:00.000Z",
    "invitee_name": "Jane Smith",
    "invitee_email": "jane@example.com",
    "invitee_timezone": "America/New_York",
    "notes": null,
    "created_at": "2026-03-01T10:00:00.000Z",
    "updated_at": "2026-03-01T10:00:00.000Z"
  },
  "created_at": "2026-03-01T10:00:00.123Z"
}

Verifying Signatures

Every webhook delivery includes an X-AstroCal-Signature header containing an HMAC-SHA256 signature of the request body. Always verify this signature to ensure the webhook came from AstroCal and wasn't tampered with.

The header format is v1=<hex-digest>.

Node.js / TypeScript Example

import crypto from "node:crypto";

function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean {
  const expectedSig = crypto.createHmac("sha256", secret).update(payload).digest("hex");

  const expected = `v1=${expectedSig}`;

  // Use timing-safe comparison to prevent timing attacks
  if (signature.length !== expected.length) return false;
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

// In your webhook handler:
app.post("/webhooks/astrocal", (req, res) => {
  const signature = req.headers["x-astrocal-signature"];
  const rawBody = req.body; // Must be the raw string, not parsed JSON

  if (!verifyWebhookSignature(rawBody, signature, WEBHOOK_SECRET)) {
    return res.status(401).send("Invalid signature");
  }

  const event = JSON.parse(rawBody);
  // Handle the event...

  res.status(200).send("OK");
});

Headers

Each webhook delivery includes these headers:

HeaderDescription
Content-TypeAlways application/json
X-AstroCal-SignatureHMAC-SHA256 signature (v1=<hex>)
X-AstroCal-EventThe event type (e.g. booking.created)

Retry Behavior

If your endpoint returns a non-2xx status code or the request times out (10 seconds), AstroCal will retry with exponential backoff:

AttemptDelay After
1Immediate
21 minute
35 minutes
430 minutes
52 hours
624 hours

After 6 failed attempts, the delivery is marked as permanently failed. You can view delivery history via the API.

Managing Webhooks

You can manage webhooks from the dashboard or via the API.

Dashboard

The Webhooks page in the developer dashboard lets you:

  • Create, edit, and delete webhook endpoints
  • Toggle endpoints active/inactive
  • View delivery logs with status, HTTP response codes, and retry counts
  • Copy the signing secret on creation

Navigate to Dashboard > Webhooks to get started.

List Endpoints

curl https://api.astrocal.dev/v1/webhooks \
  -H "Authorization: Bearer YOUR_API_KEY"

Update an Endpoint

curl -X PATCH https://api.astrocal.dev/v1/webhooks/WEBHOOK_ID \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"active": false}'

Delete an Endpoint

curl -X DELETE https://api.astrocal.dev/v1/webhooks/WEBHOOK_ID \
  -H "Authorization: Bearer YOUR_API_KEY"

View Delivery History

curl "https://api.astrocal.dev/v1/webhooks/WEBHOOK_ID/deliveries?status=failed" \
  -H "Authorization: Bearer YOUR_API_KEY"

Best Practices

  1. Always verify signatures. Never trust webhook payloads without signature verification.
  2. Respond quickly. Return a 2xx response within 10 seconds. Process the event asynchronously if needed.
  3. Handle duplicates. In rare cases, the same event may be delivered more than once. Use the event data.id for idempotency.
  4. Use HTTPS. Always use HTTPS URLs for your webhook endpoints in production.
  5. Monitor deliveries. Check the dashboard or the deliveries endpoint for failed deliveries.

On this page