Connect Braze Webhooks to RewardStar
Connect Braze Webhooks to RewardStar Cards
Who this is for: Marketing ops and Braze admins who want Braze to issue a RewardStar gift card when a campaign or Canvas step fires.
Time to complete: About 30–60 minutes (plus QA), once Incentable credentials and a RewardStar card template are ready.
Overview
When a Braze campaign or Canvas step runs, Braze sends an automated HTTP webhook to Incentable. Incentable issues a RewardStar gift card, emails the recipient the card (with a redeem link), and the recipient completes redemption in the RewardStar redeem flow.
If a recipient unsubscribes from the RewardStar email, they confirm on Incentable's unsubscribe page and Incentable then opts them out of email in Braze through the Braze REST API. This keeps Braze as the source of truth for email consent.
Optionally, in the same Braze multichannel campaign, you can also send a Braze push or email (for example, “Your gift card is on the way”) so the user hears from you in Braze as well as from Incentable/RewardStar.
Braze’s own docs describe a similar pattern: when a user hits a milestone or earns points, use webhooks plus your existing API to credit a reward to their account. See Create a webhook.
Prerequisites
Braze
| Requirement | Notes |
|---|---|
| Webhooks enabled on your Braze package | Availability depends on your Braze contract. If Webhooks is not visible, ask your Braze account manager or customer success manager. |
| Permission to create a Webhook Campaign or Canvas webhook step | Needed to configure the call to Incentable. |
| A defined trigger | Custom event (for example, reward earned / points threshold) or Canvas entry / step criteria after the user qualifies. |
A Braze REST API key with the email.status permission | Used by Incentable only to sync unsubscribes. Created in Braze under Settings → APIs and Identifiers. |
| Your Braze REST endpoint | The REST cluster for your workspace, for example https://rest.au-01.braze.com. Shown in Braze next to your API keys. |
Incentable / RewardStar
| Requirement | Notes |
|---|---|
| Active RewardStar card template | With produced denominations (card images produced for the amounts you will issue). |
| Program fund funded | Or use the card in test mode for QA (test mode does not draw down the fund). |
| A Braze integration in Incentable | With RewardStar: Write permission. Add Read if you will look up cards later. |
| Braze REST credentials saved on the integration | Required. Card issue requests are rejected until they are saved (see below). |
| Optional: Default RewardStar card | If set on the integration, Braze does not need to send cardId in every payload. |
Get credentials from Incentable
- Log in to the Incentable Admin Dashboard.
- Select the program you want to issue RewardStar cards for (API keys are scoped to a single program).
- Open Integrations and add a Braze integration (or open your existing one).
- Under Permissions & Configuration → RewardStar, confirm Write is on. New Braze integration keys have it on by default. Read is optional, for looking up issued cards. Permission changes are made by Incentable — contact support if you need one changed.
- Optionally set Default RewardStar Card on the same card so Braze payloads can omit
cardId. - Save your Braze REST credentials (next section).
- Generate the API key and store it in a secure password manager.
Save your Braze REST credentials
Incentable needs a Braze REST API key so it can opt recipients out of email in Braze when they unsubscribe.
- In Braze, go to Settings → APIs and Identifiers and create a REST API key with only the
email.statuspermission. - In Incentable, open the Braze integration and find the Braze REST API card.
- Choose your REST cluster (for example
AU-01 — rest.au-01.braze.com). - Paste the Braze API key and click Save Changes. Incentable stores it encrypted and shows only a masked prefix afterwards.
If the credentials are missing, card issue requests return 400 with code BRAZE_CREDENTIALS_REQUIRED.
Endpoint Braze should call
| Item | Value |
|---|---|
| Method | POST |
| Path | /rewardstar/cards |
| Full URL | https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external/rewardstar/cards |
The URL is also shown on the Braze integration's settings page under Connection. See the RewardStar API reference for full field and response details.
Direction: Braze → Incentable (outbound webhook from Braze).
Headers
| Header | Required | Value |
|---|---|---|
Authorization | Yes | Bearer <YOUR_API_KEY> |
Content-Type | Yes | application/json |
Idempotency-Key | Recommended | Stable unique string for this issue attempt. Body idempotencyKey takes precedence over this header; externalRef is used if neither is sent. |
Request body for the Braze webhook composer
Fields
The body uses the same fields as the RewardStar API — see that page for every field, type and limit. The ones that matter most in Braze:
member.email,member.firstname,member.lastname— required; map them from the Braze profile.denomination— required; must be a produced denomination on the RewardStar card.cardId— required unless a Default RewardStar Card is set on the integration.externalRef— strongly recommended; unique percardId. Critical for Braze retries.
Recommended Braze → payload mapping
| Incentable field | Suggested Braze source |
|---|---|
member.email | {{${email_address}}} |
member.firstname | {{${first_name}}} |
member.lastname | {{${last_name}}} |
member.accountKey | Fixed value or Liquid — see Fixed values vs Braze Liquid |
member.mobile | {{${phone_number}}} or a custom attribute |
denomination | Fixed number or Liquid — see Fixed values vs Braze Liquid |
cardId | Fixed string, or omit if default card is configured |
externalRef | Must be unique per card issue — e.g. Canvas/campaign + user id + reward id on the trigger event |
expiryDays | Fixed integer or Liquid — see Fixed values vs Braze Liquid |
externalRef. Braze may retry on 408, 429, and 5XX. Without a stable key, a retry can issue a second card. If you send neither externalRef nor an idempotency key, Incentable generates a one-off key for the request — that key is different on every retry, so it does not protect against duplicates.Fixed values vs Braze Liquid
Some fields can be hard-coded in the webhook body; others should almost always use Braze Liquid personalization.
Rule of thumb
- Profile fields (
email, name, phone) → almost always Liquid. accountKey,denomination, andexpiryDays→ fixed or Liquid.- Start with fixed values where possible. Use Liquid when the value must change per user or per event.
| Field | Fixed example | Liquid / variable example |
|---|---|---|
accountKey | "CRM-100245" | Braze user id {{${user_id}}} or custom attribute {{custom_attribute.${account_key}}} |
denomination | 50 | Event property {{event_properties.${gift_card_amount}}} or custom attribute {{custom_attribute.${reward_amount}}} |
expiryDays | 90 | Custom attribute {{custom_attribute.${card_expiry_days}}} |
Choosing accountKey
Prefer, in order:
{{${user_id}}}— always present in Braze, stable, no custom attribute setup.- Custom attribute — when you already sync a CRM/external id into Braze and want Incentable to match on that same key.
- Omit — Incentable matches/creates by email only (works, but weaker if emails change).
Simple (recommended for most campaigns) — Liquid for profile fields, Braze user id for accountKey, fixed amount and expiry:
{
"member": {
"email": "{{${email_address}}}",
"firstname": "{{${first_name}}}",
"lastname": "{{${last_name}}}",
"accountKey": "{{${user_id}}}"
},
"denomination": 50,
"expiryDays": 90,
"cardId": "YOUR_REWARDSTAR_CARD_ID",
"externalRef": "braze-{{campaign.${api_id}}}-{{${user_id}}}-{{event_properties.${reward_id}}}",
"idempotencyKey": "braze-{{campaign.${api_id}}}-{{${user_id}}}-{{event_properties.${reward_id}}}"
}
Advanced — amount, expiry, and account key from Braze custom attributes / event properties. Adjust attribute names to match your workspace:
{
"member": {
"email": "{{${email_address}}}",
"firstname": "{{${first_name}}}",
"lastname": "{{${last_name}}}",
"accountKey": "{{custom_attribute.${account_key}}}"
},
"denomination": {{event_properties.${gift_card_amount}}},
"expiryDays": {{custom_attribute.${card_expiry_days}}},
"cardId": "YOUR_REWARDSTAR_CARD_ID",
"externalRef": "braze-{{campaign.${api_id}}}-{{${user_id}}}-{{event_properties.${reward_id}}}",
"idempotencyKey": "braze-{{campaign.${api_id}}}-{{${user_id}}}-{{event_properties.${reward_id}}}"
}
Static JSON sample (for smoke tests)
{
"member": {
"email": "jane.doe@example.com",
"firstname": "Jane",
"lastname": "Doe",
"accountKey": "CRM-100245",
"mobile": "+61400000000"
},
"denomination": 50,
"expiryDays": 90,
"cardId": "YOUR_REWARDSTAR_CARD_ID",
"externalRef": "braze-qa-2026-07-22-001",
"idempotencyKey": "braze-qa-2026-07-22-001"
}
Liquid-templated JSON sample (paste into Braze)
Use the simple example above for most setups. Keep externalRef unique for every intended card. Switch to the advanced example only when denomination, expiry, or account key must vary per user or event.
cardId. Prefer the same string for externalRef and idempotencyKey (or the Idempotency-Key header).unsubscribeUrl is no longer used. Earlier versions of this guide asked you to send Braze's unsubscribe link in the body. Incentable now ignores it: recipients unsubscribe on Incentable's own page, and with a Braze integration that unsubscribe is synced to Braze. Existing campaigns that still send it keep working — you can remove it at your convenience.Braze setup steps
Aligns with Braze’s Create a webhook flow. Exact UI labels can vary by Braze version.
- Create a Webhook Campaign, or add a Webhook component in a Canvas.
- Webhook URL: paste the Incentable issue endpoint from above (also on the Braze integration's Connection card).
- HTTP method:
POST. - Request headers:
Authorization:Bearer <YOUR_API_KEY>Content-Type:application/json- Optional but recommended:
Idempotency-Keywith the same Liquid expression asexternalRef.
- Request body: choose JSON / raw body and paste the simple Liquid sample from Fixed values vs Braze Liquid (or the advanced sample if values must vary). Confirm personalization resolves from the user profile and/or trigger event properties.
- Compose / personalization: preview with a test user so email, name, denomination, and
externalReflook correct. - Delivery / trigger:
- Campaign: action-based on a custom event (example: reward earned, points threshold reached), or
- Canvas: place the webhook step after the qualification path.
- Optional multichannel: add a Braze email or push in the same campaign/Canvas to tell the user their gift card is on the way (Incentable still sends the RewardStar card email with the redeem link).
- Save, run a test send, then launch.
Official Braze guide: Create a webhook
How Braze retries interact with RewardStar responses
Braze retries only for certain HTTP responses (for example 408, 429, 5XX). Most other responses — including 401 Unauthorized and other 4XX — are not retried. Retry-After and X-Rate-Limit-* only affect backoff when the response is already retry-eligible; they do not create retries for non-retriable errors.
Full Braze table: Response codes and retry logic.
| Incentable response | Braze typically… | What you should do |
|---|---|---|
201 Created | Success, no retry | Done — a new card was issued. |
200 OK (idempotent replay) | Success, no retry | Safe — same prior issuance returned; no second card. |
202 Accepted (quarantined) | Success, no retry | The recipient has opted out of email. No card was issued or funded — the request is held for an admin to review. See Opted-out recipients. |
400 / 401 / 403 / 404 / 409 / 422 (most 4XX) | Usually not retried | Fix config/payload; check Braze webhook / Message Activity logs. |
402 insufficient fund | Usually not retried | Top up the program fund, or use test mode for QA. |
408 / 429 / 5XX | May retry | You must use a stable externalRef (and/or Idempotency-Key) so retries do not create duplicate cards. |
Success response
A successful issue returns 201 with the card id, amount, expiry, test flag and redeemUrl. A replay of the same idempotency key returns 200 with the original payload. Field-by-field details are on the RewardStar API page.
Braze does not need to store anything from the response. Incentable emails the card and redeem link to the recipient.
Opted-out recipients
If the member has previously unsubscribed from Incentable emails, Incentable does not issue the card. Instead it holds the request in quarantine and returns 202 Accepted with "quarantined": true and a quarantineId. Nothing is drawn from the fund.
Program admins are notified and can review quarantined requests on the RewardStar card's Issue Cards page, then either Release & issue (for example, if the recipient has asked to receive it) or Discard. Resending the same externalRef while a request is in quarantine returns the same 202 rather than creating a second request.
Idempotency & duplicates
Because Braze may retry on 408 / 429 / 5XX, design every webhook body so a retry cannot mint a second card.
| Concept | Rule |
|---|---|
externalRef uniqueness | Unique per cardId, not across the whole program. The same externalRef can exist on a different RewardStar card template. |
| Choosing a Braze-side key | Use something that will not change on retry: e.g. braze-{campaign_or_canvas_id}-{user_id}-{reward_or_event_id}. Avoid timestamps or random values that regenerate on each attempt. |
Idempotency-Key / idempotencyKey | Prefer the same stable value as externalRef. The API resolves: body idempotencyKey → Idempotency-Key header → externalRef → a one-off generated key. A generated key changes on every retry, so it gives no duplicate protection. |
201 vs 200 | 201 = new card. 200 = safe replay of a completed issuance for the same idempotency key. |
409 | Conflict — either a card with this externalRef already exists for this cardId (DUPLICATE_EXTERNAL_REF), or an issuance is still in progress for the idempotency key (IDEMPOTENCY_IN_PROGRESS). Braze typically does not retry 409. For an already-issued duplicate, treat as “card already exists” (response may include existing card summary without redeemUrl). |
Troubleshooting
Start in Braze Message Activity / webhook error logs for the campaign or Canvas step, then map the HTTP status. The RewardStar API page lists every error code.
| Status / signal | Plain language | What to fix |
|---|---|---|
400 validation / NO_CARD_SPECIFIED | Payload missing required fields, bad types, or no cardId and no default card on the integration. | Check Liquid (empty names/email), denomination as a number, and set cardId or configure a default RewardStar card. |
400 BRAZE_CREDENTIALS_REQUIRED | The Braze integration has no Braze REST cluster or API key saved. | Save them on the integration's Braze REST API card. |
401 | Invalid or missing API key. | Fix Authorization: Bearer …. Braze will not keep retrying most 401s — correct the key and resend. |
403 | API key lacks rewardStar: write. | Ask Incentable to enable RewardStar Write on the integration. |
202 with quarantined: true | Recipient has opted out of email; card held for review. | Expected. An admin releases or discards it in Incentable. |
402 / INSUFFICIENT_FUND | Program fund balance too low for face value + fees. | Top up the fund, or use a test-mode card for QA. |
404 | RewardStar card template not found. | Confirm cardId (or default) is correct for this program. |
409 / DUPLICATE_EXTERNAL_REF | That externalRef was already used for this cardId. | Expected on a true duplicate. Use a new externalRef only when you intend a new card. |
409 / IDEMPOTENCY_IN_PROGRESS | A prior attempt with the same idempotency key is still processing. | Wait briefly; look up by externalRef if needed (rewardStar: read). Do not invent a new key for the same reward. |
422 SETUP_INCOMPLETE_CATALOGUE | Card has no gift card catalogue assigned. | Finish RewardStar card setup in Incentable. |
422 SETUP_INCOMPLETE_DENOMINATIONS | No produced denomination images. | Produce card images for the template. |
422 SETUP_INCOMPLETE_CLIENT_NAME | Client name missing in branding. | Complete branding setup. |
422 DENOMINATION_NOT_PRODUCED | Requested amount exists in config but that denomination image was not produced. | Produce that denomination, or send a produced amount. |
| Braze defers the host | Many failures to Incentable caused Braze to pause sends to this host. | Fix the root cause, wait for cooldown, then retest. |
Test plan
- Prefer a RewardStar card in test mode so QA does not draw down the fund.
- In Braze, send a test webhook to a known inbox with a unique
externalRef(for examplebraze-qa-<date>-001). - Confirm:
- Braze shows a successful webhook delivery (
201). - Recipient receives the Incentable/RewardStar email.
- Card appears issued in Incentable (and
isTest: trueif using test mode).
- Braze shows a successful webhook delivery (
- Replay / retry simulation: send again with the same
externalRefand same idempotency key.- Expect either
200(idempotent replay) or409(duplicateexternalRef) — both mean no second card was created. Confirm only one card exists.
- Expect either
- Intentionally send with a bad API key.
- Expect
401. - Confirm Braze does not keep retrying that failure (per Braze
4XXrules).
- Expect
- Optional: trigger a real Canvas/campaign path with a QA user before go-live.
Pre-launch checklist
- Braze package includes Webhooks (confirmed with Braze AM/CSM if needed)
- Webhook Campaign or Canvas webhook step created
- Trigger / Canvas path matches the intended reward moment
- Incentable Braze integration created; RewardStar Write enabled
- Braze REST cluster and
email.statusAPI key saved on the integration - API key stored securely; used only in
Authorizationheader (not in the URL) - RewardStar card template active; denominations produced; branding complete
- Program fund funded or test mode used for QA then switched for production
- Default RewardStar card set or
cardIdincluded in the Braze body - Liquid maps email, first name, last name, denomination correctly
- Stable unique
externalRef(and matchingidempotencyKey/Idempotency-Key) on every send - Test send:
201, email received, one card issued - Same-key resend:
200or409, still only one card - Bad-auth test:
401, no Braze retry loop -
unsubscribeUrlremoved from older webhook bodies (optional — it is ignored) - Optional Braze email/push copy reviewed for the multichannel campaign
- Owners know where to check Braze Message Activity and Incentable Integrations activity
Related
- RewardStar Card (Admin) — set up the card template before Braze issues against it
- RewardStar API — full issue/lookup reference
- Connect Braze Webhooks to Prize Draws — enter members into a prize draw from the same Braze integration
- API Overview — base URL, auth, getting your API key
- Braze — Create a webhook
- Braze — Response codes and retry logic
