name.ai

Webhooks & events

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.

PUT

/api/partner/webhooks

scope: webhook

Register or update your webhook endpoint and signing secret.

Request
PUT /api/partner/webhooks
Content-Type: application/json
...auth headers...

{
  "url": "https://yoursite.com/webhooks/nameai",
  "secret": "whsec_your_chosen_signing_secret"
}
Response 200
{
  "url": "https://yoursite.com/webhooks/nameai",
  "active": true,
  "created_at": "2026-06-08T07:00:00Z"
}

Event delivery format

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.

Webhook payload shape
{
  "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"
    }
  }
}
Signature verification: Compute HMAC-SHA256(whsec_secret, raw_body) → hex → compare with X-NameAI-Signature. Always use timing-safe comparison.

Signature verification (Node.js)

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 types

Event typeDescriptionTriggered by
order.recordedA partner-collected sale has been successfully recorded (status: EXTERNALLY_PAID).POST /orders success
order.manual_review_clearedA held order has been cleared by ops and transfer will proceed.Admin action
order.transfer_startedAdmin has initiated the domain push (TRANSFER_IN_PROGRESS).Admin action
order.transfer_completedDomain delivered to partner registrar (TRANSFER_COMPLETED). Settlement clock starts.Admin confirms delivery
order.settledSettlement period closed, order fully reconciled (SETTLED).Settlement run
order.refundedOrder refunded or cancelled.POST /refunds or admin
brokerage.case_completedA brokerage acquisition case was closed with a deal.Brokerage deal closed
GET

/api/partner/v1/events

scope: webhook

Replayable signed event history. Use after_id to paginate and catch up after downtime.

Example — catch up from a known event
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..."
}

Delivery best practices

  • Respond 200 within 5 seconds; do heavy processing async.
  • Make your handler idempotent — events may be delivered more than once.
  • Use GET /events to replay if your endpoint was down.
  • Never trust webhook data without verifying the X-NameAI-Signature.

Next: Full API reference →

Syndicate Partner API — Webhooks & events — name.ai