Skip to main content

Promotions

Manage of general promotions.

All JSON response field names in this API are camelCase, generated automatically from the underlying C# model — with a single deliberate exception, APIRequireIssyTermsAcceptance/apiRequireIssyTermsAcceptance (kept as-is for backwards compatibility, casing differs by endpoint — see below). Request bodies accept PascalCase field names as shown (matching the API's internal model); this doc uses that same PascalCase for requests throughout for consistency with the rest of the site.

termsAndConditions is an HTML string, written with a rich-text editor in issy's backoffice — e.g. "<p>This is the space where the Terms and Conditions of the <b><u>Hennessy Bahamas Loyalty Program</u></b> will be displayed.</p>". Render it as sanitized HTML (e.g. DOMPurify), not as plain text. It's null when nothing is loaded. To build the full consent UI (privacy policy, brand opt-in, issy's legal pages) use Get Terms display — see Showing the consent UI.

Available Promotions​

Get list of available Promotions. The response is a bare JSON array (not wrapped in an envelope).

GET /promotions
RESPONSE (200)
[
{
"id": "{promotion id}",
"tenantId": "{tenant id}",
"name": "{promotion name}",
"tags": "{array of strings - free-form labels assigned to the promotion in the backoffice (e.g. ["summer", "vip"]). Trimmed, case-insensitively de-duplicated, returned in the order they were saved. Always an array, [] when there are no tags}",
"description": "{promotion description}",
"code": "{promotion unique code}",
"enabled": "{promotion enabled}",
"mainImageUrl": "{promotion image url}",
"type": "{promotion type}",
"prizeType": "{promotion prize type}",
"requirePOPCode": "{whether participating requires a POP code - see Choosing a participation flow in Participations}",
"mechanicType": "{promotion mechanic type}",
"startDate": "{date when promotion starts}",
"endDate": "{date when promotion ends}",
"fraudPreventionModuleActivation": "{is active the fraud prevention module}",
"termsAndConditions": "{HTML string - promotion terms and conditions, see note below. Can be null}",
"policyPrivacyUrl": "{promotion privacy policy url}",
"apiRequireIssyTermsAcceptance": "{true/false, never null - whether the API enforces T&C acceptance for this promotion. camelCase here (list endpoint) - see Terms & Conditions Acceptance in Get Started}",
"requireAgegateConfiguration": "{true/false, never null - whether the API enforces a minimum age on registration and participation for this promotion - see Age Gate in Get Started}",
"minimumAge": "{integer, never null - minimum age (in years) the user must have. 0 when not configured. Only enforced when requireAgegateConfiguration is true and minimumAge > 0}"
}
]

An empty array ([]) means the tenant has no available promotions — not an error.

Error responses:

HTTPerrorCodeCause
404PROMOTION_NOT_FOUNDThe search returned null (unexpected — normally an empty array is returned instead).
401 / 406INVALID_HEADER_CONTENTMissing/invalid issy-token or issy-tenant-id.
500INTERNAL_ERRORUnexpected server error.

Get Promotion​

Get an individual Promotion's full information, including its participation form and product list.

GET /promotions/{promotion id}
RESPONSE (200)
{
"id": "{promotion id}",
"tenantId": "{tenant id}",
"name": "{promotion name}",
"tags": "{array of strings - free-form labels assigned to the promotion in the backoffice (e.g. ["summer", "vip"]). Trimmed, case-insensitively de-duplicated, returned in the order they were saved. Always an array, [] when there are no tags}",
"description": "{promotion description}",
"code": "{promotion unique code}",
"enabled": "{promotion enabled}",
"mainImageUrl": "{promotion image url}",
"type": "{promotion type}",
"prizeType": "{promotion prize type}",
"requirePOPCode": "{whether participating requires a POP code - see Choosing a participation flow in Participations}",
"requireProofOfPurchase": "{whether participating requires an invoice/receipt image - only present in this detail response, not in the list above - see Choosing a participation flow in Participations}",
"proofOfPurchaseType": "{0 = invoice/receipt OCR, 1 = photo (AI rule evaluation). For a classic (non-loyalty) promotion this is only meaningful when requireProofOfPurchase is true, and is mutually exclusive with the invoice flow - photo participation isn't exposed as a one-step API endpoint for classic promotions yet. Loyalty programs behave differently - see Choosing a participation flow in Participations}",
"mechanicType": "{promotion mechanic type}",
"startDate": "{date when promotion starts}",
"endDate": "{date when promotion ends}",
"fraudPreventionModuleActivation": "{is active the fraud prevention module}",
"termsAndConditions": "{HTML string - promotion terms and conditions, see note below. Can be null}",
"policyPrivacyUrl": "{promotion privacy policy url}",
"APIRequireIssyTermsAcceptance": "{true/false, never null - whether the API enforces T&C acceptance for this promotion. PascalCase here (detail endpoint, kept for backwards compatibility) - see Terms & Conditions Acceptance in Get Started}",
"requireAgegateConfiguration": "{true/false, never null - whether the API enforces a minimum age on registration and participation for this promotion - see Age Gate in Get Started}",
"minimumAge": "{integer, never null - minimum age (in years) the user must have. 0 when not configured. Only enforced when requireAgegateConfiguration is true and minimumAge > 0}",
"typeDescription": "{promotion type as text: Online, In Store}",
"prizeTypeDescription": "{promotion prize type as text, e.g. Enter to win, Instant Gratification, Time-Based Coupon, Top Ranking - useful as a badge/label}",
"activatePromotionWebButtonText": "{custom text for the promotion's activation button - null when not set, use your own default text}",
"onlineRedemptionType": "{0 = Single Code, 1 = Multicode, 2 = Pass Through, 3 = Cashback - null when not set}",
"onlineRedemtpionUrl": "{URL the user is sent to - for Pass Through (onlineRedemptionType 2) the activation button just opens this URL, there is no participation flow. Note: the field name is misspelled ('Redemtpion') in the API}",
"products": [
{
"product": {
"id": "{product id}",
"name": "{product name}"
}
}
],
"form": {
"formItems": [
{
"id": "{form item identifier}",
"statement": "{question statement}",
"imageUrl": "{image associated to question}",
"type": "{type of question: 0 => text, 1 => single-choice, 2 => multi-choice, 3 => image}",
"typeString": "{question type as text: Text, Single-Choice, Multi-Choice, Image}",
"fields": [
{
"id": "{field id}",
"name": "{name of field - not used for Text or Image questions}",
"imageUrl": "{final image url, used for consultation}",
"imageUrlBase64": "{image decoded in base64 - only for Image form items}",
"value": "{value of consumer answer}",
"hasPoints": "{whether the question accumulates points}",
"points": "{points of question}"
}
],
"totalPoints": "{maximum total possible points}",
"minimalPoints": "{minimum points to approve}"
}
]
}
}

Note the casing difference: this endpoint returns APIRequireIssyTermsAcceptance (PascalCase), while the list endpoint above returns apiRequireIssyTermsAcceptance (camelCase) for the exact same field. This is intentional and applies the same way to Loyalty Programs and Rewards — see Terms & Conditions Acceptance.

Error responses:

HTTPerrorCodeCause
404PROMOTION_NOT_FOUNDpromotion id doesn't exist for this tenant.
401 / 406INVALID_HEADER_CONTENTMissing/invalid issy-token or issy-tenant-id.
500INTERNAL_ERRORUnexpected server error.
error response example
{
"success": false,
"errorCode": "PROMOTION_NOT_FOUND",
"message": "Profile not found."
}

Get Promotion Locations​

Get the locations where a promotion is available. Promotions, loyalty programs and rewards share the same underlying model, so this single endpoint works for all three — pass a promotion id, a loyalty program id or a reward id. The response is a bare JSON array (not wrapped in an envelope).

Only locations with status Available are returned (locations with a pending invitation, a failed/expired audit, or that reached their redemption amount are excluded). There is no pagination and no limit on the number of locations returned.

GET /promotions/{promotion id}/locations
RESPONSE (200)
[
{
"id": "{location id}",
"name": "{location name}",
"address": "{location address}",
"city": "{location city}",
"latitude": "{location coordinates latitude, number}",
"longitude": "{location coordinates longitude, number}"
}
]

An empty array ([]) means the promotion has no available locations — not an error.

Error responses:

HTTPerrorCodeCause
404PROMOTION_NOT_FOUNDpromotion id doesn't exist for this tenant.
401 / 406INVALID_HEADER_CONTENTMissing/invalid issy-token or issy-tenant-id.
500INTERNAL_ERRORUnexpected server error.