Webhooks
Subscribe to Partli events from your own backend. Signed, retried, audit-logged.
Partli sends webhook events to your registered endpoints whenever something important happens — a new application, a sale, a payout. Useful for syncing Partli state into your own database or triggering downstream actions.
Setup
Workspace sidebar → Developer → Webhooks. Click Create endpoint, paste your URL, pick the events you care about, save. We generate a signing secret you use to verify each delivery.
Available events
partner.applied— partner submitted an applicationpartner.approved— partner approved (manually or via auto-approve)partner.rejected— partner application rejectedlead.created— attributed lead eventsale.created— attributed sale eventcommission.created— pending commission row createdcommission.approved— commission moved to approved (post-holding)commission.paid— included in a successful payoutpayout.sent— payout transfer to partner succeededpayout.failed— payout transfer failed
Payload format
Each delivery includes two headers: x-partli-event with the event name, and x-partli-signature with the HMAC. The body is:
{
"event": "sale.created",
"timestamp": "2026-04-25T10:32:14.892Z",
"data": {
"saleId": "uuid-...",
"partnerId": "uuid-...",
"customerId": "uuid-...",
"amountCents": 4900,
"currency": "USD",
"commissionId": "uuid-..."
}
}Verifying signatures
Every delivery includes x-partli-signature — an HMAC-SHA256 (hex) of the raw body using your endpoint's secret:
import crypto from "crypto";
export function verifyPartliWebhook(rawBody: string, signature: string, secret: string) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex"),
);
}
// In your handler:
const valid = verifyPartliWebhook(rawBody, req.headers["x-partli-signature"], process.env.PARTLI_WEBHOOK_SECRET);
if (!valid) return res.status(400).end();Retries
We retry non-2xx responses with exponential backoff: 1m, 5m, 30m, 2h, 6h, 24h. After 6 failed attempts the delivery is marked failed (visible in the webhook logs).
Idempotency on your side
data payload (e.g. saleId,commissionId) plus the event name as your idempotency key. We may retry — your handler should treat duplicate deliveries as no-ops.