Skip to content

Partner webhooks

A partner endpoint receives the events of all of the partner’s stores, so the platform needs one receiver, not one per store. Manage endpoints with the Partner API (partner.webhooks:manage):

Terminal window
curl -X POST "https://api.nexafone.so/api/v1/partner/webhook-endpoints" \
-H "Authorization: Bearer $NEXAFON_PARTNER_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://platform.example/hooks/nexafon", "events": ["order.created", "order.paid", "message.received"]}'

Each event carries the store it comes from:

{
"id": "7c6b5a49-3827-4165-9483-a2b1c0d9e8f7",
"type": "order.paid",
"createdAt": "2026-09-21T14:13:18Z",
"workspaceId": "bbbbbbbb-0000-0000-0000-000000000000",
"partner": { "storeExternalRef": "shop-1" },
"data": { "order": { "number": 1042, "status": "paid", "totalCents": 2800 } }
}

Deliveries are signed, retried and logged exactly like a workspace’s: see signatures, retries and the event catalog. The helpers’ verifyWebhook handles both kinds.

partner.ts
// One endpoint receives every store's events; partner.storeExternalRef names the store.
export function onDelivery(headers: Record<string, string>, rawBody: Buffer) {
const event = verifyWebhook(headers, rawBody, process.env.NEXAFON_PARTNER_WEBHOOK_SECRET ?? '')
if (event.type === 'order.paid') {
console.log('paid order in', event.partner?.storeExternalRef, event.id)
}
return event
}

Stores can still have their own endpoints too; an event goes to both.