> ## Documentation Index
> Fetch the complete documentation index at: https://bobprince-78964c2b.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Paystack

> Capture and inspect Paystack webhook events with Hookdrop.

Use Hookdrop as your Paystack webhook URL to capture payment, transfer, subscription, and invoice events — and inspect every payload in real time without a public endpoint.

## Setup

<Steps>
  <Step title="Open API Keys & Webhooks settings">
    Go to the [Paystack Dashboard](https://dashboard.paystack.com) and navigate to **Settings → API Keys & Webhooks**.
  </Step>

  <Step title="Paste your Hookdrop URL">
    In the **Webhook URL** field, enter your capture URL:

    ```
    https://hookdrop.dev/in/{your-token}
    ```

    Replace `{your-token}` with the token shown on your Hookdrop dashboard.
  </Step>

  <Step title="Save changes">
    Click **Save**. Paystack will begin sending events to your Hookdrop URL immediately.
  </Step>
</Steps>

<Note>
  Paystack supports one webhook URL per account (live and test environments each have their own). Make sure you set the URL in the correct environment — use your test-mode secret key and Hookdrop URL together when building.
</Note>

## Common events

| Event                 | When it fires                       |
| --------------------- | ----------------------------------- |
| `charge.success`      | A payment completes successfully    |
| `transfer.success`    | A transfer to a recipient completes |
| `subscription.create` | A new subscription is created       |
| `invoice.create`      | A subscription invoice is generated |

## Signature verification

Paystack signs every webhook request with an `X-Paystack-Signature` header containing an HMAC SHA-512 hex digest. Verify it in your handler before processing any event.

```typescript paystack-webhook.ts theme={null}
import crypto from 'crypto'

const verifyPaystackWebhook = (
  payload: string,
  signature: string,
  secret: string
): boolean => {
  const expected = crypto
    .createHmac('sha512', secret)
    .update(payload)
    .digest('hex')

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature)
  )
}
```

Use your **secret key** (not the public key) as the `secret` parameter. Find it in **Paystack Dashboard → Settings → API Keys & Webhooks**.

<Warning>
  Paystack uses SHA-512, not SHA-256. Using the wrong algorithm will cause every verification check to fail.
</Warning>

## Testing locally

<Tip>
  Point your Paystack test-mode webhook URL at your Hookdrop capture URL. Every test charge and transfer appears in your Hookdrop dashboard instantly — replay any event to your handler without re-running a payment flow each time.
</Tip>

<Card title="Back to quickstart" icon="rocket" href="/quickstart">
  Return to the quickstart guide to set up your first Hookdrop endpoint.
</Card>
