Case watch with webhooks
Watch a case by CNR and get a signed webhook when its next date changes or an order lands. Build and test it end to end in the sandbox.
You track cases for clients. You want to know the day a next date moves or an order is uploaded, without opening a portal each morning. This guide builds that with a watch and a webhook, tests it in the sandbox, and then goes live.
A next date is the date the court has fixed for the next hearing. An order is what the judge recorded.
#1. Run a handler
Start a small server that verifies the signature and stores the event. This one is Express; any framework works if you hand it the raw body.
import express from "express";
import { webhooks } from "@advocate-os/sdk";
const app = express();
const seen = new Set<string>(); // use your database in production
app.post("/hooks/aos", express.raw({ type: "application/json" }), (req, res) => {
let event;
try {
event = webhooks.verify(req.body.toString("utf8"), req.header("AOS-Signature") ?? "", process.env.AOS_WEBHOOK_SECRET!);
} catch {
return res.sendStatus(400); // bad signature or stale timestamp
}
res.sendStatus(200); // answer first, work after
if (seen.has(event.id)) return; // events can arrive twice
seen.add(event.id);
if (event.type === "case.next_date_changed") {
const { cnr, changes } = event.data as { cnr: string; changes: { field: string; from: string | null; to: string | null }[] };
const c = changes.find((x) => x.field === "next_hearing_date");
console.log(`${cnr}: ${c?.from} -> ${c?.to}`);
} else if (event.type === "order.published") {
console.log("new order", event.data);
}
});
app.listen(3000);
import os
from flask import Flask, request
from advocate_os import webhooks
app = Flask(__name__)
seen = set() # use your database in production
@app.post("/hooks/aos")
def hook():
try:
event = webhooks.verify(request.get_data(), request.headers.get("AOS-Signature", ""), os.environ["AOS_WEBHOOK_SECRET"])
except Exception:
return "", 400 # bad signature or stale timestamp
if event["id"] in seen: # events can arrive twice
return "", 200
seen.add(event["id"])
if event["type"] == "case.next_date_changed":
d = event["data"]
c = next((x for x in d["changes"] if x["field"] == "next_hearing_date"), {})
print(f"{d['cnr']}: {c.get('from')} -> {c.get('to')}")
return "", 200
#2. Receive events on your laptop
Our servers cannot call localhost. In development, the CLI reads your event log and forwards each event, signed, to your handler:
export AOS_API_BASE="https://adv.heliosynctech.com/api/v1"
export AOS_KEY="aos_test_paste_your_key_here"
aos listen --forward-to http://localhost:3000/hooks/aos
It prints a signing secret. Put it in AOS_WEBHOOK_SECRET and restart your handler.
#3. Watch a sandbox case
SBXX010000032026 gets a new order every sandbox day, which is what you want for testing.
curl -X POST https://adv.heliosynctech.com/api/v1/watches \
-H "Authorization: Bearer $AOS_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" -H "AOS-Sandbox-Date: 2026-12-01" \
-d '{ "kind": "case", "cnr": "SBXX010000032026" }'
The watch is made "on" sandbox day 2026-12-01 and remembers what the case looked like that day. A test watch is free. In live mode a case watch costs ₹15, then ₹10 from 1,000 a month, ₹6 from 10,000 a month per case a month.
#4. Make something happen
Two ways, both free:
-
Move the clock. The sandbox has no clock of its own, so events appear when its date moves on. Make
GET /events(orGET /watches) withAOS-Sandbox-Dateset to a later day than the watch was made on. That call works out what changed in between, and the case gets a new order: your handler seesorder.published, withcase.updatedandcase.next_date_changedbesides. With the CLI, runAOS_SANDBOX_DATE=2026-12-02 aos listen --forward-to ….curl https://adv.heliosynctech.com/api/v1/events \ -H "Authorization: Bearer $AOS_KEY" -H "AOS-Sandbox-Date: 2026-12-02" -
Send an event.
aos trigger case.next_date_changed --cnr SBXX010000012026, orPOST /sandbox/events.
Check that your handler logged the event, replied 200, and ignored a second delivery of the same id. Then break it on purpose: return a 500 from the handler and watch the event come back later. See retries.
#5. Go live
- Deploy the handler at a public
httpsaddress. - Make a live key, then register a live webhook endpoint for the events you need and store its
whsec_…secret. Live endpoints must be publichttps.
curl -X POST https://adv.heliosynctech.com/api/v1/webhook-endpoints \
-H "Authorization: Bearer $AOS_LIVE_KEY" -H "Content-Type: application/json" \
-d '{ "url": "https://example.com/hooks/aos", "events": ["case.next_date_changed", "order.published", "case.disposed"] }'
- Create a watch for each real CNR.
- Keep the safety net: every few hours, read
GET /events?after=<last event id>and handle anything a webhook missed. See events.
#What to do with an event
case.next_date_changed: update your diary, and tell the client. Do not let a machine send advice; sending the date is fine.order.published: fetch the order (GET /orders/{id}, ₹1.50, then ₹1 from 10,000 a month) only when you need its text. The event itself is free.case.disposed: stop the watch withDELETE /watches/{id}, so you are not charged next month.
Billing: a watch is charged for the month it is created in, then on the 1st of each month it is active.