Receive real-time event notifications when things happen in your Arch Tools account — payments, credit alerts, errors, and more.
Register an HTTPS endpoint with the events you want to subscribe to. When an event fires, Arch Tools sends a POST request to your URL with a signed JSON payload.
Every delivery includes an HMAC-SHA256 signature so you can verify it came from us. We retry failed deliveries up to 3 times with exponential backoff.
| Event | Fires When | Payload Fields |
|---|---|---|
payment.received |
A payment completes (one-time pack, subscription start, or renewal) | type, credits_added, amount_usd, plan |
credits.low |
Credit balance drops below 20% threshold after a tool call | credits_remaining, tool_name, threshold |
credits.depleted |
Credit balance hits zero | credits_remaining, tool_name, message |
agent.registered |
A new agent registers (for admin/platform webhooks) | agent_id, email, tier |
tool.error |
A tool call fails with an error | tool_name, credits_charged |
Every webhook delivery is a JSON POST with this structure:
{
"id": "evt_a1b2c3d4e5f6g7h8i9j0k1l2",
"event": "payment.received",
"timestamp": "2026-03-17T14:30:00.000Z",
"data": {
"agent_id": "clx1abc2def3ghi4jkl",
"type": "one_time",
"credits_added": 5000,
"amount_usd": "9.00",
"stripe_session_id": "cs_test_..."
}
}
| Header | Description |
|---|---|
Content-Type | application/json |
X-Webhook-Id | Unique event ID (for idempotency) |
X-Webhook-Event | Event type (e.g. payment.received) |
X-Webhook-Signature | HMAC-SHA256 signature: sha256=<hex> |
X-Webhook-Timestamp | ISO 8601 timestamp |
User-Agent | ArchTools-Webhook/1.0 |
Every delivery is signed with your webhook's secret using HMAC-SHA256. Always verify the signature before processing.
import crypto from "crypto";
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
return signature === `sha256=${expected}`;
}
// In your Express handler:
app.post("/my-webhook", (req, res) => {
const sig = req.headers["x-webhook-signature"];
const rawBody = JSON.stringify(req.body);
if (!verifyWebhook(rawBody, sig, "whsec_your_secret_here")) {
return res.status(401).send("Invalid signature");
}
const event = req.body;
console.log(`Received ${event.event}:`, event.data);
res.status(200).send("OK");
});
import hmac
import hashlib
def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return signature == f"sha256={expected}"
# In your Flask handler:
@app.route("/my-webhook", methods=["POST"])
def webhook():
sig = request.headers.get("X-Webhook-Signature", "")
if not verify_webhook(request.data, sig, "whsec_your_secret_here"):
return "Invalid signature", 401
event = request.json
print(f"Received {event['event']}: {event['data']}")
return "OK", 200
curl -X POST https://archtools.dev/api/v1/webhooks/register \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhook",
"events": ["payment.received", "credits.low"]
}'
secret is only returned once at registration. Save it immediately — you'll need it to verify signatures.curl https://archtools.dev/api/v1/webhooks \ -H "x-api-key: YOUR_API_KEY"
curl -X DELETE https://archtools.dev/api/v1/webhooks/WEBHOOK_ID \ -H "x-api-key: YOUR_API_KEY"
curl -X POST https://archtools.dev/api/v1/webhooks/test \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "webhook_id": "OPTIONAL_SPECIFIC_WEBHOOK_ID" }'
If your endpoint returns a non-2xx status or times out (10s), we retry up to 3 times with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 1 second |
| 2nd retry | 4 seconds |
| 3rd retry | 9 seconds |
Client errors (4xx except 429) are not retried — fix your endpoint and use the test endpoint to verify.
X-Webhook-Signature before processing200 OK quickly — process events asynchronously if neededid field for idempotency (don't process the same event twice)X-Webhook-Timestamp to reject old replays/webhook path/test endpoint to verify your setup before going live