Incentable

Connect Braze Webhooks to RewardStar

Set up a Braze integration so campaigns and Canvas steps issue RewardStar gift cards, and recipient unsubscribes sync back to Braze.

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.

Issuing a card is a custom webhook from Braze → Incentable. It is not a Braze Alloy partner connector. The only call Incentable makes to Braze is the unsubscribe sync.

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

RequirementNotes
Webhooks enabled on your Braze packageAvailability 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 stepNeeded to configure the call to Incentable.
A defined triggerCustom 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 permissionUsed by Incentable only to sync unsubscribes. Created in Braze under Settings → APIs and Identifiers.
Your Braze REST endpointThe REST cluster for your workspace, for example https://rest.au-01.braze.com. Shown in Braze next to your API keys.

Incentable / RewardStar

RequirementNotes
Active RewardStar card templateWith produced denominations (card images produced for the amounts you will issue).
Program fund fundedOr use the card in test mode for QA (test mode does not draw down the fund).
A Braze integration in IncentableWith RewardStar: Write permission. Add Read if you will look up cards later.
Braze REST credentials saved on the integrationRequired. Card issue requests are rejected until they are saved (see below).
Optional: Default RewardStar cardIf set on the integration, Braze does not need to send cardId in every payload.

Get credentials from Incentable

  1. Log in to the Incentable Admin Dashboard.
  2. Select the program you want to issue RewardStar cards for (API keys are scoped to a single program).
  3. Open Integrations and add a Braze integration (or open your existing one).
  4. 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.
  5. Optionally set Default RewardStar Card on the same card so Braze payloads can omit cardId.
  6. Save your Braze REST credentials (next section).
  7. Generate the API key and store it in a secure password manager.
Already using a Custom API integration for Braze? It still issues cards, but unsubscribes will not sync back to Braze. Create a Braze integration, point your Braze webhook at its key, then deactivate the Custom API integration.
Security: Treat the API key as a secret. Put it only in the Braze webhook Authorization header. Never put the API key in the webhook URL. Prefer Braze secrets / credential fields if your workspace supports them.

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.

  1. In Braze, go to Settings → APIs and Identifiers and create a REST API key with only the email.status permission.
  2. In Incentable, open the Braze integration and find the Braze REST API card.
  3. Choose your REST cluster (for example AU-01 — rest.au-01.braze.com).
  4. Paste the Braze API key and click Save Changes. Incentable stores it encrypted and shows only a masked prefix afterwards.
Never put the Braze REST key in a Braze campaign, email or webhook body. It belongs only in the Incentable integration settings. Braze does not let you edit permissions on an existing key — create a new key if your requirements change.

If the credentials are missing, card issue requests return 400 with code BRAZE_CREDENTIALS_REQUIRED.

Endpoint Braze should call

ItemValue
MethodPOST
Path/rewardstar/cards
Full URLhttps://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

HeaderRequiredValue
AuthorizationYesBearer <YOUR_API_KEY>
Content-TypeYesapplication/json
Idempotency-KeyRecommendedStable 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 per cardId. Critical for Braze retries.
Incentable fieldSuggested Braze source
member.email{{${email_address}}}
member.firstname{{${first_name}}}
member.lastname{{${last_name}}}
member.accountKeyFixed value or Liquid — see Fixed values vs Braze Liquid
member.mobile{{${phone_number}}} or a custom attribute
denominationFixed number or Liquid — see Fixed values vs Braze Liquid
cardIdFixed string, or omit if default card is configured
externalRefMust be unique per card issue — e.g. Canvas/campaign + user id + reward id on the trigger event
expiryDaysFixed integer or Liquid — see Fixed values vs Braze Liquid
Always set a stable 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, and expiryDays → fixed or Liquid.
  • Start with fixed values where possible. Use Liquid when the value must change per user or per event.
FieldFixed exampleLiquid / variable example
accountKey"CRM-100245"Braze user id {{${user_id}}} or custom attribute {{custom_attribute.${account_key}}}
denomination50Event property {{event_properties.${gift_card_amount}}} or custom attribute {{custom_attribute.${reward_amount}}}
expiryDays90Custom attribute {{custom_attribute.${card_expiry_days}}}

Choosing accountKey

Prefer, in order:

  1. {{${user_id}}} — always present in Braze, stable, no custom attribute setup.
  2. Custom attribute — when you already sync a CRM/external id into Braze and want Incentable to match on that same key.
  3. 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.

