Incentable

RewardStar API

Issue and look up RewardStar gift cards via the Custom API.

RewardStar API

Issue prepaid RewardStar gift cards to members and look up previously issued cards. This surface is part of the Custom API (externalApi).

Base URL

https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external

Authentication & permissions

Use a Bearer API key (inc_…):

Authorization: Bearer YOUR_API_KEY
ActionRequired permission
Issue a cardrewardStar → write
Look up a cardrewardStar → read

Keys come from a Custom API or Braze integration in the Admin dashboard — see Getting your API key. Optionally set a Default RewardStar Card on the integration so requests can omit cardId.

Issuing from Braze? Follow Braze → RewardStar Cards. Braze integrations also sync recipient unsubscribes back to Braze, and need Braze REST credentials saved before they can issue.

Issue a card

POST /rewardstar/cards

Request body

FieldTypeRequiredDescription
member.emailstringYesRecipient email
member.firstnamestringYesFirst name
member.lastnamestringYesLast name
member.accountKeystringNoMatched before email when present
member.mobilestringNoOptional mobile
denominationnumberYesFace value in dollars; must be a produced denomination on the card
expiryDaysnumberNo30–365 (default 90)
cardIdstringConditionalCard id (shown on RewardStar Card pages in Admin); required unless a default is configured
externalRefstringNoYour idempotent reference (unique per cardId)
idempotencyKeystringNoExplicit idempotency key

Also accepted: Idempotency-Key header. Resolution order: body idempotencyKey → header → externalRef → generated key.

Send an externalRef with every request. A generated key is different on every attempt, so it does not stop a retry from issuing a second card.

Example

curl -X POST \
  "https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external/rewardstar/cards" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: crm-order-12345" \
  -d '{
    "cardId": "abc123",
    "denomination": 50,
    "expiryDays": 90,
    "externalRef": "crm-order-12345",
    "member": {
      "email": "jane@example.com",
      "firstname": "Jane",
      "lastname": "Doe",
      "accountKey": "ACME-001"
    }
  }'

Success response (201)

{
  "data": {
    "id": "codeDocId",
    "status": "issued",
    "amount": 50,
    "expiresAt": "2026-10-19T06:00:00.000Z",
    "redeemUrl": "https://redeem.rewardstarcard.com/?t=…",
    "isTest": false,
    "externalRef": "crm-order-12345"
  },
  "memberId": "memberDocId",
  "memberCreated": true,
  "message": "RewardStar card issued successfully"
}

Opted-out recipients (202)

If the member has unsubscribed from Incentable emails, no card is issued and nothing is drawn from the fund. The request is held for an admin to review and the API returns 202 Accepted:

{
  "quarantined": true,
  "quarantineId": "quarantineDocId",
  "reasonId": "member_email_opt_out",
  "reasonLabel": "Member opted out of email",
  "message": "Member has opted out of email. Card was not issued or funded. Awaiting admin review."
}

Admins release or discard quarantined requests from the RewardStar card's Issue Cards page. Resending the same externalRef while it is pending returns the same 202.

Replays and duplicates

Idempotent replays of the same key return 200 with the original payload. Duplicate externalRef for the same cardId returns 409 with the existing card (no redeemUrl on that conflict payload). The same externalRef may be reused on a different RewardStar card.

Behaviour notes

  • Member upsert: accountKey → email → create Pending member (encrypted fields + auth sync).
  • Email: Branded HTML is compiled server-side from the card template (CTA, produced card image, placeholders). Recipients receive the redeem link by email.
  • Fund: Live cards draw down the program fund (face + fee + GST where applicable). Cards with test mode on skip fund movement and set isTest: true.
  • redeemUrl: Returned only on issue (and idempotent replay). The plaintext token is never stored; GET lookup does not include redeemUrl.

Common errors

StatusCodeMeaning
400NO_CARD_SPECIFIEDNo cardId and no default configured
400BRAZE_CREDENTIALS_REQUIREDBraze integration has no Braze REST cluster / API key saved
400INVALID_ARGUMENT / VALIDATION_ERRORBad body or denomination not on the card
402INSUFFICIENT_FUNDProgram fund balance too low
403PERMISSION_DENIEDKey lacks rewardStar write
409DUPLICATE_EXTERNAL_REFexternalRef already used for this cardId
409AMBIGUOUS_EXTERNAL_REFGET by externalRef matched multiple cards — pass ?cardId=
409IDEMPOTENCY_IN_PROGRESSSame key still processing
422SETUP_INCOMPLETE_CATALOGUE / SETUP_INCOMPLETE_DENOMINATIONS / SETUP_INCOMPLETE_CLIENT_NAMECard setup not finished in Admin
422DENOMINATION_NOT_PRODUCEDAmount is configured but its card image was not produced
429RATE_LIMIT_EXCEEDEDRate limit reached for the key

Get an issued card

GET /rewardstar/cards/{id}

{id} may be the issued code document id or an externalRef. When looking up by externalRef, you can pass ?cardId= to disambiguate (references are unique per card, not across every card in the program).

curl -X GET \
  "https://us-central1-incentable-app-37d9c.cloudfunctions.net/externalApi/api/v1/external/rewardstar/cards/crm-order-12345?cardId=YOUR_CARD_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example response

{
  "data": {
    "id": "codeDocId",
    "status": "issued",
    "amount": 50,
    "cardId": "abc123",
    "memberId": "memberDocId",
    "externalRef": "crm-order-12345",
    "isTest": false,
    "expiresAt": "2026-10-19T06:00:00.000Z",
    "issuedAt": "2026-07-21T06:00:00.000Z"
  }
}