Extended API Integration
Kard’s Extended API feature enhances our existing rewards endpoints with dynamic, per-user offer data. By requesting UI components through the supportedComponents query parameter, you can surface richer offer experiences to your end users — dynamic descriptions, call-to-action buttons, contextual tags, progress bars, boosted rewards, and logo decorations — without building custom logic to interpret raw offer data.
This guide covers how to request and render extended offer fields from the Get Offers by User and Get Locations by User endpoints.
Key Concepts
Supported Components
The Extended API uses a component-based model to deliver dynamic offer data. You tell Kard which UI components your app supports, and the API returns the relevant data for each offer. Kard evaluates each offer independently and returns only the components that apply to that offer and that you requested.
How Components Are Returned
The components included in the response depend on what you request via the supportedComponents query parameter and on each offer’s configuration.
Support as many components as possible. Kard renders each offer with the richest representation its state can take from the components you support, so the more you support, the more your users can see and act on. When an offer relies on a component you did not request — a cta to activate, a progressBar for a punch card, a boostedReward for a boost — Kard falls back to expressing that state through shortDescription and longDescription. If you don’t support those either, the state is folded into the offer’s name (for example, "World's Greatest Chicken - tap to activate").
- All components (
shortDescription,longDescription,baseReward,boostedReward,cta,tags,detailTags,logoFlare,progressBar): The full experience. Provides dynamic descriptions, formatted rewards, call-to-action buttons, contextual tags, logo decorations, and progress bars for both list and detail views. Best for apps that support interactive and visual elements. - Description-only components (
shortDescription,longDescription): Provides dynamic descriptions without interactive elements. Best for apps that cannot render buttons, tags, or progress bars. In this case, Kard uses a VIEW event on the offer as the activation signal. When a user views an offer detail page, you fire a VIEW attribution event. After the event, re-fetch the offer to display the updated descriptions reflecting the new user state.
At minimum, support shortDescription and longDescription. They are the universal fallback for offer state: when an offer requires a richer component your app doesn’t support (for example a cta or a progressBar), its state is expressed through these descriptions instead. Without them, that state is only available in a modified offer name — and your users may miss required actions like activating or boosting an offer.
Which components an offer surfaces depends on its configuration. For example:
- A standard activatable offer surfaces a
cta(andtags/detailTags) until it is activated. - A boostable offer surfaces a boost
ctabefore boosting, then aboostedReward(withbaseRewardstruck through) and alogoFlaredecoration after boosting. - A multi-redemption, punch-card, or progressive-reward offer surfaces a
progressBar(plus a matchingshortDescription). - A limited-supply offer surfaces a
"Limited supply"tag and remaining-redemption copy in its descriptions.
You can request any combination of components. Kard evaluates each offer independently and returns only the components that apply to that offer. If a component does not apply, it is simply omitted — always check for presence before rendering.
Implementation
Step 1: Add the supportedComponents Query Parameter
Append the supportedComponents query parameter to your existing Get Offers by User or Get Locations by User requests. Use repeated parameters for multiple component types.
Get Offers by User with all components:
Get Locations by User with all components:
Get Offers by User with description-only components:
For Get Locations by User, you must include include=offers in the query to receive offer data with components.
supportedComponents accepts only the values listed in the Supported Components table. Requesting an unknown value returns a 400 Invalid Request.
Step 2: Parse the components Object
When supportedComponents is provided and an offer is eligible for extended data, the response includes a components object within the offer attributes.
Example Response with all components (activatable offer, not yet activated):
Example components for a boostable offer (after the user has boosted it):
Before the offer is boosted, the same offer instead returns a boost cta (a SECONDARY button such as “Get 10%”) and no boostedReward/logoFlare. See Handle Call-To-Action Events.
Example components for a punch-card offer (rewards every 3rd purchase; user is 2 of 3):
See Rendering the Progress Bar for the full model and more examples.
Step 3: Render Components in Your UI
How you render the components depends on which ones you requested and which the offer returns. Always check for presence before rendering — an offer that isn’t eligible for a component simply omits it.
Descriptions and rewards
- Display
shortDescriptionon offer cards in list/browse views. - Display
longDescriptionon the offer detail page. - Display
baseRewardas the formatted reward amount (e.g., “5.7% cash back”). - If
boostedRewardis present, render it as the active reward and showbaseRewardwith a strikethrough to communicate the uplift (e.g.,5% cash back10% cash back).
Call-to-action button (cta)
- If
ctais present, display the call-to-action button usingbuttonText:- Style the button per
buttonStyle:PRIMARY(prominent, e.g. activation),SECONDARY(lower-emphasis, e.g. boost), orDISABLED(rendered but not interactive). - If
startIconis present, render it (an inline SVG string) before the button text. - When tapped, call the URL in
cta.action.urlusingcta.action.method(see Step 4a).
- Style the button per
- If
ctais absent, the offer requires no action right now (e.g. it has already been activated) — hide the button.
Tags
- Render
tagsas overlays or badges on the offer card in list/browse views (may be empty). - Render
detailTagsas labels on the offer detail page.
Logo flare (logoFlare)
- If
logoFlareis present, decorate the offer’s logo/thumbnail:- Draw a border around the logo using
borderColor(PRIMARYorSECONDARY, mapped to your theme colors). - If
badgeis present, overlay thebadge.icon(an inline SVG) at the corner given bybadge.position.
- Draw a border around the logo using
Progress bar (progressBar)
- If
progressBaris present, render it per Rendering the Progress Bar. Use the compactdefaultlayout on cards and the richerdetailslayout on the offer detail page.
All components, offer not activated:
All components, offer is activated:
If you requested description-only components (shortDescription and longDescription):
This approach is for issuers that cannot render interactive call-to-action buttons or graphical elements. Instead of using a call-to-action button to activate or boost offers, the VIEW event serves as the activation signal. Progress and state are still communicated through the descriptions (e.g. shortDescription reads “2 of 3 purchases” for a punch-card offer).
- Display
shortDescriptionon offer cards in list/browse views. - Display
longDescriptionon the offer detail page. - When a user navigates to the offer detail page, fire a VIEW attribution event (see Step 4b).
- After the VIEW event, re-fetch the offer to get updated descriptions that reflect the new user state.
- Re-render the offer with the updated
shortDescriptionandlongDescription.
Important: Without a call-to-action button, the user has no explicit activation action. The VIEW event acts as a proxy for activation. You must re-fetch and re-render the offer after firing the VIEW event to display the updated state to the user.
Step 4a: Handle Call-To-Action Events
When a user taps a call-to-action button, call the endpoint provided in cta.action using the given method. Use cta.action.url and cta.action.method exactly as provided — the path, query string, and method are pre-configured by Kard. Different offers point at different actions:
-
Activation offers point at the activate endpoint:
-
Boost offers point at the boost endpoint:
The cta.action.url Kard returns already includes include=offer and your requested supportedComponents, so the response contains the updated offer:
Activation response (201 Created):
Boost response (201 Created): identical in shape, but eventCode is BOOST. The included offer now carries the elevated boostedReward, the struck-through baseReward, and a logoFlare:
Use the updated offer from included to immediately refresh your UI without re-fetching the full offer list. After a successful action the offer’s components change (for example, an activation drops the cta and sets detailTags to ["Activated"]; a boost drops the boost cta and adds boostedReward + logoFlare).
Step 4b: Handle VIEW Event Activation (Description-Only)
If you are only using shortDescription and longDescription (no cta), use the VIEW attribution event to signal that a user has engaged with an offer. This acts as the activation trigger.
When a user opens an offer detail page, fire a VIEW event:
After a successful VIEW event, re-fetch the offer with your supported components to get the updated descriptions:
The descriptions will now reflect the updated user state:
Re-render the offer detail page with the updated longDescription, and update the offer card with the new shortDescription in your list views.
We recommend integrating with call-to-action components when possible. The call-to-action flow gives users a clear, explicit action to activate and boost offers and provides a better user experience than the implicit VIEW event approach.
Rendering the Progress Bar
The progressBar component tracks a user’s progress toward a reward. It powers three offer types with a single, fully data-driven model — you do not need to know the offer type to render it correctly:
- Redemption count — a multi-use offer, tracking how many of
Nredemptions the user has used. - Punch card — an offer that rewards every
Nqualifying purchases, tracking progress toward the next reward. - Progressive / tiered rewards — an offer whose reward grows as the user climbs tiers.
Anatomy
total— the number of nodes/steps in the bar.currentProgress— how far the user has progressed (clamp to0..totalwhen rendering).labels— the left/right text that flanks the bar, per layout (see below).segments— how to draw the bar, per layout, plus the per-nodeprogressfill array. Absent for a plain continuous bar.
Pick the layout for your surface
A single progressBar payload carries two layouts so you can render the same data differently on a card versus a detail page:
default— the compact layout for list/browse/card views. Uselabels.defaultandsegments.default.details— the richer layout for the offer detail page. Uselabels.detailsandsegments.details, each falling back todefaultwhen not present.
Choose the visual style
The resolved segment configuration (segments.default or segments.details) determines the visual style:
- Continuous bar — when
segmentsis absent. Draw a single bar filled tocurrentProgress / total, flanked by the left/right labels. (Used for redemption-count offers with more than 5 redemptions.) - Segmented bars — when
segmentsis present with noseparator. Draw one bar per node (totalnodes). Fill each nodeitoprogress[i].completed / progress[i].total. Nodes support partial fill (e.g.2 / 4), which a punch card uses to show progress within the current step. If a segment provides per-nodelabels, render each label next to its bar. - Icon tiers with line separators — when
segments.<layout>.separatorisLINEandpositionisFULL_WIDTH. Draw theicon(an inline SVG) for each node, connected by horizontal lines, with the per-nodelabels[i].titlebeneath. Icons are binary (active/inactive) and ignore partial fill. (Used for progressive/tiered rewards.)
Fill and selection rules
- Per-node fill comes from
segments.progress[i](completed / total). Whenprogressis absent, a node is either full or empty based on selection. selectiondecides which nodes read as “reached”:CURRENT— nodes with index< currentProgress.CURRENT_AND_BELOW— nodes with index<= currentProgress.
iconSVGs are themeable via the CSS custom properties--icon-fill,--icon-outline, and--icon-detail. Set these on the icon’s container to match your theme’s active/inactive colors; icons that don’t reference the variables fall back to their embedded colors.positionplaces the segments relative to the labels:LEFT,RIGHT, orFULL_WIDTH(segments span the full width with labels above).
Example: redemption-count bar
A multi-use offer redeemable up to 3 times, where the user has redeemed 1. Five or fewer redemptions render as segmented nodes with a check icon; more than five render as a continuous bar.
Renders as three check icons, the first filled. On the detail page a “Redemptions” label sits to the left.
Example: punch card
An offer that rewards every 3rd qualifying purchase, with the user 2 of 3 into the current card:
Renders as three bars, the first two filled and the third empty, with a “2 of 3” label to the right. Once the user redeems every reward the offer allows, every node reads full and the copy switches to a “reward redeemed” message.
Example: progressive / tiered rewards
An offer with three reward tiers (5%, 10%, 15%) where the user has reached the first tier:
Renders as three ring icons joined by lines with “5%”, “10%”, “15%” beneath — the reached tiers highlighted. When a progressive offer is also a punch card, Kard omits the icon/separator so the raw segmented bars can show partial fill toward the next tier.
Rendering algorithm
- Pick the layout:
detailson the detail page, otherwisedefault. - Resolve
labels = labels[layout] ?? labels.defaultandsegment = segments[layout] ?? segments.default. - If there is no
segmentsobject, draw a continuous bar filled tocurrentProgress / totalbetween the left/right labels. Done. - Otherwise, for each node
iin0..total-1, compute its fill:progress[i].completed / progress[i].totalif provided, else full/empty perselection. - If
segment.separatorisLINE(andpositionisFULL_WIDTH), drawicons joined by lines withlabels[i].titlebeneath (icons are binary). Otherwise draw one bar per node, applying each node’s fractional fill and any per-node label. - Place the label block according to
position(LEFT,RIGHT, orFULL_WIDTH).
Progress is display-only and dynamic. Progress bar values reflect the user’s current state at request time and change as the user transacts. Do not cache them across sessions; re-fetch to get the latest state.
Component Reference
components Object
cta Object
logoFlare Object
progressBar Object
progressBar.labels
progressBar.segments
progressBar.segments.default / .details (segment configuration)
progressBar.segments.progress[]
Important Notes
Component availability is per-offer. Different offers in the same response may return different components depending on their configuration.
The components object is additive. Existing fields like name, userReward, terms, and assets are always returned regardless of whether you request components.
Component values are dynamic. Descriptions, tags, CTA state, boosted rewards, and progress bars reflect the user’s state at request time and can change between requests. Re-fetch to get the latest state; do not cache component data across sessions.
Best Practices
- Support as many components as possible. Different offers rely on different components (activation, boosts, punch cards, tiered rewards, limited supply). The more you support, the more offers render fully; unsupported features degrade to
shortDescription/longDescription, and then to a modified offername. - At minimum, support
shortDescriptionandlongDescription. They are the universal fallback for any offer state you don’t otherwise support — without them, that state is only available in the offernameand users may miss required actions. - Always check for the presence of a component before rendering. Not every offer includes every component — your UI should gracefully fall back to standard offer fields.
- Use
cta.actionexactly as provided. The URL (including its query string) and method are pre-configured by Kard. Do not modify them. - Render state changes immediately. After a successful
ctaaction, use the updated offer from the responseincludedarray to update your UI without waiting for a full list refresh. - Choose components based on your UI capabilities. If you cannot render interactive buttons or graphical elements, request
shortDescriptionandlongDescription— progress and state are still conveyed through the descriptions. - Request only the components you support. Avoid requesting components you don’t intend to render.
- Show the reward uplift for boosts. When
boostedRewardis present, render it as the active reward and strike throughbaseRewardso the uplift is clear. - Render the progress bar per surface. Use the
defaultlayout on cards and thedetailslayout on the offer detail page, and honor per-nodeprogressfill so punch cards show partial progress. - Handle the absence of
ctaafter an action. When an offer has been activated or boosted, thectais omitted. Hide the button whenctais absent. - Do not cache component data across sessions. Values like tags, CTA state, boosted rewards, and progress are dynamic and may change between requests.