# Partnero Webhooks

Partnero (affiliate, referral and partner program platform) sends an HTTP `POST` with a JSON body to
your endpoint when partners, customers, transactions or rewards change. Every request carries a
`Signature` header: the hex HMAC-SHA256 of the **raw request body**, keyed with the webhook's
signing secret.

## When to Use This Skill

* How do I receive Partnero webhooks?
* How do I verify the Partnero `Signature` header?
* Why does my Partnero webhook signature verification fail?
* How do I handle `partner.created`, `transaction.created` or `reward.approved` events?
* How do I test Partnero outgoing webhooks locally?

## Verification (core)

* Header: `Signature` (literally that name). Value: bare lowercase hex digest, no prefix.
* Signed content: the raw body bytes only (no timestamp, no id).
* Key: the webhook's signing secret as UTF-8 bytes. Compare the whole header value as one digest.

```javascript
const crypto = require('crypto');

function verifyPartneroSignature(rawBody, signatureHeader, secret) {
  if (!signatureHeader || !secret) return false;
  if (!/^[0-9a-f]{64}$/i.test(signatureHeader)) return false; // check shape before comparing
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signatureHeader.toLowerCase()),
    Buffer.from(expected)
  );
}

```

* Missing, malformed or mismatched signature: `401`. Bad JSON after a valid signature: `400`. Otherwise `200`.
* Read the body raw (`express.raw({ type: '*/*' })`, `request.arrayBuffer()`, `await request.body()`) and parse
  JSON only after the check. Partnero signs PHP `json_encode` output (escaped `\/` and `\uXXXX`), so
  `JSON.stringify(req.body)` never matches.
* In Python use `hmac.compare_digest` on **bytes**; `str` raises `TypeError` on non-ASCII input.
* No timestamp is signed, so there is no replay window to check. Deduplicate on your own keys.

> **For complete handlers with tests**, see [examples/express/](https://github.com/hookdeck/webhook-skills/tree/main/skills/partnero-webhooks/examples/express/), [examples/nextjs/](https://github.com/hookdeck/webhook-skills/tree/main/skills/partnero-webhooks/examples/nextjs/), [examples/fastapi/](https://github.com/hookdeck/webhook-skills/tree/main/skills/partnero-webhooks/examples/fastapi/).

## Event Types

Body: `{event, url, webhook_key, created_at, data}`. Dispatch on `event`; `data` holds the
event-specific fields. No header names the event type.

| Event | Sent When |
| --- | --- |
| `partner.created` | A new partner signs up or is created |
| `partner.updated` | Partner information is updated |
| `partner.approved` | A partner application is approved |
| `partner.rejected` | A partner application is rejected |
| `partner.archived` | A partner is archived |
| `partner.deleted` | A partner is deleted |
| `customer.created` | A new customer is created |
| `customer.updated` | Customer information is updated |
| `customer.deleted` | A customer is deleted |
| `transaction.created` | A new transaction is recorded |
| `transaction.updated` | A transaction is updated |
| `transaction.deleted` | A transaction is deleted (refund) |
| `reward.created` | A commission/reward is created |
| `reward.approved` | A reward is approved for payout |
| `reward.paid` | A reward is marked as paid |

## Environment Variables

```bash
PARTNERO_WEBHOOK_SECRET=your_webhook_signing_secret  # shown when you create the webhook

```

## Local Development

Partnero can't reach `localhost`. Tunnel with the Hookdeck CLI (no account required):

```bash
npx hookdeck-cli listen 3000 partnero --path /webhooks/partnero

```

Use the printed URL as the webhook URL in Partnero (Program Settings > Webhooks).

## Resources

* [references/overview.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/partnero-webhooks/references/overview.md) - What the webhooks are, events, payloads and delivery
* [references/setup.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/partnero-webhooks/references/setup.md) - Create the webhook and copy the signing secret
* [references/verification.md](https://github.com/hookdeck/webhook-skills/blob/main/skills/partnero-webhooks/references/verification.md) - Signature details, gotchas, debugging
* [examples/](https://github.com/hookdeck/webhook-skills/tree/main/skills/partnero-webhooks/examples/) - Runnable Express, Next.js and FastAPI handlers with tests