Zapier
Verify a RefRef webhook in a Zap, grant the Reward, and confirm it with the RefRef API.
This Zap receives reward.earned, verifies the RefRef signature in a Code step, and confirms the Reward with a POST step. Read the overview first for the subscription and signature rules.

Plan limits
On a free account, the editor marked this Zap as using two Pro features: Webhooks by Zapier and the third step. The free account could build and test the Zap; check Zapier's plans before you turn it on. The free plan also stopped the Code step after about one second when it called the API, so the confirmation is a separate POST step.
1. Catch the raw request
- Create a Zap with the trigger Webhooks by Zapier → Catch Raw Hook. Use Catch Raw Hook, not Catch Hook: it keeps the raw body and the request headers, which the signature check needs.
- Copy the webhook URL.
- Subscribe the URL with
fulfillmentMode: "explicit"and keep the returnedsecret(see Subscribe the URL). - Send one event, then select the request in the trigger's Test tab. Earn a real Reward for a complete test. Send test event… in the endpoint menu of Developers → Webhooks sends a signed sample that is enough to test the verify step, but its Reward does not exist, so the confirm step answers
404for it.
2. Verify the signature
Add Code by Zapier → Run Javascript and map these input fields:
| Input | Value |
|---|---|
rawBody | 1. Raw Body |
webhookId | 1. Headers Http Webhook Id |
webhookTimestamp | 1. Headers Http Webhook Timestamp |
webhookSignature | 1. Headers Http Webhook Signature |
secret | The endpoint secret, starting whsec_ |

Paste this code:
const crypto = require("crypto");
// Verify the Standard Webhooks signature over id.timestamp.body.
const key = Buffer.from(inputData.secret.replace(/^whsec_/, ""), "base64");
const expected = crypto
.createHmac("sha256", key)
.update(
`${inputData.webhookId}.${inputData.webhookTimestamp}.${inputData.rawBody}`,
)
.digest("base64");
if (!inputData.webhookSignature.split(" ").includes(`v1,${expected}`)) {
throw new Error("Invalid RefRef signature");
}
if (Math.abs(Date.now() / 1000 - Number(inputData.webhookTimestamp)) > 300) {
throw new Error("Old webhook timestamp");
}
const event = JSON.parse(inputData.rawBody);
return {
eventId: event.id,
projectId: event.projectId,
rewardId: event.data.reward.id,
externalId: event.data.reward.beneficiary.externalId,
};A thrown error stops the Zap, so the later steps run only for a signed, recent request. The timestamp check refuses a sample older than five minutes: send a fresh event before you test this step.
3. Grant the Reward
Add the steps that grant the Reward in your product. Use 2. Reward Id as the idempotency key and 2. External Id to find the user.
4. Confirm the fulfillment
Add Webhooks by Zapier → POST:
| Field | Value |
|---|---|
| URL | https://<your RefRef API>/v1/rewards/ + 2. Reward Id + /fulfillment |
| Payload Type | Json |
| Data | projectId = 2. Project Id; externalReference = zapier: + 2. Event Id |
| Headers | x-api-key = your Workspace API key |


Write the header name in lowercase: x-api-key. In our check, the request
reached RefRef without the key when the header was named X-Api-Key, and
RefRef answered API key required.
Test the step. The Reward's status becomes fulfilled, and GET /v1/rewards/{rewardId} shows the externalReference that the Zap sent.