SDK & Integrations

Custom Outbound Webhooks Reference

PRO / PREMIUM

Real-time event streaming for daily BaZi shifts, solar term transitions, and quota alerts with HMAC-SHA256 verification.

REST API Reference
The BaZi API Webhook Subsystem pushes real-time JSON payloads to your servers whenever astrological events occur or quota thresholds are met. Includes HMAC-SHA256 signature verification and automatic 3x retries with exponential backoff.

Quick Start

Example Webhook Event Payload (daily.bazi_shift)
JSON
{
  "event": "daily.bazi_shift",
  "timestamp": "2026-09-03T00:00:00.000Z",
  "data": {
    "date": "2026-09-03",
    "lunarDate": "丙午年 七月十四",
    "dayPillar": {
      "gan": "Ding",
      "zhi": "Wei",
      "wuXing": "Fire / Earth",
      "naYin": "Heavenly River Water"
    },
    "zodiac": "Horse",
    "solarTerm": "Li Qiu"
  }
}

API Parameters

ParameterTypeRequiredDefaultDescription
x-bazi-signaturestringRequiredHMAC-SHA256 hex digest computed with your webhook signing secret (whsec_...).
x-bazi-eventstringRequiredThe name of the triggered event (e.g. daily.bazi_shift, solar_term.changed).
x-bazi-timestampstringRequiredISO-8601 timestamp indicating when the payload was generated.

More Examples

Node.js (Express) Webhook Signature Verification

Node.js (Express) Webhook Signature Verification
JavaScript
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());

app.post('/api/webhooks/bazi', (req, res) => {
  const signature = req.headers['x-bazi-signature'];
  const event = req.headers['x-bazi-event'];
  const secret = process.env.BAZI_WEBHOOK_SECRET; // whsec_...

  const expected = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(req.body))
    .digest('hex');

  // Verify HMAC-SHA256 signature
  if (signature !== expected) {
    return res.status(401).json({ error: 'Invalid webhook signature' });
  }

  console.log('Verified Webhook Event:', event, req.body.data);
  return res.status(200).json({ received: true });
});

app.listen(3000, () => console.log('Listening on port 3000'));

Python (FastAPI) Webhook Signature Verification

Python (FastAPI) Webhook Signature Verification
Python
from fastapi import FastAPI, Request, Header, HTTPException
import hmac
import hashlib
import json
import os

app = FastAPI()
WEBHOOK_SECRET = os.getenv("BAZI_WEBHOOK_SECRET")

@app.post("/api/webhooks/bazi")
async def handle_bazi_webhook(request: Request, x_bazi_signature: str = Header(None)):
    raw_body = await request.body()
    
    expected = hmac.new(
        WEBHOOK_SECRET.encode("utf-8"),
        raw_body,
        hashlib.sha256
    ).hexdigest()
    
    if not x_bazi_signature or not hmac.compare_digest(x_bazi_signature, expected):
        raise HTTPException(status_code=401, detail="Invalid signature")
        
    payload = json.loads(raw_body)
    print("Received verified event:", payload.get("event"))
    return {"received": True}

PHP Webhook Receiver

PHP Webhook Receiver
php
<?php
$secret = getenv('BAZI_WEBHOOK_SECRET');
$signature = $_SERVER['HTTP_X_BAZI_SIGNATURE'] ?? '';
$rawBody = file_get_contents('php://input');

$expected = hash_hmac('sha256', $rawBody, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    echo json_encode(['error' => 'Invalid signature']);
    exit;
}

$payload = json_decode($rawBody, true);
// Process event data
http_response_code(200);
echo json_encode(['received' => true]);

Something unclear? Contact developer support.