Loading…
Subscribe once — we deliver signed events to your endpoint for every order, transfer, and settlement update. Events are also stored in a replayable history so you can catch up after downtime.
Register or update your webhook endpoint and signing secret.
PUT /api/partner/webhooks
Content-Type: application/json
...auth headers...
{
"url": "https://yoursite.com/webhooks/nameai",
"secret": "whsec_your_chosen_signing_secret"
}{
"url": "https://yoursite.com/webhooks/nameai",
"active": true,
"created_at": "2026-06-08T07:00:00Z"
}Events are sent as POST requests to your registered URL with a JSON body and an X-NameAI-Signature header. Verify the signature before processing.
{
"id": "evt_01JXYZ...",
"type": "order.transfer_completed",
"created_at": "2026-06-08T09:15:00Z",
"partner_id": "ptr_KEHD6AA3...",
"data": {
"order": {
"public_id": "ord_01JABC...",
"domain": "custodylawyer.com",
"status": "TRANSFER_COMPLETED",
"sale_price_cents": 2500000,
"currency": "USD"
}
}
}HMAC-SHA256(whsec_secret, raw_body) → hex → compare with X-NameAI-Signature. Always use timing-safe comparison.import crypto from "crypto";
export function verifyWebhook(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody, "utf8")
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signatureHeader, "hex"),
Buffer.from(expected, "hex")
);
}
// Express example
app.post("/webhooks/nameai", express.raw({ type: "application/json" }), (req, res) => {
const sig = req.headers["x-nameai-signature"];
if (!verifyWebhook(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(req.body.toString());
console.log("Event type:", event.type, "Order:", event.data?.order?.public_id);
res.sendStatus(200); // always respond 200 quickly; process async
});| Event type | Description | Triggered by |
|---|---|---|
| order.recorded | A partner-collected sale has been successfully recorded (status: EXTERNALLY_PAID). | POST /orders success |
| order.manual_review_cleared | A held order has been cleared by ops and transfer will proceed. | Admin action |
| order.transfer_started | Admin has initiated the domain push (TRANSFER_IN_PROGRESS). | Admin action |
| order.transfer_completed | Domain delivered to partner registrar (TRANSFER_COMPLETED). Settlement clock starts. | Admin confirms delivery |
| order.settled | Settlement period closed, order fully reconciled (SETTLED). | Settlement run |
| order.refunded | Order refunded or cancelled. | POST /refunds or admin |
| brokerage.case_completed | A brokerage acquisition case was closed with a deal. | Brokerage deal closed |
Replayable signed event history. Use after_id to paginate and catch up after downtime.
GET /api/partner/v1/events?after_id=evt_01JXYZ...&limit=50
{
"events": [
{
"id": "evt_01JAAA...",
"type": "order.transfer_completed",
"created_at": "2026-06-08T09:15:00Z",
"data": { ... }
}
],
"next_cursor": "evt_01JBBB..."
}200 within 5 seconds; do heavy processing async.GET /events to replay if your endpoint was down.X-NameAI-Signature.Next: Full API reference →