If you configured a default RewardStar card in Incentable, you can omit 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.

  1. Create a Webhook Campaign, or add a Webhook component in a Canvas.
  2. Webhook URL: paste the Incentable issue endpoint from above (also on the Braze integration's Connection card).
  3. HTTP method: POST.
  4. Request headers:
    • Authorization: Bearer <YOUR_API_KEY>
    • Content-Type: application/json
    • Optional but recommended: Idempotency-Key with the same Liquid expression as externalRef.
  5. 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.
  6. Compose / personalization: preview with a test user so email, name, denomination, and externalRef look correct.
  7. 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.
  8. 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).
  9. 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 responseBraze typically…What you should do
201 CreatedSuccess, no retryDone — a new card was issued.
200 OK (idempotent replay)Success, no retrySafe — same prior issuance returned; no second card.
202 Accepted (quarantined)Success, no retryThe 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 retriedFix config/payload; check Braze webhook / Message Activity logs.
402 insufficient fundUsually not retriedTop up the program fund, or use test mode for QA.
408 / 429 / 5XXMay retryYou must use a stable externalRef (and/or Idempotency-Key) so retries do not create duplicate cards.
Host-level deferral: If most webhook requests to Incentable are failing, Braze may temporarily defer all sends to that host until a cooldown ends. Fix the root cause (auth, payload, fund, card setup), wait for the cooldown, then retest.

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.

ConceptRule
externalRef uniquenessUnique per cardId, not across the whole program. The same externalRef can exist on a different RewardStar card template.
Choosing a Braze-side keyUse 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 / idempotencyKeyPrefer 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 200201 = new card. 200 = safe replay of a completed issuance for the same idempotency key.
409Conflict — 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 / signalPlain languageWhat to fix
400 validation / NO_CARD_SPECIFIEDPayload 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_REQUIREDThe Braze integration has no Braze REST cluster or API key saved.Save them on the integration's Braze REST API card.
401Invalid or missing API key.Fix Authorization: Bearer …. Braze will not keep retrying most 401s — correct the key and resend.
403API key lacks rewardStar: write.Ask Incentable to enable RewardStar Write on the integration.
202 with quarantined: trueRecipient has opted out of email; card held for review.Expected. An admin releases or discards it in Incentable.
402 / INSUFFICIENT_FUNDProgram fund balance too low for face value + fees.Top up the fund, or use a test-mode card for QA.
404RewardStar card template not found.Confirm cardId (or default) is correct for this program.
409 / DUPLICATE_EXTERNAL_REFThat 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_PROGRESSA 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_CATALOGUECard has no gift card catalogue assigned.Finish RewardStar card setup in Incentable.
422 SETUP_INCOMPLETE_DENOMINATIONSNo produced denomination images.Produce card images for the template.
422 SETUP_INCOMPLETE_CLIENT_NAMEClient name missing in branding.Complete branding setup.
422 DENOMINATION_NOT_PRODUCEDRequested amount exists in config but that denomination image was not produced.Produce that denomination, or send a produced amount.
Braze defers the hostMany failures to Incentable caused Braze to pause sends to this host.Fix the root cause, wait for cooldown, then retest.

Test plan

  1. Prefer a RewardStar card in test mode so QA does not draw down the fund.
  2. In Braze, send a test webhook to a known inbox with a unique externalRef (for example braze-qa-<date>-001).
  3. Confirm:
    • Braze shows a successful webhook delivery (201).
    • Recipient receives the Incentable/RewardStar email.
    • Card appears issued in Incentable (and isTest: true if using test mode).
  4. Replay / retry simulation: send again with the same externalRef and same idempotency key.
    • Expect either 200 (idempotent replay) or 409 (duplicate externalRef) — both mean no second card was created. Confirm only one card exists.
  5. Intentionally send with a bad API key.
    • Expect 401.
    • Confirm Braze does not keep retrying that failure (per Braze 4XX rules).
  6. 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.status API key saved on the integration
  • API key stored securely; used only in Authorization header (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 cardId included in the Braze body
  • Liquid maps email, first name, last name, denomination correctly
  • Stable unique externalRef (and matching idempotencyKey / Idempotency-Key) on every send
  • Test send: 201, email received, one card issued
  • Same-key resend: 200 or 409, still only one card
  • Bad-auth test: 401, no Braze retry loop
  • unsubscribeUrl removed 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