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’s Custom API. 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.
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. |
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). |
Custom API key with rewardStar: write | Required to issue cards. Add rewardStar: read if you will look up cards later. |
| Optional: Default RewardStar card | If set on the Custom API integration (defaultRewardStarCardId), 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 select (or create) your Custom API integration.
- Enable RewardStar permissions:
- Write — required to issue cards (
rewardStar: write) - Read — optional, for looking up issued cards (
rewardStar: read)
- Write — required to issue cards (
- Generate the API key and store it in a secure password manager.
- Optionally set Default RewardStar card so Braze payloads can omit
cardId.
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 Custom API base URL is also shown under Integrations in the Admin dashboard. See the RewardStar API reference for full field and response details.
Direction: Braze → Incentable (outbound webhook). Incentable does not call Braze for this flow.
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. If omitted, the API falls back to body idempotencyKey, then externalRef, then a random value. |
Request body for the Braze webhook composer
Field reference
| Field | Required | Default | Description |
|---|---|---|---|
member | Yes | — | Recipient object (see below). |
member.email | Yes | — | Recipient email. Used for delivery and member match/create. |
member.firstname | Yes | — | First name. |
member.lastname | Yes | — | Last name. |
member.accountKey | No | — | External account id. If provided, Incentable matches the member by accountKey first, then by email. |
member.mobile | No | — | Mobile number. |
denomination | Yes | — | Face value in dollars (number). Must match a produced denomination on the RewardStar card. |
expiryDays | No | 90 | Days until expiry. Integer from 30 to 365. |
cardId | Conditional | — | RewardStar card template id. Required unless a default card is configured on the integration. |
externalRef | Strongly recommended | — | Your unique reference for this card. Max 255 chars. Unique per cardId (not program-wide). Critical for Braze retries. |
idempotencyKey | Recommended | Falls back to header / externalRef / random | Max 255 chars. Prefer the same stable value as externalRef, or send Idempotency-Key header. |
Recommended Braze → payload mapping (Liquid)
| Incentable field | Suggested Braze source |
|---|---|
member.email | {{${email_address}}} |
member.firstname | {{${first_name}}} |
member.lastname | {{${last_name}}} |
member.accountKey | Custom attribute, e.g. {{custom_attribute.${account_key}}} |
member.mobile | {{${phone_number}}} or a custom attribute |
denomination | Event property or custom attribute, e.g. {{event_properties.${gift_card_amount}}} — or a fixed number |
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 | Usually leave default 90, or set a fixed integer |
externalRef. Braze may retry on 408, 429, and 5XX. Without a stable key, a retry can issue a second card.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)
Adjust attribute / event property names to match your Braze workspace. Keep externalRef unique for every intended card.
{
"member": {
"email": "{{${email_address}}}",
"firstname": "{{${first_name}}}",
"lastname": "{{${last_name}}}",
"accountKey": "{{custom_attribute.${account_key}}}",
"mobile": "{{${phone_number}}}"
},
"denomination": {{event_properties.${gift_card_amount}}},
"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}}}"
}
cardId. Prefer the same string for externalRef and idempotencyKey (or the Idempotency-Key header).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.
- 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 Liquid sample. 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. |
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 fields
On success, Incentable returns JSON shaped like:
{
"data": {
"id": "issued-card-document-id",
"status": "issued",
"amount": 50,
"expiresAt": "2026-10-20T00:00:00.000Z",
"redeemUrl": "https://redeem.rewardstarcard.com/?t=...",
"isTest": false,
"externalRef": "braze-..."
},
"memberId": "member-document-id",
"memberCreated": false,
"message": "RewardStar card issued successfully"
}
| Field | Meaning |
|---|---|
data.id | Issued card id (RewardStar code document id). |
data.status | Usually issued. |
data.amount | Face value issued. |
data.expiresAt | Expiry timestamp (ISO 8601). |
data.redeemUrl | One-time redeem link — returned on issue only. |
data.isTest | true if the card template is in test mode. |
data.externalRef | Echo of your reference (if provided). |
memberId | Matched or newly created member id. |
memberCreated | true if Incentable created a Pending member for this request. |
Notes
redeemUrlis returned on issue (POST) only.GET /rewardstar/cards/{id}lookup does not returnredeemUrl.- Braze usually does not need to store
redeemUrlif Incentable emails the card to the recipient. 201= new issue.200= idempotent replay of a previous issuance (same completed idempotency key).
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 → random. |
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:
| 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. |
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. | Update key permissions in Incentable Integrations. |
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 Custom API key created;
rewardStar: writeenabled - 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 - 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
- API Overview — base URL, auth, getting your API key
- Braze — Create a webhook
- Braze — Response codes and retry logic
