# Glossary Source: https://docs.paylead.fr/glossary Key terms and concepts in the Paylead ecosystem Terms written with a leading capital letter throughout this documentation (such as [Consumer](#consumer), [Program](#program), or [Offer](#offer)) are core Paylead concepts defined here. ## A ### ALO (Account-Linked Offer) Paylead's flagship promotional system, also called **Account-Linked Offers®**. Once enrolled in a [Program](#program), a [Consumer](#consumer) automatically receives a [Reward](#reward) when a purchase made with their linked bank account matches an active [Offer](#offer). Unlike cookie-based promotions, ALO works without any code, voucher, or click: the bank transaction itself is the proof of purchase. ### Automatic Cashback (ACB) The [Cashback](#cashback) experience presented to a [Consumer](#consumer) in the [WebApp (MFP)](#webapp-mfp). It lets the Consumer browse participating [Brands](#brand) and [Offers](#offer) and track the [Rewards](#reward) earned automatically when a purchase with their linked bank account matches an active Offer, without any code or voucher. ### Automatic Earn The defining mechanic of the [Loyalty](#loyalty) domain: because the [Consumer](#consumer)'s bank account is linked to their loyalty account, paying with the bank card automatically credits the program's Loyalty reward without presenting a loyalty card at checkout. The payment itself is the proof of loyalty. ## B ### Brand A network of points of sale belonging to the same holding company and available to [Consumers](#consumer) in a given country. A Brand can operate brick-and-mortar [Stores](#stores), an online boutique, or both. **Brand vs. Merchant:** The Brand is the commercial name displayed on the transaction. The merchant is the legal entity that owns one or several Brands. ### Budget The ceiling of [Cashback](#cashback) an [Offer](#offer) can pay out. The budget is carried by the [Campaign](#campaign) the Offer comes from, so a [Program Manager](#program-manager) does not set it in [Shift](#shift): it is agreed with the merchant, and on an [LBS](#lbs-local-business-solution) Campaign the local merchant sets it themselves (see [Campaigns](/program/lbs/campaigns)). Once the budget is consumed, the Offer moves to the `Completed` status and stops rewarding: a transaction matched afterwards produces no [Reward](#reward). Shift shows the budget through its effects, the `Budget reached` date on the Offer detail page and the `Completed` status in the Offers list, and a [Webhook](#webhooks) warns the Program Manager before it runs out (see [available events](/program/shift/webhooks#available-events)). ### Burn The act of spending accumulated [Reward](#reward) value instead of earning it. Burn applies across both Paylead domains: paying out a Perks [Pool](#pool) (the *cagnotte*) or buying a [Voucher](#voucher) with its euros is a form of Burn, as is converting accumulated [Loyalty](#loyalty) points into merchandise, discounts, vouchers, or experiences. It is the counterpart to earning. ## C ### Campaign A raw, unpublished commercial proposal sent by a merchant to a [Program Manager](#program-manager). It carries the merchant's conditions (eligible [Brand](#brand), duration, [playground](#playground) range, channel, loyalty rules). The Program Manager reviews the Campaign and either turns it into a published [Offer](#offer) or rejects it. ### Cashback A type of [Reward](#reward) in which a portion of the [playground](#playground) (defined per [Offer](#offer) by the [Program Manager](#program-manager)) is returned to the [Consumer](#consumer) in cash. Legally, the Cashback is owed by the Program Manager to its Consumers; Paylead manages the Consumer [pool](#pool) and distributes it on the Program Manager's behalf. See [Ventilation](#ventilation) for the payout process. ### Commissioned Transaction A [Consumer](#consumer) transaction that matches an active [Offer](#offer) and triggers the revenue mechanism: it generates a [playground](#playground) (the budget Paylead returns to the [Program Manager](#program-manager)) split per Offer between the Program Manager's commission and the [Cashback](#cashback) for the Consumer. ### Connector A legacy type of API key, still offered in the **Type** selector of [Shift](#shift)'s API Keys screen and mapped to a machine-to-machine role on the Paylead server. A Connector key feeds [Consumer](#consumer) and bank-connection data into Paylead through the pre-platform Connector API, which also exposes the Consumer's [Offers](#offer) and [Cashbacks](#cashback) and the [Brand](#brand) and [Stores](#stores) referential. New integrations use a Program M2M key instead: see [API keys](/program/shift/api-keys) for the selector and [Authentication](/program/user-journey/authentication) for the current model. The archived Connector reference stays available on [Versions & Download](/program/api/releases). ### Consumer A customer who has subscribed to a [Program](#program) and accepted that their banking transactions are analyzed by Paylead. The Consumer is the end-user who makes eligible purchases and receives [Rewards](#reward). ### Consumer-centric approach One of the two models a [Program](#program) that runs its own [Ventilation](#ventilation) can operate. The [Program Manager](#program-manager) credits the [Consumer](#consumer) as soon as the [Reward](#reward) reaches the technical status `Validated`, on the `REWARD_VALIDATED` [Webhook](#webhooks), and Paylead reimburses it at the next monthly settlement. The Program Manager therefore fronts the cash. The alternative is the [Standard approach](#standard-approach). See [Autonomous ventilation](/program/user-journey/concepts/autonomous-ventilation). ### Coupon A discount a [Consumer](#consumer) claims in the bank app and redeems at a merchant, by typing a code on the merchant's website or showing one at checkout. Unlike a [Cashback](#cashback) [Offer](#offer), a Coupon carries no [Reward](#reward) rate and is not matched against a transaction: the merchant grants the discount at the point of sale. Two mechanics exist: a **Generic Coupon** carries a single code shared by everyone, a **Unique Coupon** draws from an uploaded file of codes, one per Consumer. In [Shift](#shift) a Coupon is an Offer whose `Type` reads `Generic Coupon` or `Unique coupon`, created from its own **Coupons** section. See [Coupons](/program/shift/coupons). ## E ### Easy Vouchers (EVO) An optional [WebApp (MFP)](#webapp-mfp) feature that lets a [Consumer](#consumer) buy and manage [Vouchers](#voucher) directly in the app. When enabled for a [Program](#program), it adds voucher purchase and management screens to the WebApp's [Cashback](#cashback) experience. ## G ### Gift A type of [Reward](#reward) granted to a [Consumer](#consumer) outside of the standard transaction-matching flow, for example a welcome bonus, a one-off promotional reward, or a loyalty incentive issued directly by the [Program Manager](#program-manager). Gifts follow the same status lifecycle as Cashbacks, see [Reward](#reward). ## I ### Injector A legacy type of API key, still offered in the **Type** selector of [Shift](#shift)'s API Keys screen and mapped to a machine-to-machine role on the Paylead server. An Injector key pushes a bank's raw transactions into Paylead's transaction hub, the entry point of the [transaction lifecycle](/program/user-journey/concepts/transaction-lifecycle). New integrations use a Program M2M key instead: see [API keys](/program/shift/api-keys) for the selector and [Authentication](/program/user-journey/authentication) for the current model. The archived Injector reference stays available on [Versions & Download](/program/api/releases). ## L ### Lookalike audience An audience built by Paylead's algorithm to optimize the marketing performance of a [Campaign](#campaign). A [Program Manager](#program-manager) does not configure it, and Paylead does not communicate on the signals used to build it. When a Campaign carries one, the [Offer](#offer) publication form shows its estimated size rather than letting you pick the audience yourself. See [Publish an Offer](/program/shift/publish-offers). ### LBS (Local Business Solution) A Paylead application that lets local merchants create and manage their own [Campaigns](#campaign) through a lightweight, user-friendly interface. LBS expands the [Offer](#offer) catalog of a [Program](#program) beyond the merchants directly contracted by Paylead. ### Loyalty One of the two domains of the Paylead [Embedded Loyalty](/program/user-journey/what-is-paylead) platform (the other being [Perks](#perks)). Loyalty lets a [Consumer](#consumer) create or link retailer loyalty accounts from the bank app and link them to their bank account, unlocking [Automatic Earn](#automatic-earn). It is primarily a *relationship engine*: accounts, brands, ongoing engagement. See the [Loyalty journey](/program/user-journey/loyalty-journey). ### Loyalty Account A Consumer's account within a specific Merchant's Loyalty program. A Loyalty Account can be created from scratch or connected. ### Loyalty Balance The accumulated total of Loyalty rewards earned by a Consumer within a specific Loyalty program, expressed in the unit defined by the Merchant (points, euros, status level, etc.). It is updated whenever the Consumer's activity changes the balance, through Automatic Earn or through standard use of the Loyalty program, and is displayed to the Consumer in the Brand Hub. It serves as the basis for Burn actions when the retailer program supports reward conversion. ### Loyalty Offer An [Offer](#offer) that grants a [Reward](#reward) only after a defined number of qualifying purchases, instead of on every transaction. `perks.cashback.frequency` marks such an Offer, and `perks.cashback.loyalty_frequency`, on the Offer detail, carries the number of qualifying purchases required. Use it to power a dedicated loyalty section. ### Loyalty Program A merchant-operated rewards scheme (e.g. points, cashback, status tiers) made available to Consumers. A Loyalty program may involve a physical card or an online account, but its purpose remains consistent for a retailer: to build customer loyalty and reinforce repeat-purchase behavior. ### Loyalty Reward The accumulation or acquisition of points, miles, or other forms of currency offered by the program through various activities such as purchases, transactions, participation in promotions, or engagement with affiliated partners. It signifies adding to one's balance of loyalty currency, increasing the potential for future redemption of rewards or benefits within the program. ## O ### Offer A published promotion created by a [Program Manager](#program-manager) from a merchant [Campaign](#campaign). It defines the conditions a [Consumer](#consumer) transaction must meet to be eligible for a [Reward](#reward): eligible [Brand](#brand) or [Stores](#stores), [Cashback](#cashback) rate, validity period, channel (online, in-store, or both), loyalty rules, and budget cap. An Offer is what the Consumer actually sees in the bank's app. ### Offer Smart Ranking A Paylead algorithm that personalizes the order in which [Offers](#offer) are displayed to each [Consumer](#consumer). Ranking criteria include the Consumer's purchase habits, location, [Brand](#brand) power, and editorial spotlight. Smart Ranking requires the Consumer's explicit consent and is designed to improve relevance and conversion. ## P ### Paylead The fintech operating the bank-linked cashback platform described in this documentation. Paylead sits between merchants (who fund the [playground](#playground)) and [Program Managers](#program-manager) (typically banks) who expose [Offers](#offer) to their [Consumers](#consumer). ### Perks One of the two domains of the Paylead [Embedded Loyalty](/program/user-journey/what-is-paylead) platform (the other being [Loyalty](#loyalty)). Perks helps [Consumers](#consumer) save money on purchases through [Cashback](#cashback), [Vouchers](#voucher), and other savings mechanics. It is primarily a *savings engine*: immediate, monetary, easy to grasp. The Perks journey is the one the Paylead APIs implement today. ### Playground The budget Paylead returns to the [Program Manager](#program-manager) for each [Commissioned Transaction](#commissioned-transaction). The Program Manager defines, in each [Offer](#offer), how the playground is split between its own commission and the [Cashback](#cashback) paid to the [Consumer](#consumer). ### Pool A [Consumer](#consumer)'s holding area (the *cagnotte*) where validated [Cashback](#cashback) accumulates before it is paid out. `POOLED` is also the Consumer-facing status of a [Reward](#reward) sitting in this area. By default, Paylead manages the pool and runs the payout. See [Ventilation](#ventilation). ### Pre-filled forms The Consumer is in a **known context**: they are already authenticated in their bank app. This lets Paylead **pre-fill the loyalty account creation form**. Creating a loyalty account is reduced to **accepting the Program's terms and conditions**; the personal information is pre-filled and remains editable by the Consumer. ### Program The complete cashback proposition operated by a [Program Manager](#program-manager): a catalog of [Offers](#offer), an enrolled [Consumer](#consumer) base, and the business rules (commission, ventilation approach, communication channels) attached to them. One bank typically runs one Program. ### Program Manager The Paylead client (most often a bank or a financial-services company) that operates a [Program](#program) for its customers. The Program Manager curates the catalog of [Offers](#offer), defines on each Offer how the [playground](#playground) is split between its own commission and the Consumer [Cashback](#cashback), and exposes the Offers to its [Consumers](#consumer). Paylead manages the Consumer [pool](#pool) and distributes the Cashback on the Program Manager's behalf. ## R ### Reward What a [Consumer](#consumer) receives for completing a transaction that matches an [Offer](#offer)'s terms. Rewards can be of several types: ALO Cashback, LBS Cashback, or [Gifts](#gift). Each Reward carries two statuses: a *technical* one in `status` (`PENDING_VALIDATION`, `VALIDATED`, `PAID_IN`, `PAID_OUT`, `CANCELLED`) and a *Consumer-facing* one in `consumer_status` (`VALIDATION`, `POOLED`, `PAID`, `CANCELLED`). See [Reward lifecycle](/program/user-journey/guides/reward-lifecycle) for both tracks. ### Reward Attribution A two-step Paylead mechanism that guarantees each eligible purchase generates exactly one [Reward](#reward), even when the same transaction is reported by several sources (e.g. the bank itself and an account aggregator). A **duplication engine** first identifies that multiple transactions refer to the same purchase, then an **attribution engine** selects the winning [Program](#program) based on a scoring system (onboarding recency, engagement, reward intensity). ## S ### Scraper / Scraping A legacy bank-data collection method, in which a partner connects to a Consumer's online banking interface to retrieve transaction history. Paylead now relies primarily on regulated API-based feeds (PSD2, account aggregators); scraping vocabulary remains in some technical statuses (e.g. `SCRAPPING` synchronization status). ### Seamless Loyalty Card (SLC) Paylead's product that connects Consumers' bank accounts to their favorite Merchants' Loyalty programs, directly within the banking application. SLC enables Consumers to create or link Loyalty Accounts, automatically earn rewards on every eligible payment (without presenting a loyalty card at checkout), and manage their Loyalty programs from a single place. ### Segment A group of [Consumers](#consumer) used to expose [Offers](#offer) to a specific audience, defined by the bank's own criteria (for example *Premium*, *New*, *Black*, or *Gold*). A [Program Manager](#program-manager) can have as many Segments as they need, each with its own name. To prevent sensitive criteria (religious, political, and similar), Segment definitions (name and reference) are created by the Paylead account manager; the Program Manager then assigns Consumers to them, in bulk via [Shift](#shift) (CSV) or in real time via the API. ### Shift The Paylead web application used by [Program Managers](#program-manager) to manage their [Program](#program): review [Campaigns](#campaign), publish [Offers](#offer), monitor performance, manage [Consumers](#consumer), and download [Ventilation](#ventilation) files. ### Standard approach One of the two models a [Program](#program) that runs its own [Ventilation](#ventilation) can operate. The [Program Manager](#program-manager) waits for Paylead's monthly settlement, then distributes the [Cashback](#cashback) to its [Consumers](#consumer) from the Ventilation file it downloads, once the [Rewards](#reward) that file covers have reached the technical status `Paid Out`. No cash is fronted, but the Consumer waits roughly three to four months after validation. The alternative is the [Consumer-centric approach](#consumer-centric-approach). See [Autonomous ventilation](/program/user-journey/concepts/autonomous-ventilation). ### Stores The individual points of sale operated by a [Brand](#brand), either physical locations or online shops. An [Offer](#offer) can target all Stores of a Brand or a subset (for example, only the in-store channel or only specific locations). ## T ### Transaction Fetch Hub A per-bank, bespoke service in which Paylead **pulls** transactions directly from the banking partner, instead of the partner pushing them to the [Paylead API](/program/user-journey/quickstart). It is scoped during the build phase of the integration and is an alternative to the default push model. See the [transaction lifecycle](/program/user-journey/concepts/transaction-lifecycle). ### Transaction Lifecycle The sequence of steps a raw banking transaction goes through inside Paylead before becoming (or not) a [Reward](#reward): collection from the source (Transaction Hub push, the [Transaction Fetch Hub](#transaction-fetch-hub) pull, account aggregator, or banking partner), bucketing per bank connection, matching against active [Offers](#offer), eligibility check, and finally Reward creation. If no [Offer](#offer) matches, the lifecycle ends silently. ## V ### Ventilation The process by which validated [Cashbacks](#cashback) are paid out to [Consumers](#consumer). **Paylead manages the Consumer [pool](#pool) and runs the payout**. Legally, the Cashback is owed by the [Program Manager](#program-manager) to its Consumers; Paylead distributes it on the Program Manager's behalf. See the [Ventilation](/program/user-journey/concepts/ventilation) guide. ### Voucher A type of benefit in which a [Consumer](#consumer) receives a code or a fixed monetary value redeemable at a participating [Brand](#brand), under defined conditions such as minimum spend, validity period, or channel. ## W ### WebApp (MFP) A Paylead-hosted webview (also called the **MFP (Modular Front Platform)**) embedded inside a partner bank's mobile app. It lets a [Program](#program) delegate part of the Consumer-facing journey (offer discovery, [Reward](#reward) history, the loyalty wallet) to Paylead instead of building each screen natively. See the [WebApp concept](/program/user-journey/concepts/web-app) and the [WebApp (MFP)](/program/webapp/overview) integration tab. ### Webhooks Real-time HTTP notifications sent by Paylead to a [Program Manager](#program-manager)'s back-office when a key event occurs, for example `REWARD_CREATED`, `REWARD_VALIDATED`, `PAYOUT_SUCCESS`. Webhooks let the Program Manager react instantly (notify the Consumer, trigger a payout, update its CRM) without polling the API. Because a Webhook reflects the state of an object at the moment it is sent, always re-fetch the object via the API before acting on it. Its status may have changed in the milliseconds since the notification was emitted. # Issue an access token Source: https://docs.paylead.fr/program/api/authz/tokens/issue-an-access-token /program/api/openapi/2.0.0/authz/openapi.json post /tokens Exchange API key credentials for a short-lived ES256 JWT access token. Authenticate with HTTP Basic: the username is the API key's `client_id` (a UUID) and the password is its `client_secret`. Send the returned `access_token` as `Authorization: Bearer ` on every subsequent Platform API call. # Get detail for a brand in this program's catalog. Source: https://docs.paylead.fr/program/api/perks/brands/get-detail-for-a-brand-in-this-programs-catalog /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/brands/{brand_id} # List brands with active offers in the program's catalog. Source: https://docs.paylead.fr/program/api/perks/brands/list-brands-with-active-offers-in-the-programs-catalog /program/api/openapi/2.0.0/perks/openapi.json get /perks/brands # List brands with offers visible to this consumer in the program's catalog. Source: https://docs.paylead.fr/program/api/perks/brands/list-brands-with-offers-visible-to-this-consumer-in-the-programs-catalog /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/brands # Enroll a consumer into the perks program (accept CGU). Source: https://docs.paylead.fr/program/api/perks/consumers/enroll-a-consumer-into-the-perks-program-accept-cgu /program/api/openapi/2.0.0/perks/openapi.json post /perks/consumers # Create or update a consumer's KYC (Mangopay natural user). Source: https://docs.paylead.fr/program/api/perks/kyc/create-or-update-a-consumers-kyc-mangopay-natural-user /program/api/openapi/2.0.0/perks/openapi.json put /perks/consumers/{consumer_id}/kyc # Get detail for an offer visible to this consumer in the program's catalog. Source: https://docs.paylead.fr/program/api/perks/offers/get-detail-for-an-offer-visible-to-this-consumer-in-the-programs-catalog /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/offers/{offer_id} # List offers visible to this consumer in the program's catalog. Source: https://docs.paylead.fr/program/api/perks/offers/list-offers-visible-to-this-consumer-in-the-programs-catalog /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/offers # Get one of the rewards a consumer has received. Source: https://docs.paylead.fr/program/api/perks/rewards/get-one-of-the-rewards-a-consumer-has-received /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/rewards/{reward_id} # List the rewards a consumer has received. Source: https://docs.paylead.fr/program/api/perks/rewards/list-the-rewards-a-consumer-has-received /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/rewards # Assign a consumer to a segment. Source: https://docs.paylead.fr/program/api/perks/segments/assign-a-consumer-to-a-segment /program/api/openapi/2.0.0/perks/openapi.json post /perks/consumers/{consumer_id}/segments/{segment_reference} # List the segments a consumer is currently assigned to. Source: https://docs.paylead.fr/program/api/perks/segments/list-the-segments-a-consumer-is-currently-assigned-to /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/segments # Unassign a consumer from a segment. Source: https://docs.paylead.fr/program/api/perks/segments/unassign-a-consumer-from-a-segment /program/api/openapi/2.0.0/perks/openapi.json delete /perks/consumers/{consumer_id}/segments/{segment_reference} # List the catalog's top-level universes. Source: https://docs.paylead.fr/program/api/perks/universes/list-the-catalogs-top-level-universes /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/universes # Designate the bank account where a consumer wants to be paid out. Source: https://docs.paylead.fr/program/api/perks/upm/designate-the-bank-account-where-a-consumer-wants-to-be-paid-out /program/api/openapi/2.0.0/perks/openapi.json post /perks/consumers/{consumer_id}/accounts/payment # Read the payment account currently designated for a consumer. Source: https://docs.paylead.fr/program/api/perks/upm/read-the-payment-account-currently-designated-for-a-consumer /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/accounts/payment # Revoke the consumer's currently designated payment account. Source: https://docs.paylead.fr/program/api/perks/upm/revoke-the-consumers-currently-designated-payment-account /program/api/openapi/2.0.0/perks/openapi.json delete /perks/consumers/{consumer_id}/accounts/payment # Trigger a payout of the consumer's pool. Source: https://docs.paylead.fr/program/api/perks/upm/trigger-a-payout-of-the-consumers-pool /program/api/openapi/2.0.0/perks/openapi.json post /perks/consumers/{consumer_id}/pools/me/payouts Pays out the consumer's `PAID_IN` rewards: reserves the funds in the ledger, moves the money on the PSP (working capital to the program's UPM wallet, then a bank wire to the consumer's recipient), and marks the rewards `PAID_OUT`. Returns `202 Accepted`: the payout is initiated synchronously but the bank wire is settled asynchronously by the PSP. # List the READY voucher orders a consumer has placed. Source: https://docs.paylead.fr/program/api/perks/voucher-orders/list-the-ready-voucher-orders-a-consumer-has-placed /program/api/openapi/2.0.0/perks/openapi.json get /perks/consumers/{consumer_id}/voucher-orders # Versions & Download Source: https://docs.paylead.fr/program/api/releases Browse every published version of the Program API and download the OpenAPI specs. Each release of the Program API ships as a single OpenAPI specification covering every domain of the platform. For each version you can preview the rendered documentation in this site, or download the raw OpenAPI JSON to feed your own tooling (SDK generators, Postman, Insomnia, etc.). Earlier releases predate the consolidated platform spec and were split into per-component APIs (m2m, connector, injector). They remain available below under **Legacy APIs** for partners with existing integrations. Download the JSON or open the rendered reference per version. ### v2.0.0 (Latest) * [View documentation](/program/api/authz/tokens/issue-an-access-token) * [Download OpenAPI](/program/api/openapi/2.0.0/2.0.0.json) ## Legacy APIs ### v1.1.11 * Connector: [View documentation](/program/api/legacy/1.1.11/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.11/connector.json) ### v1.1.10 * Connector: [View documentation](/program/api/legacy/1.1.10/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.10/connector.json) ### v1.1.9 * Connector: [View documentation](/program/api/legacy/1.1.9/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.9/connector.json) ### v1.1.8 * Connector: [View documentation](/program/api/legacy/1.1.8/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.8/connector.json) ### v1.1.7 * Connector: [View documentation](/program/api/legacy/1.1.7/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.7/connector.json) ### v1.1.6 * Connector: [View documentation](/program/api/legacy/1.1.6/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.6/connector.json) ### v1.1.5 * Connector: [View documentation](/program/api/legacy/1.1.5/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.5/connector.json) ### v1.1.4 * Connector: [View documentation](/program/api/legacy/1.1.4/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.4/connector.json) * M2M: [View documentation](/program/api/legacy/1.1.4/m2m/lbs/get-the-lbs-strategies) · [Download OpenAPI](/program/api/openapi/legacy/1.1.4/m2m.json) ### v1.1.3 * Connector: [View documentation](/program/api/legacy/1.1.3/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.3/connector.json) * M2M: [View documentation](/program/api/legacy/1.1.3/m2m/lbs/get-the-lbs-strategies) · [Download OpenAPI](/program/api/openapi/legacy/1.1.3/m2m.json) ### v1.1.2 * Connector: [View documentation](/program/api/legacy/1.1.2/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.2/connector.json) * Injector: [View documentation](/program/api/legacy/1.1.2/injector/bank/get-the-list-of-bank) · [Download OpenAPI](/program/api/openapi/legacy/1.1.2/injector.json) * M2M: [View documentation](/program/api/legacy/1.1.2/m2m/lbs/get-the-lbs-strategies) · [Download OpenAPI](/program/api/openapi/legacy/1.1.2/m2m.json) ### v1.1.1 * Connector: [View documentation](/program/api/legacy/1.1.1/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.1/connector.json) ### v1.1.0 * Connector: [View documentation](/program/api/legacy/1.1.0/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.1.0/connector.json) ### v1.0.1 * Connector: [View documentation](/program/api/legacy/1.0.1/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.0.1/connector.json) ### v1.0.0 * Connector: [View documentation](/program/api/legacy/1.0.0/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/1.0.0/connector.json) ### v0.3.0 * Connector: [View documentation](/program/api/legacy/0.3.0/connector/banks/gets-the-list-of-banks) · [Download OpenAPI](/program/api/openapi/legacy/0.3.0/connector.json) # Create a bulk of historical transactions Source: https://docs.paylead.fr/program/api/thub/bulk-transaction/create-a-bulk-of-historical-transactions /program/api/openapi/2.0.0/thub/openapi.json post /consumers/{consumer_id}/transactions/history Inserts multiple historical transactions to consumer `consumer_id` using a bulk. Historical transactions will not be cashbacked. # Create a bulk of transactions Source: https://docs.paylead.fr/program/api/thub/bulk-transaction/create-a-bulk-of-transactions /program/api/openapi/2.0.0/thub/openapi.json post /consumers/{consumer_id}/transactions Inserts multiple transactions to consumer `consumer_id` using a bulk. # Offboard a consumer from Paylead platform Source: https://docs.paylead.fr/program/api/thub/consumers/offboard-a-consumer-from-paylead-platform /program/api/openapi/2.0.0/thub/openapi.json delete /consumers/{consumer_id} Delete a consumer by providing it's `consumer_id` # Onboard a consumer on Paylead platform Source: https://docs.paylead.fr/program/api/thub/consumers/onboard-a-consumer-on-paylead-platform /program/api/openapi/2.0.0/thub/openapi.json post /consumers Create a consumer by providing it's `consumer_id` # Get a consumer's aggregated reward information Source: https://docs.paylead.fr/program/api/thub/rewards/get-a-consumers-aggregated-reward-information /program/api/openapi/2.0.0/thub/openapi.json get /consumers/{consumer_id}/rewards/info Aggregates reward information for consumer `consumer_id` by querying the different backends concurrently. Each backend contributes its own field (e.g. `perks`) and is only included when it responds: a backend that fails, times out or has no data for the consumer is omitted from the payload. # Delete transaction Source: https://docs.paylead.fr/program/api/thub/transaction/delete-transaction /program/api/openapi/2.0.0/thub/openapi.json delete /consumers/{consumer_id}/transactions/{transaction_id} Delete the transaction `transaction_id` on account `account_id` linked to bank connection `bank_connection_id` for consumer `consumer_id`. # Update transaction Source: https://docs.paylead.fr/program/api/thub/transaction/update-transaction /program/api/openapi/2.0.0/thub/openapi.json put /consumers/{consumer_id}/transactions/{transaction_id} Update the `transaction_id` transaction on `account_id` linked to `bank_connection_id` bank connection for consumer `consumer_id`. # Give each teammate the right access Source: https://docs.paylead.fr/program/shift/access-and-roles Sign in to Shift, manage your own account, and invite teammates with the exact roles their job needs. Every member of your team signs in to [Shift](/glossary#shift) with their own account. Each account carries one or more **roles**, and a role decides which sections of Shift that account can open. Signing in and reading your own settings need no role. Inviting teammates and assigning their roles need the Administration role. ## Sign in Each environment has its own sign-in URL: | Environment | Sign-in URL | | ----------- | ----------- | | Sandbox | | | Production | | Sandbox and production are isolated environments with separate URLs and separate credentials. Paylead provisions both during onboarding. Enter the email address and password Paylead provisioned for your [Program Manager](/glossary#program-manager) account, then click **Sign In**. Shift lands you on **Performances**, a section every account can open regardless of its roles. Two elements of that form are worth knowing about: * **Remember me** keeps you signed in for 90 days. Left clear, your session follows the shorter default and you sign in again sooner. Tick it on a machine only you use, never on a shared one. * After a failed attempt, Shift may add a reCAPTCHA challenge before it accepts another try. Solve it and submit again. If Shift greets you with "Your password is not strong enough. Please change it to secure your account.", the sign-in worked. Paylead checks the password you just typed against its current rules, and asks you to update it under **My account** > **Settings**. If you forget your password, use **Forget your password?** on the sign-in page. Paylead emails you a reset link; opening it takes you to a screen where you set the new password, and you then come back to Shift to sign in. If the email does not arrive, check that the address you typed is the one registered on your Shift account. ### Sign in with SSO When Paylead has connected your Program to your bank's identity provider, the credentials form is not your entry point. Click **SSO Login** at the bottom of the sign-in page: the **Single Sign-on** screen asks for your email address only, then hands the browser over to your identity provider, which authenticates you and sends you back into Shift. **Regular login** returns to the credentials form. Your Program also gets its own base URL for each environment, which replaces the standard URLs above. See [Shift with SSO](#shift-with-sso) for what this mode removes from the interface once you are in. ## Manage your account settings Open **My account** > **Settings** to review and edit your personal credentials. Every signed-in user reaches this page, whatever their roles. | Field | Editable | Description | | ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Created** | No | Date your account was created. | | **Name** | Yes | Your first and last name. Click **Edit** to open the **First name** and **Last name** fields, both required. **Cancel** restores what was there when you opened them. | | **Email** | Yes | Your sign-in email. Click **Edit** to change it. | | **Password** | Yes | Click **Edit**, confirm your **Old password**, then fill in **Password** and **Retype your password**. | Each block saves on its own. Shift confirms with "Your settings have been updated." and refreshes your session, so a name or email change takes effect without signing out and back in. ### Password requirements Shift lists these rules under the password fields and marks each one as you type: * Minimum 14 characters * 1 lowercase * 1 uppercase * 1 digit * 1 special * No company name or one of our product names * No username (firstname or lastname) ### Email notifications A second card sits under the settings card on the same page, titled **Notifications**. It holds your personal email subscriptions, and every one of them concerns a [Campaign](/glossary#campaign) event. That is why Shift shows the card only to users who hold the **Offers** role: a teammate without that role never sees it. Six subscriptions are offered: * **New campaign available** * **Campaign ending soon** * **Campaign extension** * **Campaign shortened** * **New visual available** * **Boosted rate phase available** Each row carries a toggle and a `?` icon that describes the event on hover. The **Apply to all** toggle at the top of the card switches every subscription on or off in one move. The card has no **Save** button: each toggle takes effect the moment you flip it. For what each notification tells you, see [Stay notified about Campaigns](/program/shift/publish-offers#stay-notified-about-campaigns). Subscriptions are personal: they follow your account, not your Program, so each teammate sets their own. Use them to decide who gets alerted when the catalog needs attention, rather than routing every Campaign email to one shared mailbox. ## Manage users A **user** is anyone with an active Shift account in your [Program](/glossary#program). **My account** > **Users** lists every user, their last activity, and their assigned roles. Search the list by name or email. ### Roles A role defines which sections of Shift a user can open. A user can hold several roles at once. Roles do not nest: Administration opens **Users** and nothing else, so an administrator who also needs the technical screens must hold **Technical** too. Two areas stay open to every signed-in user, whatever their roles: **Performances** and **My account** > **Settings**. | Role | Sections it opens | | -------------------- | ---------------------------------------------------------------------------------------- | | **Administration** | Users | | **Financial** | Invoices, [Ventilation](/glossary#ventilation) | | **Gifts** | [Gifts](/glossary#gift) | | **Offers** | [Offers](/glossary#offer), [Campaigns](/glossary#campaign), Brands, Coupons, Integration | | **Reporting** | Reporting, Brands, Ventilation | | **Consumer support** | [Consumers](/glossary#consumer), Segments | | **Technical** | Program, Developers (Event logs, Hooks, API Keys) | Three of these sections depend on how Paylead configured your Program, on top of the role: Coupons, Ventilation, and Integration. If one of them is missing for a user who holds the matching role, ask Paylead from the **Support** button in Shift whether it is enabled on your Program. ### Choose the roles for a new teammate Start from the job, not from the matrix. Ask what the person is accountable for, grant the roles that cover it, and add more later when they hit a wall. | Their job | Roles to grant | | -------------------------------------------------------------------------------- | -------------------- | | Runs the Offer catalog: reviews what Paylead proposes and publishes it | **Offers** | | Answers Consumer questions about their [Rewards](/glossary#reward) and sync | **Consumer support** | | Reconciles invoices and payouts | **Financial** | | Builds and reads performance reports | **Reporting** | | Runs the [Gift](/glossary#gift) catalog | **Gifts** | | Owns the integration: API keys, [Webhooks](/glossary#webhooks), Program settings | **Technical** | | Onboards and off-boards teammates | **Administration** | Combine them when one person covers several jobs: someone who both manages the catalog and reconciles payouts needs **Offers** and **Financial**. Grant **Administration** on top of a working role, unless the person does nothing but manage accounts. Give at least two people the **Administration** role. It is the only role that can invite and deactivate users, and no account can change its own roles or deactivate itself. ### Invite a user In **My account** > **Users**, click **Invite a user**. Enter the **First name**, **Last name**, and a valid **Email** address. The invited person signs in with that email. Open the **Roles** selector and pick every role the new user needs. At least one role is required. You can change the selection later. Click **Invite**. Paylead emails the new user a link to create their account. The user appears in the list once they complete the flow. ### Edit a user In the users list, click the pencil icon next to a user to open their record. Update their **First name**, **Last name**, or **Roles**, then click **Save**. Shift confirms with "User successfully edited." and returns to the list. **Cancel** goes back without saving, and leaving the page with unsaved edits raises "You're leaving this page without saving your modifications." The email address is read-only here. It identifies the account, so only its owner changes it, from **My account** > **Settings**. **Roles** is a required field: a user always holds at least one, so off-board someone with **Deactivate user** rather than by emptying their roles. The field is hidden when you open your own record. Ask another holder of the **Administration** role to change your roles. Shift reads a user's roles when it loads, so a teammate who already has Shift open keeps the old menu until they reload the page. ### Deactivate a user In **My account** > **Users**, click the pencil icon next to the user to off-board. Click **Deactivate user**, then confirm in the dialog. Shift returns to the users list and confirms the deactivation. Deactivation is permanent. You cannot deactivate your own account: ask another holder of the **Administration** role. ## Shift with SSO Paylead can connect Shift to your bank's identity provider instead of issuing credentials itself. When SSO is enabled on your Program, the identity provider owns accounts, credentials, and sessions, and Shift removes every control that would compete with it. Several procedures on this page no longer apply in that mode. | Control | Where it normally sits | With SSO enabled | | --------------------------------------- | ----------------------------- | -------------------------------------------------------------------------------- | | **Sign Out** | Bottom of the main sidebar | Hidden. End your session from your identity provider. | | **Edit** next to **Name** and **Email** | **My account** > **Settings** | Hidden. | | **Password** | **My account** > **Settings** | Removed, along with the change-password form. | | **Invite a user** | **My account** > **Users** | Hidden, so the invite flow cannot be started. | | Pencil icon at the end of a user row | **My account** > **Users** | Hidden, which also puts the user edit form and **Deactivate user** out of reach. | Everything else behaves the same. You still read your account settings and your email notification subscriptions, browse the users list with each user's roles and last activity, and open every section your roles grant. Ask Paylead from the **Support** button in Shift for anything the identity provider does not cover. ## What's next Group your Consumers by targeting criteria for audience-specific Offers. Review the Campaigns Paylead proposes and publish them as Consumer-facing Offers. # API keys Source: https://docs.paylead.fr/program/shift/api-keys Generate and manage the API keys that authenticate your integration with Paylead. An API key is a bearer token that authenticates calls from a system outside [Shift](/glossary#shift), for example your bank's mobile app backend or your data ingestion job. Use one when a server on your side needs to read or write Paylead data on its own, with no human signed in to click anything. Generate, view, and revoke keys from **My account** > **Developers** > **API Keys**. For how a credential becomes a bearer token and how that token travels on each call, see [Authentication](/program/user-journey/authentication). For events Paylead pushes to your system in real time, see [Webhooks](/program/shift/webhooks). ## Key types The type you pick decides what the key is allowed to reach. It is fixed at generation: to change the reach of an integration, generate a new key of the right type and revoke the old one. | Type | What a key of this type is for | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Program M2M** | Server-to-server access to your own [Program](/glossary#program) data: [Rewards](/glossary#reward), [Offers](/glossary#offer), [Brands](/glossary#brand), reporting, and [Ventilation](/glossary#ventilation) files. This is the type behind back-office integrations, data warehouse feeds, and scheduled reports. Shift preselects it. | | **Connector** | Legacy. Feeds [Consumer](/glossary#consumer) and bank-connection data into Paylead. | | **Injector** | Legacy. Pushes raw transactions into Paylead. | Pick **Program M2M** unless Paylead asked you for one of the other two. When a Paylead contact asks you for a **Connector** or an **Injector** key, ask them for the matching integration contract at the same time. ## View existing keys The **API Keys** table lists every key active on your Program. Revoking a key removes its row, so the table is your live inventory of what can reach your data. | Column | Description | | --------------- | ---------------------------------------------------- | | **Created** | The date the key was generated. | | **Type** | The key's type. See [Key types](#key-types). | | **API Key** | The generated token, truncated to fit the column. | | **Description** | The free-form label you set when generating the key. | Each row also carries an **API Documentation** link and a bin icon that revokes the key. The full token is shown once, in the dialog that opens right after you generate the key. Copy it then and store it in your secret manager. If you did not, revoke the key and generate a new one. ### The API Documentation link **API Documentation** opens a screen inside Shift, not the Paylead documentation site. It embeds the raw OpenAPI reference for that row's key type, plus a selector for the other available specification versions. Open it from a key row when you need to confirm what a key of a given type is technically allowed to call. For the current Platform API, which is what a new integration should build against, use the [API reference](/program/api/releases). ## Generate an API key In **My account** > **Developers** > **API Keys**, click **Generate new API key**. **Type** is preset to **Program M2M**. Change it only if Paylead asked for a legacy type. One key serves one system: do not reuse a key across services. **Description** accepts 20 characters at most, so name the consuming system as tightly as you can, for example `Lyra mobile app` or `Yuna ingestion job`. Future operators rely on this label to know what they would break by revoking the key. Click **Confirm**. Shift issues the key and opens a dialog showing the **API Key** value. Click **Copy Token**, paste the value into your secret manager, then click **Close**. The new key appears in the list. The key is usable immediately, with no activation step. Send one authenticated call from the consuming system to confirm the token reached it intact. The key issued on this screen is a JWT: three Base64URL segments separated by dots (`header.payload.signature`), with no prefix. The Platform API client `client_secret` described on [Authentication](/program/user-journey/authentication) is a different credential, with a different shape and its own issuing flow. ## Rotation and revocation A key generated here **does not expire**: it stays valid until someone revokes it, so rotation only happens if you schedule it. Treat API keys like any other production secret. * **Store them in a secret manager** (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager). Never commit a token to Git, paste it in a ticket, or share it over chat. * **Rotate periodically**: generate a new key, deploy it to the consuming system, confirm traffic flows on the new token, then revoke the old one from Shift. * **Revoke immediately on suspicion**: if a token may have leaked, revoke it rather than waiting for evidence. A revoked key cannot be restored, and generating a replacement costs a minute. * **One key per consuming system**: sharing a key across services means revoking it takes down all of them at once, and the **Description** no longer tells you which system you are about to break. Sandbox and production are isolated environments with separate credentials, so generate each key from the matching Shift environment. A sandbox token reaches sandbox endpoints only, and a production token production endpoints only. ### Revoke a key In the key's row, click the bin icon, then click **Confirm**. Shift revokes the key and the row leaves the table. Revocation is immediate and cannot be undone. Every system still presenting that token starts failing authentication at once, so deploy the replacement token before you revoke, not after. ## What's next Register a callback URL and receive Program events in real time. Token format, headers, and credential handling for the Platform API. # Billing address Source: https://docs.paylead.fr/program/shift/billing-address Read the billing address Paylead uses to invoice your Program, and edit the legal terms attached to it. The billing address is the postal address Paylead uses to invoice your [Program](/glossary#program). It sits on **My account** > **Program**, next to the other identity details of your Program. Check it before your first invoicing cycle closes, and again whenever your legal entity, its registered address, or its VAT regime changes. ## Read your Program details **My account** > **Program** shows four fields, all read-only: | Field | Description | | ------------------- | -------------------------------------------------------- | | **Program name** | The name of your Program. | | **Country** | The country your Program is registered in. | | **Description** | The free-text description of your Program. | | **Billing address** | The postal address Paylead uses to invoice your Program. | Paylead maintains these four fields. To correct the billing address, ask Paylead from the **Support** button in Shift: a wrong address changes the tax details on your invoices and on your [Ventilation](/glossary#ventilation) payouts. Raise the correction as soon as you spot it rather than at cycle end. A correction takes effect on the next cycle. Invoice generation reads the address current at the moment it runs, so invoices already issued keep the old one: check them in [Invoices](/program/shift/invoices) and flag the ones to reissue when you report the correction. Ventilations carry payout references, not the billing address, so they are unaffected. ## Edit the legal terms **Legals terms and application** is the field you edit here, a free-text box under the Program details holding your Program's own terms. The same label appears on each [Brand](/program/shift/brands), where it carries the legal text bound to that Brand's Offers; this box is the Program-level one. Paylead holds this text on your Program record and passes it to the WebApp inside the Program object. Treat it as a record held by Paylead rather than as text you publish to your [Consumers](/glossary#consumer). Click in the **Legals terms and application** box, type your terms, then click **Save**. Saving replaces the previous wording outright, so keep your own copy of the current terms before you replace them. ## What's next Download the Ventilation files that pay Cashbacks to your Consumers. Retrieve the invoices Paylead issues to your Program. # Brands Source: https://docs.paylead.fr/program/shift/brands Look up the details of the Brands in your catalog. Available only for Programs that offer Coupons. A [Brand](/glossary#brand) is a merchant your [Consumers](/glossary#consumer) can earn [Cashback](/glossary#cashback) from. Paylead grants your [Program](/glossary#program) access to a Brand, and the Brand then appears in your catalog. Paylead proposes [Campaigns](/glossary#campaign) for the Brands in that catalog, which you review and publish as [Offers](/glossary#offer). See [Publish an Offer from a Campaign](/program/shift/publish-offers) for how a Campaign becomes an Offer. The **Brands** section is the read-only lookup on that catalog. Open it when you need something about a merchant that the Offer screens do not show you: its legal terms, the description Consumers read, its company number, or the universe it is filed under. In practice you come here before attaching a [Coupon](/program/shift/coupons) to a Brand, or when a Consumer questions the wording displayed next to one of your Offers. The section is available on Programs that run [Coupons](/program/shift/coupons), the discount-code mechanic where each Coupon is issued to exactly one Brand. On a Program running Cashback alone, the Brand behind an Offer is named on the Offer itself. Brand details are maintained by Paylead. For a Brand attached to a Coupon Offer, ask Paylead from the **Support** button in Shift to update its logo, **Description**, **Legals terms and application**, or **Website**. ## View a Brand's details Under **My account > Brands**, each row lists a Brand in your catalog. Open a Brand to see its details: | Field | Content | | -------------------------------- | --------------------------------------------------------------------------------------------- | | **Brand name** | The merchant name shown to Consumers. | | **Company number** | The merchant's registration number (for example, a French SIRET such as `732 829 320 00074`). | | **Website** | The merchant's public website URL. | | **Universe** | The category and sub-category the Brand belongs to (for example, Food and Supermarket). | | **Description** | A Consumer-facing description of the Brand. | | **Legals terms and application** | The legal text bound to the Brand's Offers. | **Description** and **Legals terms and application** are held per language. Language tabs appear on these two fields only when your Program declares more than one language: they list your Program's primary language first, then its secondary languages. The list also shows a **Stores** column, which is not populated: the details apply to the Brand as a whole, not to its individual [Stores](/glossary#stores). ## What's next Publish a Consumer-facing Offer from a Campaign Paylead proposes. Adjust a published Offer's details, dates, or Reward rate. # Browse Consumers Source: https://docs.paylead.fr/program/shift/browse-consumers Search a Consumer by exact ID, inspect their profile, and review every Offer, Reward, voucher, transfer, and bank synchronization tied to their account. The **Consumers** section of [Shift](/glossary#shift) is where you find a single [Consumer](/glossary#consumer) and reconstruct everything that happened on their account: which [Offers](/glossary#offer) were displayed, which [Rewards](/glossary#reward) were generated, which payouts went out, and whether their bank connection is healthy. Use it to answer a support ticket, audit a disputed [Cashback](/glossary#cashback), or debug an integration. ## Find a Consumer To open a profile, you need the Consumer's exact ID. **All**, **Active**, and **Inactive** at the top show Consumer counts only. In **Consumers**, paste the exact [Consumer](/glossary#consumer) ID into the search field. Search matches that ID only, not a name, an email, or a phone number, so look it up in your own customer record first. An exact match opens the Consumer profile directly. If nothing matches, the page returns to the empty state with **No Consumer has been found with this ID…**. Shift reopens the last Consumer you searched for, so a profile can still be on screen when you come back after a break. Close the browser tab at the end of a support session. The activity tabs keep their own memory, and it is not tied to a Consumer. The selected tab, the page, the sort order, and the **Date from** / **Date to**, status, and Reward type filters carry over to the next profile you open. A date range left over from a previous ticket hides the Rewards you are looking for. Clear the filters before concluding that a Reward is missing. ## Consumer profile The profile page is split between Consumer-level metadata at the top and a tabbed activity zone below. ### Consumer details | Field | What it tells you | | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | **TOS acceptance** | Date the Consumer accepted the terms of service. | | **Privacy policy acceptance** | The Consumer's consent state. Click the cross next to a granted consent to revoke it. **Basic** is greyed out and cannot be revoked. | | **Last activity** | Date the Consumer last opened the Program app. | | **Status** | `Active` or `Inactive`. Inactive accounts no longer generate Rewards. | | **Account sync** | Whether Shift is in sync with the Consumer's bank data, for example `Synced`. | | **Forwarded KYC** | `yes` or `no`. Only on a Program whose Ventilation Paylead operates. See [Reading Forwarded KYC](#reading-forwarded-kyc). | | **Segments** | The [Segments](/glossary#segment) the Consumer belongs to. Empty when the Consumer is in none. | | **Target account** | IBAN of the bank account that receives Cashback payouts. Only on a Program whose Ventilation Paylead operates. | **Forwarded KYC** and **Target account** only concern Programs whose [Ventilation](/glossary#ventilation) Paylead operates. On a Program that runs its own Ventilation, Paylead does not execute the payouts and both squares are absent. **Target account** is also absent when payouts are aggregated rather than sent per Consumer. ### Reading Forwarded KYC When Paylead operates the Ventilation, it pays Consumers through a payment service provider that requires their identity to be registered before it can send money. **Forwarded KYC** says whether that registration exists: `yes` on a green square, `no` on a red one. A Consumer whose **Forwarded KYC** reads `no` cannot be paid, however many validated Cashbacks sit in their pool. On a Consumer chasing a payout, a red square is the answer to their ticket. ### Consent The **Privacy policy acceptance** box lists every consent the Consumer has granted, each with its acceptance date and a cross to revoke it, after a confirmation dialog. The consents surfaced are: * **Basic**, greyed out: it cannot be revoked from Shift. It is the consent that authorizes Offer matching in the first place, so withdrawing it amounts to removing the Consumer from the [Program](/glossary#program) rather than adjusting a preference. * **Statistics** * **Targeting** * **Smart ranking**, which enables [Offer Smart Ranking](/glossary#offer-smart-ranking) * **Transaction triggers** * **Web Analytics** An absent level was never granted, or has already been revoked. What each consent authorizes is defined by your Program's privacy policy, set with Paylead. See the [Status reference](/program/shift/status-reference#privacy-policy-acceptance) for a short definition of each level. Revoking a consent is one-way in Shift: the Consumer has to accept it again from your own app. It does not cancel the Rewards they have already earned, which keep their status and are paid out as usual. What changes is what Paylead may do with their data from that point on. A Consumer who wants to leave the [Program](/glossary#program) entirely does it from your own app: withdrawing the **Basic** consent is a Consumer-side action. ### Pool The **Pool** zone is the last block of the **Consumer details** card, a full-width strip under **Segments** and **Target account**. It counts the Consumer's Cashbacks, and totals their amounts, for four states only: * `Pending validation`: The Cashback is being validated. * `Validated`: The Cashback is locked and ready for payout. * `Pool`: The Cashback sits in the Consumer's wallet, waiting to be transferred. * `Paid`: The Cashback has been transferred to the Consumer's bank account. These are display labels. Behind `Pool` and `Paid` sit the technical statuses `PAID_IN` and `PAID_OUT`, which is what the [Paylead API](/program/user-journey/quickstart) and your own back-office return for the same Cashback. Match the two before quoting a status to a developer: see [How to read a status in Shift](/program/shift/status-reference#how-to-read-a-status-in-shift). The `Pool` counter carries a colored dot that explains why a validated Cashback has not been paid out yet. Hover it to read the payout threshold, worded ` minimum to trigger the cagnotte` (`cagnotte` is the Pool). The threshold is set once for your whole Program, not per Consumer. The color compares the `Pool` amount alone, not the sum of `Validated` and `Pool`, against that threshold: | Dot | What it means | | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Red | The `Pool` amount is zero. Nothing is waiting to be transferred. | | Orange | The `Pool` amount is below the threshold, so the Consumer has to earn more before a transfer is triggered. This is the normal answer to "my Cashback is validated but I was never paid". | | Green | The `Pool` amount has reached the threshold, so a payout is due. If the **Transfers** tab shows nothing yet, the transfer has not been executed, not that the Cashback was lost. | | Grey | Your Program sets no payout threshold, so there is nothing to compare. | What happens once the dot turns green depends on your Program's [Ventilation](/glossary#ventilation) model: a scheduled payment batch, or a payout with a manual and an automatic trigger. Check which one you run before telling a Consumer when to expect the money. Two more states exist for a Cashback, but the Pool zone counts neither of them: * `Not attribued`: The Cashback was duplicated across sources (for example, the bank feed and an account aggregator both reported the same transaction). One of the duplicates was kept and the rest are marked `Not attribued`. See [Reward Attribution](/glossary#reward-attribution) for the deduplication logic. * `Cancelled`: The Cashback is no longer eligible (matching issue, technical error, or merchant cancellation). See the [Status reference](/program/shift/status-reference#pool) for the full Pool status table. ## Consumer activity The activity zone groups everything that happened on the Consumer's account into four tabs, five when your [Program](/glossary#program) has the [Easy Vouchers (EVO)](/glossary#easy-vouchers-evo) option enabled, which is what adds the **Vouchers** tab. The **Offers** tab lists every Offer the Consumer is currently eligible to see. When [Offer Smart Ranking](/glossary#offer-smart-ranking) is enabled, the order reflects the algorithm's score (purchase habits, location, [Brand](/glossary#brand) power, editorial spotlight). Use the calendar picker to inspect eligibility on a past date, useful when a Consumer claims they saw a specific Offer but never received the Cashback. Filter by Reward type to narrow the list. Click any row to expand it in place. The panel that opens adds three values for that Offer: **Minimum basket**, **Maximum amount**, and **Capping**. Each one shows `N/A` when the Offer does not set it. See [Publish an Offer](/program/shift/publish-offers) for the full Offer reference. The **Rewards** tab lists every Reward generated for the Consumer, Cashbacks and [Gifts](/glossary#gift) alike. Each row shows the date, the status, the Reward type, the origin, the Offer name, and the amount. The matched transaction is not in the row: open the Reward to see it. Filter by **Date from** / **Date to** to scope to a period, and by status to focus on one state. The status filter offers **All**, **Pending validation**, **Validated**, **Pool**, and **Paid**, each prefixed with the number of Rewards it holds. `Cancelled` and `Not attribued` Rewards cannot be isolated this way. Click the view icon on a row to open the Reward detail page. It contains up to three cards: * **Reward details**: the linked Offer and its origin, the Cashback amount, and the current status. * **Reward history**: the originating transactions first (identifier, label, amount, merchant, execution date), then every status transition with its date. Gift Rewards have no transaction block. This card is the source of truth when reconstructing a payout dispute. * **Attributions**: shown only when several candidates claimed the same transaction. See [Reading the Attributions card](/program/shift/customer-support-workflow#reading-the-attributions-card). The **Vouchers** tab lists the Vouchers the Consumer ordered. A Voucher is not a Cashback: the Consumer buys it, for a code or a fixed value redeemable at a [Brand](/glossary#brand), which is why the statuses below talk about payment. The tab appears only when [Easy Vouchers (EVO)](/glossary#easy-vouchers-evo) is enabled on your Program. Filter by date range to scope the list. Each row shows the reservation date, the voucher status, the Brand, the Offer reference, and the value. See [Status reference](/program/shift/status-reference#vouchers) for what each voucher status means. Click the view icon to open the voucher detail page. See [Working on a single voucher](#working-on-a-single-voucher) for what you can do there, and [Vouchers report](/program/shift/vouchers-report) for the Program-wide export of the same data. The **Transfers** tab lists every Cashback payout sent to the Consumer's bank account. The Target account configured in the Consumer details zone is the destination IBAN. Filter by **Date from** / **Date to** to scope to a payout window. Each row shows: | Column | What it represents | | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Date** | Date the payment was executed. While the transfer has not been executed, the column falls back to the date it was created, with no visual distinction. | | (no header) | A status icon for the transfer. Hover it to read the status: `Ok`, `Error`, or `Failed`. | | **ID** | Internal transfer identifier. Quote this in any payout dispute. | | **Accounts** | Source and destination bank accounts, last digits only. The symbol between them repeats the status: an arrow when the transfer succeeded, a cross when it failed, a tilde while it has not been executed. | | **Amount** | Total amount transferred. | The status is the answer to "the money never arrived", so read it before anything else: | Status | What to conclude | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Ok` | The payout left Paylead on the **Date** shown. If the Consumer still sees nothing, the question moves to their bank: give them the **ID** and the amount. | | `Error` or `Failed` | The payment did not go through. No money left. Escalate to Paylead with the transfer **ID**. | | No icon at all | The transfer exists but has not been executed yet. The **Date** column is showing its creation date, not a payment date. Nothing is lost; nothing has moved either. | Click the view icon to open the transfer detail page. It breaks the lump-sum transfer down into the individual Rewards that funded it, which is what you need to reconcile a Consumer's bank statement against Shift. The **Synchronizations** tab is the health check for the Consumer's bank connections. Each row is one bank connection; below the bank name, the linked accounts are listed. | Column | What it represents | | ------------------------------ | ----------------------------------------------------------------------------------------------------- | | **Name** | Bank name and linked account references. | | **1st connection** | When the bank account first connected to the Program. | | **Last successful connection** | Last successful sync. | | **Most recent transaction** | Date of the latest banking transaction Paylead received. | | (no header) | A question mark icon, shown only when the connection reported an error. Hover it to read the message. | A **Status** column reports the connection state, as a translated label rather than the raw API value. See [Status reference](/program/shift/status-reference#bank-synchronization) for the mapping and what each state means. ### Reading the Activations column The **Activations** column of the **Offers** tab can carry two different values, and both use the same `x / y` format: * The fidelity badge, shown only when the Offer runs a fidelity Campaign that sets a purchase frequency (a Reward is only granted after N purchases). It reads `current / target`: `3 / 5` means three of the five qualifying purchases have been recorded. * The activation capping, shown only when the Offer sets a maximum number of activations. It reads `activations / maximum`. When the Offer sets no maximum, the column shows the activation count on its own, with no denominator. ### Working on a single voucher The voucher detail page opens on three cards, **Voucher details**, **Voucher history**, and **Voucher downloads**, with two buttons at the top of the page: **Force sync** and **Back**. **Voucher history** lists every status the order went through, most recent first, each with its date. It is where you check whether an order ever left `Created`. Click **Force sync** when the status looks stale, for example an order stuck in `Confirmed` while the Consumer says they received nothing. Shift asks the external provider for the current state, then reloads the page. A new line in **Voucher history** means the order moved; no new line means the provider still holds it in the same state, so escalate to Paylead rather than syncing again. **Voucher downloads** logs every download, with the Shift account that clicked and the date, visible to anyone who opens that voucher afterwards. Download the PDF only when the ticket requires it: you are creating an auditable trace on a Consumer's personal document. The **Download** button appears in the card header once the provider has produced a file. An order that never reached `Ready` shows an empty card, so a Consumer asking for their voucher code on such an order needs the order fixed, not a re-send. ## What's next The full Level 1 triage playbook, from ticket intake to resolution. Every Reward, voucher, and synchronization status, with the exact transitions and root causes. # Coupons Source: https://docs.paylead.fr/program/shift/coupons Create, publish, and steer discount Coupons in Shift: pick between a generic code and a file of unique codes, choose the Brand, fill the form, and follow the Coupon once it is live. A Coupon is a discount your [Consumers](/glossary#consumer) claim in the bank app and redeem at a merchant, either by typing a code on the merchant's website or by showing a code at checkout. Unlike a [Cashback](/glossary#cashback) [Offer](/glossary#offer), a Coupon carries no [Reward](/glossary#reward) rate and is not matched against a transaction: the discount is granted by the merchant at the point of sale. In [Shift](/glossary#shift), a Coupon is still an Offer under the hood. It shows up in the Offers detail page with a `Type` of `Generic Coupon` or `Unique coupon` (see [Edit an Offer](/program/shift/edit-an-offer)), but you create it from its own **Coupons** section, not from a [Campaign](/glossary#campaign) Paylead proposes. The **Coupons** section appears once Paylead has enabled Coupons on your [Program](/glossary#program), on top of the **Offers** role. See [Access and roles](/program/shift/access-and-roles#roles) for the role matrix. ## Generic Coupon or Unique Coupon The choice you make at the start of the creation flow decides which form you fill in next, and it cannot be changed afterwards. The two mechanics differ in how the code reaches the Consumer. | | **Generic Coupons** | **Unique Coupons** | | ---------------- | ----------------------------------------- | ------------------------------------------------------------------ | | The code | One code you type in, shared by everyone. | A file of codes you upload, one per Consumer. | | Volume | You declare it in **Coupon amount**. | Computed from the file you upload. **Coupon amount** is read-only. | | Per-Consumer cap | Not available. | **Maximum number per consommer**, `1` by default. | | Typical use | An online promo code for a seasonal push. | A one-shot in-store code that must not be reused. | Both mechanics carry the same **Coupon type** selector (`QR Code`, `EAN`, or `Code`), which sets how the code is rendered to the Consumer. It is independent of the generic/unique choice: a Generic Coupon can still be displayed as a QR code. ## Browse your Coupons The **Coupons** section opens on the list of your Coupons, split into the same four status tabs as the Offers list: **Live**, **Pending**, **Finished**, and **All**. See [Status reference](/program/shift/status-reference#offers) for what each status means. Above the table, three filters narrow the list: a keyword search, and a **Date From** and **Date to** pair. Each row carries: * **Merchant**: the [Brand](/glossary#brand) the Coupon is attached to, with the Coupon reference underneath. Sortable. * **Segments**: the [Segments](/glossary#segment) the Coupon targets. Shown only when Segments are enabled on your Program. * **Type**: `Generic Coupon` or `Unique coupon`. * **Reward**: despite the header, this column carries the code: the generic code on a Generic Coupon, the uploaded file name on a Unique Coupon. * **Period**: the start and end dates, or an infinity sign when the Coupon has no end date. Sortable. * **Redemption**: the share of the declared volume already claimed by Consumers, as a percentage with a pie chart. It reads `-` while no volume is known. * **Status**: the Coupon's current status. Two icons at the end of the row act on the Coupon: the edit icon opens its form, the duplicate icon starts a copy (see [Duplicate a Coupon](#duplicate-a-coupon)). ## Create a Coupon Creating a Coupon is a three-screen flow: pick the mechanic, pick the recipient Brand, then fill the form. **Cancel** is available on each of the three screens and returns you to the list. From the Coupons list, click **Create a coupon**. The **Coupons / Select** screen opens. Click **Create offer with generic coupon** or **Create offer with unique coupon**. The choice cannot be changed afterwards, see [Generic Coupon or Unique Coupon](#generic-coupon-or-unique-coupon). The **Offers / Recipients** screen opens on "Choose recipients". Search a Brand by name, then click its card; each card shows the Brand logo and its number of [Stores](/glossary#stores). Only one Brand can be selected: clicking a second card replaces the first, and **Next** stays disabled until you have picked one. **Next** opens the **Generic coupon** or **Unique coupon** form, titled with the Brand you just picked. Fill it in as described in [Fill in the Coupon form](#fill-in-the-coupon-form). Click **Save**. If a required field is missing, the form stays open and flags it. On success, Shift flashes "Coupon successfully edited." and returns you to the Coupons list. ## Fill in the Coupon form Both forms share the same three cards: **Essential**, **Channel**, and **Legals terms and application**. Once the Coupon has been saved at least once, the **Essential** card header also shows its **Coupon reference** with a **Copy** action. ### Fields common to both forms * **Coupon name**: the Consumer-facing name. Required. * **Segments**: the Segments to target. The field appears only when Segments are enabled on your Program, and is disabled when no Segment exists. See [Segments](/program/shift/segments). * **Description**: the Consumer-facing description. Required. * **Date From** and **Date to**: the activation window. **Date From** is required and cannot be earlier than the publication date; **Date to** must be at least a day later, and can be left empty for a Coupon that never ends. A hint under each field spells out the effective moment in Paris time: start dates land at `00:00:00`, end dates at `23:59:59`. * **Coupon type**: `QR Code`, `EAN`, or `Code`. Required. * **Discount**: the discount value, with a selector next to it to express it in `€` or in `%`. Only one of the two is stored, so switching the unit reinterprets the number you typed. * **Visual**: click **Select a picture** in the right-hand panel. PNG or JPEG, at most 5 MB, at least 750 by 421 pixels, displayed in 16:9. **Name**, **Description**, and the legal terms are held per language: when your Program runs more than one language, use the language control next to the field to edit a specific locale. ### Fields specific to a Generic Coupon * The code field, between **Coupon type** and **Coupon amount**, holds the single code every Consumer will use. It carries no label, only the placeholder `Ex. BLACKFRIDAY10`. Required. * **Coupon amount**: how many times the code can be claimed in total. Required. ### Fields specific to a Unique Coupon * **Coupon file**: click **Select a file** to upload the list of codes, a CSV with one code per line. Required on a new Coupon. * **Coupon amount**: read-only, derived from the file you upload. * **Maximum number per consommer**: how many codes a single Consumer can claim. Defaults to `1`. ### Channel and legal terms The **Channel** card sets where the Coupon can be redeemed: * **Channel**: `Online`, `In store`, or `Online & In store`. * **Channel URL**: the merchant page where the code is entered. Required when the channel is `Online`. The **Legals terms and application** card holds one required text area for the legal text bound to the Coupon. Once the Coupon is saved, a card under the form lists the Stores it covers, with their name, merchant, zip code, city, and company number. ## Schedule the publication Publication is what makes the Coupon reach Consumers, and it is separate from the **Date From** you set in the form. A new Coupon is pre-set to publish the next day. The **Summary** card at the top of the form lists what the Coupon needs before it can go live: **Coupon details**, **Legal Terms**, and **Published on**. The date next to **Published on** opens the **Coupon publication** dialog; on a saved Coupon it opens from the **Modify** link on the **Current state** row instead. In the dialog, select **As soon as possible (tomorrow)**, or **At a specific date and time** to enable the date picker and the hour selector beside it (whole hours only, `00:00` to `23:00`, Central European time). **Confirm** applies it: the date cannot be earlier than now, nor later than the day before the Coupon's start date. The publication date is stored with the rest of the form, so you still have to click **Save** for the new schedule to take effect. The Coupon becomes visible to Consumers when that date is reached, not before. ## Steer a published Coupon Reopening a saved Coupon from the edit icon in the list shows the same form, topped by a **Summary** card that carries its status badge and its live counters: | Row | What it shows | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Current state** | `Waiting for publication` while the publication date is ahead, with a **Modify** link that opens the [Coupon publication](#schedule-the-publication) dialog, plus a progress bar counting the days left until publication and then until activation. | | **Remaining time** | The days left before the end date, as a progress bar. An infinity sign replaces the count when the Coupon has no end date. **Modify** scrolls you to the date fields. | | **Remaining coupons** | The declared volume minus what Consumers have already consumed. **Modify** scrolls you to the volume fields. | | Activation | A toggle labeled `Active` or `Inactive`. Switching it off deactivates the Coupon when you save. | A Coupon is steered by volume, not by budget: **Remaining coupons** is the counter to watch. ### What stays editable How much of the form you can still change depends on where the Coupon is in its life: | Situation | What you can change | | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Not started yet (start date in the future) | Everything. | | Running (start date passed, still active) | **Coupon name**, **Segments**, **Description**, **Date to**, **Discount** and its unit, the visual, **Channel URL**, the legal terms, and the activation toggle, plus the code and **Coupon amount** on a Generic Coupon. Locked: **Date From**, **Coupon type**, and on a Unique Coupon **Coupon file** and **Maximum number per consommer**. | | Ended (end date passed) | Nothing. A banner says so. | | Deactivated | Nothing except the activation toggle. | Deactivating a Coupon is reversible as long as its end date has not passed: reopen it and switch the toggle back to `Active`. This differs from a `Reward` Offer, where deactivation is final (see [Edit an Offer](/program/shift/edit-an-offer)). To stop a Coupon, deactivate it or let its end date pass. To change a locked field such as **Date From** or **Coupon type**, duplicate the Coupon and deactivate the original. ## Duplicate a Coupon Duplication is how you roll a Coupon over into a new period, or run parallel Coupons on the same Brand for different Segments. The duplicate icon at the end of a row opens a fresh form pre-filled from the source Coupon, with the same mechanic. Shift resets the fields that must not be shared between two Coupons: * The name is prefixed with `[Copy] `. * **Date From**, **Date to**, and the publication date are cleared. * The Coupon reference is cleared. The copy gets its own once you save it. Everything else is carried over: the recipient Brand, the Segments, the discount, the visual, and the legal terms. Nothing is written until you click **Save**. ## What's next Credit Gifts to Consumers in bulk, outside the Offer catalog. Find a Consumer and review the Offers and Rewards tied to their account. # Customer support workflow Source: https://docs.paylead.fr/program/shift/customer-support-workflow The pre-flight checklist your Level 1 support team runs in Shift before escalating a missing or unexpected Reward to Paylead. When a [Consumer](/glossary#consumer) reaches out about a [Reward](/glossary#reward) they expected but did not receive, work through this checklist in Shift before opening a ticket with Paylead. Most tickets resolve at one of these steps, without ever reaching Paylead. ## Before you start You need three things on hand: * **The Consumer ID.** Shift searches on that ID only, never on a name, an email, or a phone number. Look it up in your own customer record before opening Shift. See [Browse Consumers](/program/shift/browse-consumers#find-a-consumer). * **The purchase details** the Consumer is disputing: date, amount, merchant, and whether they bought online or in store. * **The right roles.** Checks 1 to 6 run entirely inside **Consumers**, which the **Consumer support** role opens. Checks 7 and 8 open the **Offers** section, which needs the **Offers** role. If you do not hold it, run the first six checks and hand the last two to a teammate who does, rather than closing the ticket early. See [Access and roles](/program/shift/access-and-roles#roles). The activity tabs of a Consumer profile keep the filters from the previous ticket, including the date range. Clear them before starting, or you will conclude that a Reward is missing when it is only filtered out. See [Browse Consumers](/program/shift/browse-consumers#find-a-consumer). ## Pre-flight checks Work through the checks in order. Stop as soon as you find the answer; most complaints fail one of the first three. In [Consumers](/program/shift/browse-consumers), paste the Consumer ID in the search field and click **Search**. * **A profile opens.** The Consumer is onboarded. Continue to the next check. * **No profile opens.** The search is exact, so a single wrong character looks the same as a Consumer who never onboarded. Retype the ID from your customer record and search again. If it still returns nothing, the person has not completed onboarding on your [Program](/glossary#program): no Reward can be generated, and the ticket ends there. Reward attribution relies on the bank account the Consumer enrolled when they subscribed. Open the **Synchronizations** tab of the profile: it lists each bank connection and, under each bank name, the accounts linked to it. Those are the accounts Paylead receives transactions from. Do not use **Target account** for this check. That field is the IBAN that receives the payouts, which is not necessarily the account the purchase was made from. If the purchase was made with a card linked to an account absent from that list (a joint account from a partner, a secondary card, a non-enrolled product), no Reward is generated, even if the merchant is in the catalog. Say so to the Consumer and point them to the enrollment screen in your app. Still in the **Synchronizations** tab, compare **Last successful connection** to the purchase date. If the last successful sync is older than the purchase, the bank feed never delivered that transaction and no Reward could be generated. Have the Consumer reconnect their account from your app, then check the **Rewards** tab again the next day. Paylead needs the transaction to land on its side, which takes up to **72 business hours**, or three working days, from the purchase. Compare the purchase date to today. * **Inside the window.** Nothing is wrong yet. Tell the Consumer their purchase is still being collected and ask them to come back after one more business day. Close the ticket. * **Outside the window.** Continue to the next check. In [Consumers](/program/shift/browse-consumers) > the Consumer's profile > **Consumer activity** > **Rewards**, look for a Reward with the `Not attribued` status. The status filter cannot isolate it, so leave it on `All` and scan the list by date. If you find one, the [Cashback](/glossary#cashback) was generated but assigned to a different source. Common causes: * The Consumer is onboarded on a second Paylead Program (e.g. with another bank) and that Program won the [Reward Attribution](/program/user-journey/guides/reward-lifecycle#reward-attribution) round. * The transaction comes from a joint account and the co-owner's Program won attribution. * The transaction was reported through an account aggregator as well as the bank's own feed, and the aggregator path was deduplicated out. Open the Reward and scroll to the **Attributions** card. A card means the arbitration is settled: another source was credited, and nothing in Shift reverses it. No card means no competitor was recorded at all, so escalate. See [Reading the Attributions card](#reading-the-attributions-card) below, and the [Status reference](/program/shift/status-reference#pool) for the full Pool status table. In [Consumers](/program/shift/browse-consumers) > **Consumer activity** > **Offers**, search by the merchant's name and use the date filter to confirm an [Offer](/glossary#offer) existed on the day of the purchase. The dates and the [Brand](/glossary#brand) must match exactly; a one-day gap is enough to disqualify the transaction. No Offer on that date means no Reward was ever possible. That is the answer to the Consumer, and the ticket ends here. An Offer that matched at the moment of the purchase can be out of reach today. Open the Offer in **Offers** and check that it is either: * `Active`, or * ended less than 30 days ago, and not `Completed`. An Offer that ended more than 30 days ago, or that reached its budget cap and turned `Completed`, produces no Reward. That is the answer to the Consumer. Then check that the Consumer has not hit their personal capping on this Offer. The **Activations** column of their **Offers** tab shows usage so far: see [Reading the Activations column](/program/shift/browse-consumers#reading-the-activations-column). Click the pencil icon on the Offer to open its details. Compare the transaction to each condition: * Eligible channel (online, in-store, or both). * **Rewarded price range**: the transaction amount must fall inside it. * **Maximal transaction eligible amount**: transactions above this cap are not rewarded. * Any loyalty rules attached (first-time buyer, frequency cap, etc.). A single missed condition is enough to disqualify the Reward, and it is the answer to give the Consumer. Every check passed and no `Not attribued` Reward exists: the case is genuinely unexplained. Escalate it. The transaction itself lives on the bank's side, not in Shift. If you can reach an account statement or your own back office, find the exact transaction and check its amount, date, channel, and Brand against the Offer's conditions. ## Reading the Attributions card When several candidates claim the same transaction, Paylead keeps one of them and marks the rest `Not attribued`. The **Attributions** card shows how that arbitration went. It sits at the bottom of the Reward detail page, under **Reward details** and **Reward history**, and appears only when the Reward had competitors. Each row is one candidate. Only your own row is named, with your Program name; competing rows keep a blank first cell. | Column | What it shows | | -------------------------- | -------------------------------------------------------------------------------------------------------------------- | | (no header) | Your Program name, on your row only. Blank on every competing row. | | **offer detail view** | A check mark per candidate. Solid when an Offer detail view is recorded for that candidate, greyed out when none is. | | **Onboarding score** | A bar filled in proportion to the candidate's onboarding score. | | **Last touch point score** | A bar filled in proportion to the candidate's last touch point score. | | **Rewarding score** | A bar filled in proportion to the candidate's rewarding score. | | **Global score** | The candidate's final score, as a percentage with up to two decimals. | The three middle columns are progress bars with no printed figure: a full bar is the top of the range, an empty bar is zero. **Global score** is the only exact number, so compare rows on that column. It tells you how close your Program came to winning the transaction, and the three bars tell you which criterion decided it. The highest **Global score** wins the Cashback, and Paylead does not disclose how the three underlying scores are weighted into it. ## When to escalate Escalate only after the eight checks above, and only when none of them explains the case. Open the ticket from the **Support** button at the bottom left of Shift, the only channel for a support request. Include the following: * `consumer_id` * Purchase date and approximate time * Transaction amount * Brand name * `reward_id` if a Reward was generated in any status * Which of the eight checks you ran and what you found Do **not** include personal data (full name, IBAN, card number, address) in the ticket body. The Consumer ID is enough for Paylead to look the case up. Paylead may ask for a proof of purchase in rare cases; provide it only on request and through a secure channel. ## What's next What every status in the checklist means. See Reward and Gift volumes at the Program level once individual tickets are resolved. # Edit an Offer Source: https://docs.paylead.fr/program/shift/edit-an-offer Adjust a published Offer's Consumer-facing content and highlight level, deactivate it, or layer time-bounded Reward rate phases on top of its default rate. A published [Offer](/glossary#offer) is not frozen. Open it from the **Offers** list to review its configuration, adjust its Consumer-facing content, deactivate it, or layer a Reward rate boost on top of its default rate for a limited time. A few fields stay locked once the Offer is live. Open the Offer from the **Actions** column at the end of the row: the edit icon opens its detail page, the performance icon opens [Offer performance](/program/shift/offer-performance). An Offer sits in the **Live** tab with an `Active` or `Published` badge, and only `Active` is visible to Consumers. See [Status reference](/program/shift/status-reference#offers) for what each Offer status means. ## Offer overview The detail page opens on the Offer's read-only configuration, organized into blocks: * **Offer's lifespan**: `Dates` (configured start and end), `Publication date` (when the Offer was created; it becomes visible to Consumers at the start date), `Offer date expired`, `Offer deactivated`, and `Budget reached`, each populated only once the corresponding event has happened. * **Reward information**: `Type` (`Reward`, `Reward LBS`, `Generic Coupon`, or `Unique coupon`; a Voucher Offer carries no `Type` row), `Current reward rate` (the [Cashback](/glossary#cashback) rate paid to the [Consumer](/glossary#consumer)), `Rewarded price range`, `Maximal transaction eligible amount`, `Validation delay`, and `Channel` (for example "Offer at local store only"). These carry over from the Campaign, see [Review a Campaign's conditions](/program/shift/publish-offers#review-a-campaigns-conditions). * **Audience reach**: `Targeting` (whether the Offer carries eligibility criteria), `Control group` (whether a slice of the audience is excluded for measurement), and `Estimated audience`, covered in [Read the estimated audience](#read-the-estimated-audience) below. * **Reward Rate Phase**: an **Add** button and a timeline strip. The strip shows the Offer's start and end dates, its default Reward rate in bold (`--%` when it has none), and beside it the Campaign playground's ceiling as "Commission max. X%", the highest rate any phase can reach. The zone reads `No reward rate phase planned` until you add a phase (see [Adjust the Reward rate](#adjust-the-reward-rate)). * **Brand details** and **Program details**: the [Brand](/glossary#brand) and [Program](/glossary#program) name and logo. To measure this Offer's turnover, Rewards, fees, and activity, see [Offer performance](/program/shift/offer-performance). ### Read the estimated audience `Estimated audience` is how many Consumers the Offer actually reaches, the figure to check when it targets a [Segment](/glossary#segment) or carries eligibility criteria. Paylead computes it once the Offer is running, so the row reports one of three states. | What the row shows | What it means | | ------------------------------------ | ------------------------------------------------------------------------------- | | "Will be computed when offer starts" | The Offer's start date is still in the future. No count has been run yet. | | "Computing in progress" | The Offer has started and the count is running. Come back later. | | A number, followed by `[ Download ]` | The count is done. The number is the audience reached, and the link exports it. | The **Download** link appears in the third state only, and exports a CSV named after the Offer's reference. This export describes your own customers. Handle the file as personal data, under your bank's own data protection rules. The export carries six columns: `consumer_id` (a pseudonymized identifier), `is_consumed`, `activations`, `capping_reached`, `eligibility_starts_at`, and `eligibility_ends_at`. It holds no name, email address, phone number, or IBAN, but the pseudonymized identifier still points at a person. ## Adjust Consumer-facing details The **Quick edit** panel, alongside the overview, carries the editable fields and a live countdown ("Remaining time") to the Offer's end date: * **Offer name**: the name shown in the catalog. * **Description**: the Consumer-facing description. * **Legal Terms**: the legal text bound to the Offer. The **Start date** and **End date** buttons under this field insert dynamic tags, not dates: each expands, for each Consumer, to the date they became eligible and the date they leave the audience. * **Channel URL**: the online store URL for the Offer (the field's placeholder reads "Online store URL"). Required when the Offer is available online. * **Highlight level**: `Normal`, `High`, or `Highest`, how prominently the Offer is surfaced in the catalog. * **Active offer** toggle: switch it off to pull the Offer out of the catalog. It disappears once the Offer is `Ended` or `Completed`. On a field that supports several languages, the language icon next to it applies your edit to one locale only, for example the French **Description** while leaving the English one untouched. The Offer's start and end dates are read-only, in the **Offer's lifespan** block of the overview. On a `Reward` Offer, deactivation is final: Shift asks you to confirm, and once the Offer is inactive the toggle stays disabled. Other Offer types can be reactivated. Deactivation is judged on the transaction date, not the processing date: a transaction made before you deactivate can still generate a Reward when it is processed later, and one made after never will. ### Change the visual The illustration at the top of the detail page is editable too, and the control you get depends on the Offer: * **`Reward` Offers**: pick another illustration from the Campaign's visuals, or click **Custom** to upload your own PNG or JPEG of 4 MB or less. The upload joins the picker as an extra choice. * **Every other Offer type**: a single uploader takes a PNG or JPEG of 5 MB or less, at least 750 by 421 pixels. The cross icon over the image removes it, after a confirmation reading "Please confirm to delete this picture." * **`Ended`, `Deactivated`, or `Completed` Offers**: the visual is read-only, like the rest of the panel. Shift confirms an upload with "File successfully uploaded", but the visual is bound to the Offer only when you click **Save**. ### Save your changes **Save** sits at the bottom of the Quick edit panel, next to the **Active offer** toggle. Nothing you change in the panel, the toggle included, reaches Paylead until you click it. * The button stays disabled while any field is invalid, for example a missing **Channel URL** on an Offer available online. * The whole block, toggle and button together, is absent once the Offer is `Ended`, `Deactivated`, or `Completed`. Those Offers are read-only. * On success, Shift confirms with "Offre edited with success." and takes you back to the Offers list. Reopen the Offer to check the saved values or make another change. The default Reward rate and the Offer's eligibility conditions (the Rewarded price range and the Maximal transaction eligible amount) are locked once the Offer is published. To run different terms, [publish another Offer](/program/shift/publish-offers) from the same [Campaign](/glossary#campaign), then deactivate this one. ## Adjust the Reward rate The **Reward Rate Phase** zone lets you layer time-bounded boosts on top of the Offer's default rate, useful to amplify a marketing push or a seasonal moment without rebuilding the Offer. Rules that govern a phase: * Every phase is attached to one phase of the Campaign behind the Offer, picked at the top of the dialog. That Campaign phase sets the rate ceiling and caps the end date. * A phase starts tomorrow at the earliest, never before, and never earlier than the start of the Campaign phase it is attached to. It ends no later than the earlier of the Offer's end date and the Campaign phase's end date. * The slider starts at the Offer's default rate, and the numeric field beside it takes the same bounds. A rate above the Campaign phase's ceiling is refused. * A phase that has already ended is read-only, as is every phase once the Offer's status is `Ended`, `Completed`, or `Deactivated`. A phase that has started but not ended can still have its dates and its rate changed. * Phases can overlap. When they do, the highest rate applies for the duration of the overlap. The **Add Reward Phase** dialog opens on the list of the Campaign's phases, each showing its commission range and its dates. Click **Select** on the phase you want to build on. The configuration form replaces the list. Pick **Date From** and **Date to**, within the bounds listed above. Move the **Reward rate** slider, which runs from the Offer's default rate to the Campaign phase's ceiling, or type a value in the numeric field beside it. Click **Save** to register the phase. It appears as a new block in the timeline. Hover a phase's block in the timeline to reveal its actions: **Adjust** on a phase that has not started, **Details** on one that has (both open the **Edit Reward Phase** dialog), and **Delete**. **Delete** does not show on a phase that has already started, on the Offer's last remaining phase, on a phase with no rate of its own (one inherited from the Campaign), or once the Offer is `Completed`. Deleting a phase cannot be undone. To wind a boost down early rather than erase it, edit its end date instead: a phase that has started still accepts a new end date, no earlier than today. Rate changes apply going forward only. [Rewards](/glossary#reward) already attributed at a previous rate are not retroactively recalculated. ## What's next Credit Gifts to Consumers in bulk, outside the Offer catalog. Find a Consumer and reconstruct their Offer, Reward, and Voucher activity. # Gifts Source: https://docs.paylead.fr/program/shift/gifts Credit Gifts to your Consumers in bulk and track their payment lifecycle. A [Gift](/glossary#gift) lets you credit a [Consumer](/glossary#consumer) directly without requiring a transaction. Use Gifts to recognize loyalty, offer goodwill credits, or fund a one-off bonus operation: anything you decide to pay a Consumer when no purchase justifies a [Reward](/glossary#reward). A support gesture after a complaint, a welcome bonus, and a referral credit all take this route. You credit Gifts in bulk, by CSV import. Each Gift then follows the same status flow as a [Cashback](/glossary#cashback) Reward: `Pending validation`, `Validated`, `Pool`, then `Paid`. It ends credited to the Consumer's bank account, exactly like a Cashback. See [Status reference](/program/shift/status-reference#gifts) for the definition of each status. Once imported, a Gift is read-only: you upload the file, then watch the statuses move. Validation and payment run on Paylead's payout cycle. ## Filter the list The Gifts list opens on five tabs, each carrying its own count. The tab labels differ from the **Status** values they filter on: | Tab | Status shown in the list | | ------------- | -------------------------------- | | **All** | every Gift, regardless of status | | **Validated** | `Validated` | | **Paid in** | `Pool` | | **Pending** | `Pending validation` | | **Paid out** | `Paid` | See [Status reference](/program/shift/status-reference#gifts) for what each status means. The **Bank wire** column confirms a Gift was actually transferred: it reads `-` until the payout carrying it is issued, then holds the wire transfer reference. ## Open a Gift Click the preview icon at the end of a row to open the Gift on its own page, which holds two cards. ### Details | Field | Content | | ---------- | ---------------------------------------------------------------------- | | **Name** | The Reward name carried by the `reward_name` field of the import file. | | **Amount** | The amount credited to the Consumer, in euros. | | **Status** | The Gift's current status. | When the Gift carries a comment, Shift displays it next to the status, truncated to 75 characters. Hover it to read the full text. The comment carries the reason behind a status, for example why a Gift was cancelled. Read it before escalating a support ticket about a Gift that did not reach the Consumer. ### History The **History** card lists the statuses the Gift went through, each with the date it was recorded. Use it to see when the Gift moved to `Pool`, or whether it ever left `Pending validation`. ## Import Gifts Open the **Gifts** section in Shift, then click **Import**. A modal opens, titled **Import gifts by CSV**. The first line must be a header, written exactly `consumer_id;amount;reward_name` in lowercase, even though the modal shows the format in uppercase. Each following line holds one Gift, with the same three fields in the same order: ```csv theme={null} consumer_id;amount;reward_name consumer-uuid-001;25.00;Holiday bonus consumer-uuid-002;50.00;Referral credit consumer-uuid-003;15.50;Birthday gift ``` Fields are separated by a semicolon. The amount is a positive number with at most two decimals, written with a dot (`25`, `25.5` and `25.00` all pass; `25,00` and `-25` are rejected). Click **Select a file** and choose your CSV. Shift checks the file in the browser and, if every line passes, uploads it straight away, with no confirmation step. It confirms with **Gift imported successfully.** and refreshes the list. Imported Gifts start at `Pending validation`. ### If the file is rejected If any line fails the check, nothing is uploaded. The modal reports how many errors it found and lists the offending lines, each prefixed with **Line** and its number; a bad header line is reported as **Line Header**. Two buttons are offered: **Close** to abandon the import, and **Start again** to pick another file. A line is rejected when: * the header line is not exactly `consumer_id;amount;reward_name`; * the Consumer ID is empty; * the amount is negative, uses a comma, or carries more than two decimals; * the Reward name is empty. ### After the import The Gifts appear straight away on the **Pending** tab, then move to `Validated`, `Pool`, and `Paid` as the payout cycle runs, the same cycle that carries Cashback Rewards. Follow one Gift in the **History** card of its page, and the whole batch through the five tabs of the list. Check the file before you upload it. A Gift imported with the wrong amount, or against the wrong Consumer, cannot be corrected or cancelled, and it reaches `Validated` almost immediately. The import is the last point where you control what gets paid. ## Reconciliation in Invoices Gift payouts are reconciled in the **[Invoices](/program/shift/invoices)** section, under the **Gifts** tab. Every `Gift` invoice there is a charge to your Program: Paylead bills you back for the Gifts that reached your Consumers, and the **Gifts VAT** column carries the amount transferred. Narrow the list by date, download the PDF, and check it against the Gifts you imported over the same period. **Invoices** opens with the **Financial** role, not **Gifts**. Ask a teammate who holds **Financial** to take this step, or have both roles assigned to your account. See [Access and roles](/program/shift/access-and-roles#roles). ## What's next Find a Consumer and check the Gifts and Rewards on their account. Triage a support ticket about a missing or unexpected credit. # Invoices Source: https://docs.paylead.fr/program/shift/invoices Browse and download the five invoice types Paylead issues for your Program, and tell at a glance which ones charge you and which ones pay you. **Invoices**, a top-level entry of the Shift sidebar, is the billing archive of your [Program](/glossary#program): every document Paylead issued for the money moving between Paylead and you. You come here at the end of an invoicing cycle to check what you owe, confirm what you are owed, and hand the PDFs to your accounting team. Paylead issues all five document types, including the ones raised on your Program's behalf, so you receive the document rather than issuing it yourself. Paylead's name on an invoice therefore tells you nothing about who pays. **Money runs in both directions**: three types charge your Program, two record what Paylead owes your Program. Read the **Type** column before the amount. ## Invoice types The **Type** column carries one of five values. | Type | Who pays whom | What it covers | | ----------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------- | | `Gift` | Your Program pays Paylead | Reimbursement for the [Gift](/glossary#gift) Rewards you distributed to your [Consumers](/glossary#consumer). | | `Revenue` | Paylead pays your Program | The commission you earn on the [Cashback](/glossary#cashback) [Rewards](/glossary#reward) your Consumers generated. | | `Voucher` | Your Program pays Paylead | The face value of the vouchers distributed to Consumers, which your Program reimburses. | | `Voucher revenue` | Paylead pays your Program | The commission your Program takes on that voucher activity. | | `Voucher budget` | Your Program pays Paylead | The money your Program advances up front to fund those vouchers, under the cash advance mechanism. | The three voucher types, and the **Voucher budget** and **Vouchers** tabs below, appear only on Programs that run vouchers. A `Revenue` invoice is settled by the wire transfer recorded on the matching [Ventilation](/glossary#ventilation) row: the **Invoice reference** column of [Ventilations](/program/shift/ventilations#columns) carries the same reference. ## Browse invoices Tabs filter the list by type: | Tab | Shows | | ------------------ | ----------------------------------------- | | **All** | Every invoice. | | **Gifts** | `Gift` invoices. | | **Revenue** | `Revenue` and `Voucher revenue` invoices. | | **Voucher budget** | `Voucher budget` invoices. | | **Vouchers** | `Voucher` invoices. | The **Revenue** tab pools `Revenue` and `Voucher revenue`: read the **Type** column to tell the two apart, or click the **Type** header to sort the tab by type. Use the keyword search and the **Date From** and **Date to** fields to narrow the list by creation date. Without filters, the list holds every invoice since the Program launched. Switching tabs clears the keyword search, both date fields, and the column sort, so set your filters again after each tab change. ### Columns Click the **Date**, **Invoice**, or **Type** header to sort the list on that column, and click it again to reverse the order. The list opens on the most recent invoice first. | Column | Description | | -------------- | --------------------------------------------------------------------------------------- | | **Date** | The invoice creation date. | | **Invoice** | The invoice reference number. | | **Type** | The invoice type: `Gift`, `Revenue`, `Voucher`, `Voucher revenue`, or `Voucher budget`. | | **Gifts VAT** | The amount of Gifts transferred, VAT included. Reads `-` on `Revenue` invoices. | | **Fees VAT** | The [Program Manager](/glossary#program-manager) commission, VAT included. | | **Amount VAT** | The invoice total, VAT included. Reads `-` on `Revenue` invoices. | Three money columns end in VAT, and Shift shows the one that is the row total in bold: **Amount VAT** on every type except `Revenue`, where the total is **Fees VAT**. Book the figure shown in bold and treat the other two as breakdown. To reconcile **Gifts VAT** against the Gifts you distributed, see [Gifts](/program/shift/gifts). ## Download or view an invoice Click the download icon on a row to retrieve the invoice as a PDF to your computer, or the view icon to open it in a new browser tab. Shift is where an invoice is published, not where it is settled. Paylead invoices are payable within 30 days of the invoice date, and you track settlement in your own accounting system. ## What's next Generate and manage the API keys that authenticate your integration. Subscribe to Ventilation and payout events in real time. # Offer performance Source: https://docs.paylead.fr/program/shift/offer-performance Read the turnover, Rewards, fees, and activity generated by one published Offer, and export the data for reporting. Use **Offer performance** to measure whether one published [Offer](/glossary#offer) is doing its job: how much turnover it drives, how many [Rewards](/glossary#reward) it triggers, and what it costs your [Program](/glossary#program) in Cashback and fees. It is a read-only view. To change the Offer's content or Reward rate, use [Edit an Offer](/program/shift/edit-an-offer). Open it from the **Offers** list: click the performance icon in the row's **Actions** column. The header reads **Performance / ``**, with **Export** and **Back** beside it. ## Set the period Every figure on the page is scoped to a period you choose. The field under the header shows the current selection as month, year, and granularity, for example `August 2026 (Monthly)`. The page opens on the current month, at `Monthly` granularity. Click that field to open the picker: * Step the month back and forward with the arrows on the month button. * Step the year back and forward with the arrows on the year button, up to the current year. * Click the granularity button to switch between `Monthly` and `Daily`. * Click **Confirm** to reload every tile, section, and chart for the new period, or **Cancel** to keep the current one. ## KPI tiles On a `Reward` Offer, seven tiles summarize its performance over the selected period. | Tile | What it tells you | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Generated turnover** | Total amount [Consumers](/glossary#consumer) spent on transactions matching the Offer's conditions, that is sales at the [Brand](/glossary#brand). Your Program's own revenue is **Total fees**. | | **Average basket** | Average amount of a transaction that qualified for the Offer. | | **Number of Rewards** | How many Rewards the Offer triggered. | | **Participation Rate** | Average number of Rewards per Consumer, printed as a plain number. | | **Total amount of Rewards** | Cumulative [Cashback](/glossary#cashback) paid out by the Offer. | | **Total fees** | Cumulative commission your Program collected on the Offer. | | **Average reward** | Average Reward amount per qualifying transaction. | Every other Offer type, including `Reward LBS`, coupons, and vouchers, shows a single tile instead: **Number of participating customers**. On a `Reward` Offer, a date line on the right of the tile card reads "From beginning of the offer to" the earlier of today and the Offer's end date. It describes the Offer's lifespan; the tiles themselves follow the period selected in the picker. ## Performance sections Below the tiles, five sections break the same figures down over the same period: * **Generated turnover**: the turnover trend behind the headline tile. * **Average baskets**: the average qualifying transaction amount. * **Amount and total number of Rewards**: Cashback paid out alongside Reward volume. * **Fees**: the commission generated on the Offer. * **Activity**: **Number of transactions** and **Number of customers**, side by side, to compare Reward volume against unique Consumer reach. ## Export the data **Export** downloads a CSV named after the Offer's reference. It carries this one Offer over the period currently selected in the picker. Set the period first, then export; to cover another period, change the picker and export again. For recurring reporting across several Offers, or to reconcile with finance, use [Rewards report](/program/shift/rewards-report) or [Vouchers report](/program/shift/vouchers-report). ## What's next Export consolidated Rewards data across Offers for reconciliation. Export and reconcile voucher Rewards. # Shift overview Source: https://docs.paylead.fr/program/shift/overview Shift is the back-office where Program partners manage their Paylead integration: Consumers, Offers, Coupons, support, performance, and billing. [Shift](/glossary#shift) is the back-office for running a [Program](/glossary#program) day to day. It is where you review the [Campaigns](/glossary#campaign) Paylead proposes and publish them as Consumer-facing [Offers](/glossary#offer), issue [Coupons](/program/shift/coupons) and [Gifts](/glossary#gift), and target [Consumers](/glossary#consumer) with [Segments](/glossary#segment). It is also where you look up a Consumer to answer a support ticket, track [Cashback](/glossary#cashback) performance, and reconcile [Ventilation](/glossary#ventilation) payouts and Paylead invoices. Paylead runs the matching engine and the payout pipeline. Shift is your side of that split: the decisions only you can make (what to publish, to whom, at what rate) and the records that go with them (who earned what, who was paid, what you owe). Access is role-based: each teammate only sees the sections their role grants. See [Users management](/program/shift/access-and-roles) for the full role matrix and how to invite teammates. ## How the work sequences The sections follow one another. A new Program meets them roughly in this order. ```mermaid theme={null} flowchart LR A[Users management
invite your team] --> B[Catalog
Segments, Offers, Coupons, Gifts] B --> C[Consumers see them
in your bank app] C --> D[Support
answer a ticket] C --> E[Performance
measure what ran] E --> F[Finance and billing
pay out and reconcile] classDef neutral fill:#f1efe8,stroke:#888780,color:#2c2c2a classDef primary fill:#e6f1fb,stroke:#0465ff,color:#042c53 classDef accent fill:#e1f5ee,stroke:#0f6e56,color:#04342c classDef success fill:#eaf3de,stroke:#3b6d11,color:#173404 class A neutral class B primary class C neutral class D accent class E accent class F success ``` * **Set your team up first.** Nothing else is reachable until roles are assigned. Start at [Users management](/program/shift/access-and-roles). * **Build the catalog.** Decide who you are talking to with [Segments](/program/shift/segments), then turn the Campaigns Paylead proposes into [Offers](/program/shift/publish-offers) and adjust them later with [Edit an Offer](/program/shift/edit-an-offer). [Coupons](/program/shift/coupons) cover the discount-code mechanic instead of Cashback, and [Brands](/program/shift/brands) is the lookup on the merchants behind all of it. [Gifts](/program/shift/gifts) credit a Consumer directly when no transaction justifies a Reward. * **Answer the tickets that follow.** [Browse Consumers](/program/shift/browse-consumers) reconstructs one Consumer's activity; the [Customer support workflow](/program/shift/customer-support-workflow) tells you which question to ask first; [Status reference](/program/shift/status-reference) decodes any status you land on. * **Measure what ran.** The [Performance dashboard](/program/shift/performance-dashboard) gives the Program-level KPIs, [Offer performance](/program/shift/offer-performance) drills into a single Offer, and the [Rewards report](/program/shift/rewards-report) and [Vouchers report](/program/shift/vouchers-report) export the underlying rows for accounting. * **Settle the money.** Check the identity Paylead invoices in [Billing address](/program/shift/billing-address), pay Consumers from the [Ventilation](/program/shift/ventilations) files, and reconcile both directions of the money flow in [Invoices](/program/shift/invoices). * **Automate the parts you repeat.** [API keys](/program/shift/api-keys) authenticate your integration, and [Webhooks](/program/shift/webhooks) push events to you instead of making you poll a screen. ## Where to go for what Sign in, adjust your account, invite teammates, and check the role matrix. Everything Consumers end up seeing: Segments, Brands, Offers, Coupons, and Gifts. Look up a Consumer, reconstruct their activity, and decode any status you meet. Track Program KPIs and export Reward and voucher data for accounting. Check your billing details, pay out Cashbacks, and retrieve Paylead invoices. Generate API keys and configure Webhooks for your integration. # Performance dashboard Source: https://docs.paylead.fr/program/shift/performance-dashboard Read your Program's executive KPIs, Consumer activation, ALO Rewards, Gifts, and more, over any time window. The **Performances** section of [Shift](/glossary#shift) is the executive KPI view of your [Program](/glossary#program). It shows how many [Consumers](/glossary#consumer) are active, how many [Rewards](/glossary#reward) have been generated, and how many [Gifts](/glossary#gift) have been distributed, over any time window you choose. The sidebar entry reads **Performances** and the page heading reads **Dashboard**: they are the same screen. Every signed-in user reaches this page, whatever their roles. See [Users management](/program/shift/access-and-roles) for the full role matrix. ## Which sub-tab answers which question Each sub-tab covers one flow. Start from your question. | Your question | Sub-tab | | -------------------------------------------------------------------------------------------- | --------------- | | Is my Consumer base growing, and how much of it earns anything? | **Audience** | | How much [Cashback](/glossary#cashback) did automatic Rewards generate, and on which Brands? | **ALO Rewards** | | How are the pro merchants of my LBS network performing? | **LBS Rewards** | | How many Gifts did we hand out, and for what value? | **Gifts** | | How many discount codes were taken up? | **Coupons** | | How many gift cards did Consumers buy, and what did they save? | **Vouchers** | Totals never carry over from one sub-tab to another: a Cashback counted on **ALO Rewards** is not counted again on **Vouchers**. Read each sub-tab on its own. ### Which sub-tabs you see Three of the six sub-tabs depend on how Paylead configured your Program. | Sub-tab | Shown when | | --------------- | ------------------------------------------------------------------------------------------------------------ | | **Audience** | Always | | **ALO Rewards** | Always | | **LBS Rewards** | `has_lbs` is enabled on your Program | | **Gifts** | Always | | **Coupons** | `has_coupon` is enabled on your Program | | **Vouchers** | `has_evo` is enabled on your Program, the flag that also drives [Easy Vouchers](/glossary#easy-vouchers-evo) | If a sub-tab you expect is missing, ask Paylead from the **Support** button in Shift whether the flow is enabled on your Program. ## Choose a period Pick one of the preset ranges above the sub-tabs, or set a custom range with the **Date From** and **Date to** fields next to them. Changing the range reloads every total and chart below, and typing a date clears the highlighted preset. Each preset sets a different kind of bound. Pick the one whose bound matches what you are about to say. | Preset | Range it sets | Use it to | | -------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | | **This month** | 1st of the current month to the last day of that month | Watch the month in progress. The end bound is in the future, so the figures keep moving until the month closes. | | **Last month** | The whole previous month | Quote a closed month, the one preset that cannot change under you. | | **6 months** | 1st of the month six months back to the end of the current month | See a trend. This is the default view. | | **This year** | 1 January to 31 December of the current year | Track the year to date against its target. | | **Last year** | The whole previous year | Compare a closed year. | | **Lifetime** | No start bound, to the end of the current month | Report a running total since the Program launched. | ### How the period applies Every total, chart, and ranking on every sub-tab is bounded by the selected range. **Total onboarded since launch**, on the **Audience** sub-tab, is the exception: it always shows the running total to date. Ranges longer than 92 days, and **Lifetime**, are plotted month by month; shorter ranges are plotted day by day. That interval is the bucket the charts and counts are grouped into, and the switch is automatic: widening a custom range past 92 days re-plots the same data month by month. Some tooltips read "since the launch" on figures that are in fact bounded by the selected range: **Total subscribers**, **Total churners**, and **Total rewarded** on **Audience**, and five of the eight **ALO Rewards** totals. Trust the selected period when you quote these figures in a report. ### Share a view The sub-tab and the period are written into the page URL, as `/performances//`. Bookmark or share that URL to reopen the same view; a custom range replaces the period segment with `?start=` and `?end=` query parameters. The sub-tab segments are `consumers` (the **Audience** sub-tab), `rewards`, `lbs`, `gifts`, `coupons`, and `vouchers`. The period segments are `this-month`, `last-month`, `6-months`, `this-year`, `last-year`, and `lifetime`. So the ALO Rewards figures for the closed month sit at `/performances/rewards/last-month`. Shift opens **Audience** over **6 months** when it does not recognise a segment, so check the highlighted sub-tab and preset before quoting a figure from a link someone sent you. ## Audience KPIs The **Audience** sub-tab is the default view. It tracks how your Consumer base is growing and how many of them are earning Rewards. Each KPI carries a tooltip with its definition. | KPI | What it measures | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | **Total onboarded since launch** | Consumers registered in the Program and not churned, counted once each. Always the running total to date, whatever period you select. | | **Total subscribers** | Consumers whose sign-up date falls in the selected range. | | **Total churners** | Consumers whose unsubscribe date falls in the selected range. | | **Total rewarded** | Consumers who generated at least one Cashback on a transaction executed in the selected range. | Below the totals, three charts break the figures down over the selected period: * **Subscribers evolution**, sign-ups per bucket as bars with a running **Cumulative subscriptions** line. * **Churners evolution**, unsubscribes per bucket as bars with a running **Cumulative churners** line. * **Rewarded consumers**, distinct Consumers rewarded in each bucket. Compare **Total subscribers** against **Total rewarded** over the same range to see how much of your Consumer base earns value from the Program. Investigate a widening gap in [Browse Consumers](/program/shift/browse-consumers). ## ALO Rewards KPIs The **ALO Rewards** sub-tab covers [Account-Linked Offers](/glossary#alo-account-linked-offer), the flow where a Consumer's bank transaction matches an active [Offer](/glossary#offer) and a Cashback is generated automatically. Every figure is keyed on the transaction execution date, not on the date the Reward was validated or paid, so a Reward still awaiting validation already counts here. Eight totals appear, in two rows of four. | KPI | What it measures | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Total rewarded** | Consumers who generated at least one Cashback in the period, counted once each however many Rewards they earned. | | **Total playground** | Total [playground](/glossary#playground) budget generated: the Cashback paid to Consumers plus your commission. | | **Total commission** | Your Program's own share of the playground, on the rewarded transactions of the period. | | **Generated revenue** | Total amount of the transactions that generated a Cashback. Read it as the retail turnover the Program drove: **Total commission** is the figure that lands in your accounts. | | **Number of rewards** | Number of Cashback lines generated in the period. One transaction produces one line. | | **Reward amount** | Total Cashback paid to Consumers over the period. | | **Average reward** | Average Cashback per Reward line: **Reward amount** divided by **Number of rewards**. Averaged per Reward, not per Consumer. | | **Average basket** | Average amount of a transaction that generated a Cashback: **Generated revenue** divided by **Number of rewards**. | Three charts follow the totals: | Chart | What it plots | | ------------------------------ | ------------------------------------------------------------------------------------------------ | | **Reward amount + commission** | Your **Commission** as bars, with the **Reward amount** paid to Consumers as a line, per bucket. | | **Rewarded consumers** | Distinct Consumers who generated at least one Cashback in each bucket. | | **Number of rewards** | Cashback lines generated in each bucket. | Four rankings close the sub-tab. All four rank [Brands](/glossary#brand), whatever the heading says. | Ranking | Ranks Brands by | | ----------------------------------- | -------------------------------- | | **Number of rewards per merchant** | Number of Cashback lines | | **Reward amount per brand** | Total Cashback amount | | **Commission per brand** | Total commission | | **Average reward amount per brand** | Average Cashback per Reward line | Every ranking on the dashboard reads the same way: **Brand Name** on the vertical axis, **Count** or **Amount (€)** on the horizontal one. The ten best Brands are listed by default, and **Show all** expands a longer list. Export the underlying rows from the [Rewards report](/program/shift/rewards-report). ## LBS Rewards charts The **LBS Rewards** sub-tab appears when `has_lbs` is enabled. It covers [Local Business Solution](/glossary#lbs-local-business-solution), the interface that lets your Program's pro customers run their own [Campaigns](/glossary#campaign), and opens straight on three charts. | Chart | What it plots | | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **LBS Number of live Merchants** | Distinct LBS merchants live on each date of the range. | | **LBS Number of unregistered merchants** | LBS merchants that left, counted in the bucket of their offboarding date. This is a per bucket count, not a running total. | | **LBS Cashback - Reward amount per month** | LBS Cashback paid as bars, with the matching **Commission** as a line, keyed on the transaction execution date. Despite the heading, it follows the same granularity rule as every other chart. | For a single `Reward LBS` Offer, use [Offer performance](/program/shift/offer-performance). ## Gifts KPIs The **Gifts** sub-tab is always shown. Every figure is keyed on the Gift creation date, so a Gift counts as soon as it is issued, whether or not the Consumer has used it. | KPI | What it measures | | -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Total activated gifts since launch** | Consumers who received at least one Gift in the period, counted once each. It counts Consumers rather than Gifts, and it is bounded by the selected range. | | **Total gifts** | Number of Gifts issued in the period. | | **Total gift amount** | Total value of the Gifts issued in the period. | Three charts follow, one per measure over the selected period: **Number of gifts**, **Gift amount**, and **Activated gifts**. Use [Gifts](/program/shift/gifts) to issue a new Gift or to check the lifecycle of an individual one. ## Coupons KPIs The **Coupons** sub-tab appears when `has_coupon` is enabled. It reports two totals per Coupon family, all keyed on the Coupon creation date. Create and steer Coupons from [Coupons](/program/shift/coupons). | KPI | What it measures | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | **Total unique coupons** | Unique Coupons created in the period, counted once each. | | **Total unique activated coupons** | Consumers who had at least one unique Coupon created in the period, counted once each. | | **Total generic coupons** | Distinct Consumer and Offer pairs that produced a generic Coupon in the period. A Consumer who takes the same generic Coupon twice counts once. | | **Total generic activated coupons** | Consumers who had at least one generic Coupon in the period, counted once each. | Both "activated" totals count Consumers: read them as reach, not as redemption. Four charts follow, one per total over the selected period: **Unique coupons**, **Unique activated coupons**, **Generic coupons**, and **Generic activated coupons**. ## Vouchers KPIs The **Vouchers** sub-tab appears when `has_evo` is enabled. Every figure is keyed on the Voucher creation date, so a Voucher counts as soon as it is ordered. Five totals appear, three on the first row and two on the second. | KPI | What it measures | | ----------------------------- | -------------------------------------------------------------------------------------------- | | **Total vouchers** | Distinct Voucher orders created in the period. | | **Total voucher value** | Total face value of those Vouchers, the amount they are worth at the Brand. | | **Total voucher sales value** | Total amount Consumers actually paid to buy them. | | **Total voucher discount** | The saving passed to Consumers: **Total voucher value** minus **Total voucher sales value**. | | **Total voucher commission** | Your Program's commission on the Vouchers of the period. | Three charts follow. | Chart | What it plots | | ------------------------------- | --------------------------------------------------------------------- | | **Rewards amount + commission** | The Voucher **Discount** as bars, with your **Commission** as a line. | | **Rewarded consumers** | Distinct Consumers who ordered at least one Voucher in each bucket. | | **Vouchers** | Distinct Voucher orders in each bucket. | Three rankings close the sub-tab. | Ranking | Ranks Brands by | | -------------------------------- | ----------------------- | | **Number of vouchers per brand** | Distinct Voucher orders | | **Rewards amount per merchant** | Voucher discount | | **Voucher commission per brand** | Voucher commission | Two headings here reuse the ALO wording: **Rewards amount + commission** and **Rewards amount per merchant** both report the Voucher discount. Read them as discount, so they stay separate from the **ALO Rewards** figures. Export the underlying rows from the [Vouchers report](/program/shift/vouchers-report). ## What's next Measure the turnover, Rewards, fees, and activity generated by one published Offer. Export the underlying Reward data for accounting and BI. # Publish an Offer from a Campaign Source: https://docs.paylead.fr/program/shift/publish-offers Review the Campaigns Paylead proposes to your Program and publish the ones you accept as Consumer-facing Offers. In [Shift](/glossary#shift), the catalog builds in two stages. Paylead proposes a [Campaign](/glossary#campaign) for a [Brand](/glossary#brand): the promotional intent, with the Brand's commercial conditions attached. You review that Campaign and decide whether to publish it as an [Offer](/glossary#offer), the customized, [Consumer](/glossary#consumer)-facing item that appears in the bank app. One Campaign can produce several Offers, for example one per [Segment](/glossary#segment). ## Browse the Campaigns proposed to your Program All Campaigns Paylead proposes to your [Program](/glossary#program) live in the **Campaigns** section of Shift. Campaigns are grouped into channel tabs, each a Campaign source in its own right: **Paylead**, **Lbs**, and **Vouchers**. **Lbs** is [Local Business Solution](/glossary#lbs-local-business-solution), the interface your Program's pro customers use to build their own Campaigns. A channel tab is exposed once it is activated on your Program; ask from the **Support** button in Shift to activate or deactivate one. Within each channel, Campaigns are organized into status tabs, each with its own count: `Available`, `Accepted`, `Rejected`, and `All`. See [Status reference](/program/shift/status-reference#campaigns) for what each one means. Each Campaign row shows: * **Brand**: the [Brand](/glossary#brand) the Campaign comes from. * **Universes**: the categories the Brand belongs to. * **Parameters**: flags such as the loyalty-frequency indicator, which marks Campaigns that reward a Consumer only after a defined number of qualifying purchases (for example, a [Cashback](/glossary#cashback) on every fourth purchase at a given Brand). * **Activation period**: the window during which the Campaign can run. * **Fees**: the range of commission rates available to your Program. * **Channel**: online, in-store, or both. * An `Active` flag, present when the Campaign is currently live. The end of each row carries a preview icon that opens the details page, plus a bin icon to reject the Campaign while it is `Available`. ### Reject a Campaign Reject a Campaign to clear it out of the `Available` tab once you have decided not to publish anything from it. It changes nothing for Consumers: an `Available` Campaign was never visible to them. Click the bin icon at the end of the row, then **Confirm**. Rejecting is not a dead end: a `Rejected` Campaign keeps its details page, and publishing an Offer from it moves it to `Accepted`. ## Stay notified about Campaigns Paylead emails you on Campaign events. Choose which ones in **My account > Settings**, under **Notifications**, one by one or with the **Apply to all** toggle. | Notification | Sent when | | ---------------------------- | ------------------------------------------------------------ | | New campaign available | Paylead proposes a new Campaign to your Program. | | Campaign extension | A running Campaign's activation period is extended. | | Campaign shortened | A running Campaign's activation period is cut short. | | New visual available | A new visual becomes available to use on an Offer. | | Boosted rate phase available | A boosted Reward rate phase becomes available on a Campaign. | | Campaign ending soon | A Campaign is about to expire. | ## Review a Campaign's conditions Open a Campaign to read the conditions attached to it and decide whether its commercial terms fit your Program. The Campaign's conditions cover: * **Activation**: the period during which the Campaign can be deployed. * **Rewarded price range**: the purchase amount band that qualifies for a [Reward](/glossary#reward). A purchase below the minimum is not rewarded; a purchase above the maximum is rewarded on the capped amount. * **Maximal transaction eligible amount**: the ceiling above which the transaction is disqualified entirely, where the Rewarded price range only caps the rewarded amount. * **Channel**: online stores, physical stores, or both. * **Fees**: the commission band open to your Program, shown here from `0%` to the width of the Campaign's [playground](/glossary#playground), that is its maximum minus its minimum. The **Fees** column in the Campaign list is computed differently: it shows the playground's own minimum and maximum. * **Capping**: the maximum number of times a single Consumer can be rewarded on this Campaign. * **Targeting**: `Yes` when the Campaign restricts who is eligible, `No` when it is open to your whole audience. The **Targeting** block lower on the page shows why. * **Control group**: whether a slice of the eligible audience is excluded from the Campaign. Paylead uses it to measure the Campaign's incremental performance and report it to the Brand. * **Estimated audience**: the number of Consumers potentially targeted. * **Validation delay**: how long Paylead waits before moving a Reward generated under this Campaign from `Pending validation` to `Validated`. * **Remaining time**: time left before the Campaign expires. Three blocks follow: * **Targeting**: why the flag above reads `Yes`. It lists the Campaign's eligibility filters, names the lookalike audience it runs on, or reads "This campaign is generic." * **Brand details**: the Brand's name and universe. * **Guidelines**: the Offer description and legal terms attached to the Campaign, each with a language toggle when your Program runs more than one language. A [lookalike audience](/glossary#lookalike-audience) is built by Paylead's algorithm to optimize the Campaign's marketing performance. The summary also carries the Campaign's assets as download buttons: **Download logo** and one **Download visual `n`** per visual. These are the same visuals you pick from inside the Offer form. Once you publish an Offer from this Campaign, it appears in the lower section of the Campaign details page. ## Publish an Offer from a Campaign From the Campaign details page, click **Create an offer** to open the configuration window. A preview panel on the right reflects your changes as you make them. The steps below describe the **Paylead** channel; each channel has its own form. Enter a short, Consumer-facing name. On a Program running more than one language, a toggle above the field switches between them, one button per language (`FR`, `EN/GB`). The **Segments** field appears when Segments are enabled on your Program, and stays disabled until Paylead has created your first one. Choosing a Segment shows a live audience counter (for example `0 / 4,571`) so you can see how many Consumers the Offer would reach. By default, the Offer inherits the Campaign's activation period. Toggle **Custom dates** to set your own start and end date instead, for example to limit the Offer to the duration of a marketing push. The **Reward rate** slider sets the [Cashback](/glossary#cashback) rate paid to the Consumer. It runs between the Campaign [playground](/glossary#playground)'s minimum and maximum, and the numeric field beside it accepts the same bounds. The rate is a split, not a total: whatever you do not hand to the Consumer stays with your Program as commission. Push the slider right and the Consumer's Cashback goes up while the **Fees** figure next to the label goes down by as much, since that figure is the playground maximum minus the rate you set. The **Share** dial in the preview panel tracks the Fees side of that split, not the Consumer's. If your Program has a main banking partner declared, a toggle labeled **Only reward transactions from `{partner name}`** appears. Enable it to exclude transactions coming from other partners. Enter the Consumer-facing description, which carries the same language toggle as the name. Below the field, a link labeled **Appliquer les indications** pulls in the guide text attached to the Campaign, when the Campaign carries one. The **Legal Terms** field is mandatory and pre-filled from the Campaign's Guidelines. Use the **Start date** and **End date** buttons to insert dynamic tags that expand, for each Consumer, to the date they became eligible and the date they leave the audience. The same guidelines link sits under this field when the Campaign carries legal terms. Click the image in the preview panel to pick one of the visuals provided with the Campaign. To use your own, click **Custom** and upload a PNG or a JPEG of 4 MB or less; it joins the picker as an extra choice. **Publish** stays disabled until every mandatory field is filled. Click it to create the Offer, listed from then on in the Campaign details page. **Cancel** discards the configuration window. Publishing an Offer also moves the Campaign itself to `Accepted`. To pull a published Offer out of the catalog, deactivate it from [Edit an Offer](/program/shift/edit-an-offer). On a `Reward` Offer, deactivation is irreversible. To run different commercial terms, publish a second Offer from the same Campaign. The status the Offer lands in depends on the start date you chose: an Offer starting today goes live, one starting later waits for its date. The **Vouchers** channel uses a different form. The name, description, Legal Terms, and visual work the same way, and in place of the Reward rate slider it carries a **Discount rate** control, running from `0%` to the Campaign's own discount, with the resulting **Fees** displayed next to its label. The **Segments** field, the **Custom dates** toggle, and the guidelines link are not part of it. To publish a second Offer close to an existing one (a parallel Offer for another Segment, a rollover of one that just ended), duplicate it rather than start over. The duplicate icon sits in the actions column of the Offers table at the bottom of the **Campaign details** page: it reopens the **Create an offer** window, pre-filled from the source Offer. A duplicate keeps the source Offer's Reward rate, not the Campaign's default. Check the **Reward rate** slider before you publish it. Once published, adjust the Offer's content or its Reward rate, or layer time-bounded Reward rate phases on top, from [Edit an Offer](/program/shift/edit-an-offer). ## The Offers list Every Offer you publish lands in the **Offers** section of the sidebar, whatever channel its Campaign came from. This is where you find an Offer again to adjust it, and where Shift flags an Offer Consumers cannot see. ### Status tabs Four tabs group the Offer statuses, each carrying its own count: | Tab | Offers it shows | | ------------ | --------------------------------------- | | **Live** | `Active` and `Published` | | **Pending** | `Waiting` and `Draft` | | **Finished** | `Ended`, `Deactivated`, and `Completed` | | **All** | Every Offer, whatever its status | The list opens on **Live**. See [Status reference](/program/shift/status-reference#offers) for what these statuses mean. Above the table, the keyword search and the **Date From** and **Date to** fields narrow the current tab. Switching tabs clears the search, both date fields, and the column sort. ### Columns | Column | Content | | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Brand** | The Brand name, with the Offer reference underneath. Sortable. | | **Parameters** | One icon per targeting option, see below. | | **Segments** | The Segments the Offer targets. Present only when Segments are enabled on your Program. | | **Highlight** | How prominently the Offer is surfaced in the catalog: `Normal`, `High`, or `Highest`. Click the value to open the quick edit panel, unless the Offer is `Ended`, `Deactivated`, or `Completed`. Sortable. | | **Type** | The Offer type, for example `Reward`, `Reward LBS`, `Generic Coupon`, or `Unique coupon`. Sortable. | | **Reward** | The Reward rate on a `Reward` or `Reward LBS` Offer, the discount on a Voucher Offer, and the code or file on a coupon Offer. Reads `-` once the Offer is `Ended`, `Deactivated`, or `Completed`. Sortable. | | **Period** | The Offer's start and end dates, with the days left underneath while it runs. An Offer with no end date shows an infinity sign. Sortable. | | **Real end date** | The date the Offer actually stopped, which differs from the planned end date when the Offer was deactivated or reached its budget. | | **Completion** | The date the Offer reached its budget cap. | | **Status** | The Offer's current status. | | **Actions** | The performance icon opens [Offer performance](/program/shift/offer-performance), the edit icon opens [Edit an Offer](/program/shift/edit-an-offer). | Paylead owns the `Completed` status. The [`OFFER_ENDING_SOON_BUDGET` Webhook](/program/shift/webhooks) is what warns you that an Offer's [budget](/glossary#budget) is running out. ### Parameters icons The **Parameters** column carries the same four icons on every row. An icon is dimmed when the option is off on that Offer. Hover one to read its tooltip: | Tooltip | What it marks | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Control group** | A slice of the eligible audience is excluded from the Offer, so Paylead can measure the Campaign's incremental performance for the Brand. | | **This offer is targeted** | The Offer carries eligibility criteria, or is built on an audience lookalike. | | **Reward buying frequency** | The Offer rewards a Consumer only after a defined number of qualifying purchases. The tooltip carries that number. | | **This offer rewards transactions from** | The Offer is restricted to your Program's main banking partner. The tooltip carries the partner name, and the icon is present only when your Program declares one. | ### Change an Offer's highlight level **Highlight** decides how prominently the Offer is surfaced in the catalog, from `Normal` up to `Highest`. Use it to push one Offer forward for a seasonal moment without touching its Reward rate or its dates. Click the value in the **Highlight** column to open a quick edit panel, pick one of the three levels, then click **Save**. The change applies straight away, and you can reopen the panel to change it again. The same shortcut sits on the Offers table at the bottom of a Campaign details page. ### Offers that need a Reward rate phase A `Reward` Offer that is `Active` or `Published` but carries no default Reward rate is not shown to Consumers at all. Shift marks the row and puts a warning icon next to its **Reward** value, with this tooltip: > This Offer is not displayed to your consumers because it requires an active phase. Please provide one to display it to your consumers. On a flagged Offer, a Reward rate phase is what gives the Offer a rate at all, not a bonus on top of a working one. The default rate cannot be changed after publication: add a phase from [Edit an Offer](/program/shift/edit-an-offer#adjust-the-reward-rate), or publish a new Offer at the rate you want. ## What's next Adjust a published Offer, including its Reward rate phases. Credit Gifts to Consumers in bulk, outside the Offer catalog. # Rewards report Source: https://docs.paylead.fr/program/shift/rewards-report Export every Reward generated by your Program to CSV for accounting, reconciliation, and BI. Filter by date, status, Offer, Brand, or Campaign. The **Reporting** section in [Shift](/glossary#shift) lists every [Reward](/glossary#reward) generated by your [Program](/glossary#program) and lets you export the filtered list as CSV. Use it for monthly accounting, reconciliation against the [Ventilation](/glossary#ventilation) file, or to feed your BI pipeline. ## Which report you need Reporting opens on the **Rewards** report, which covers ALO Rewards, [Gifts](/glossary#gift), and Reward LBS. Programs that run vouchers get a second tab, where voucher purchases are tracked. | Question | Where to look | | ------------------------------------------------------------------------------------- | -------------------------------------------------- | | How much [Cashback](/glossary#cashback) did my Program generate, and on which Offers? | **Rewards**, this page. | | How much do I owe my Consumers for a Ventilation cycle? | **Rewards**, filtered on `Status = Paid`. | | How many vouchers did Consumers buy, and for how much? | [Vouchers report](/program/shift/vouchers-report). | ## Generate a report Click **Reporting** in the Shift sidebar. On a Program that runs vouchers, select the **Rewards** tab. Stack any combination of the filters below, then click **Apply filters**. Shift writes them into the page URL, so the address bar is a shareable link to that exact selection, and returns you to page 1 of the results. Check the aggregated totals for the filtered set: **Reward amount**, **Total rewards**, **Total consumers**, **Total commissions**. Click **Export**, above the results table, to download the filtered list as CSV, named `export-reports.csv`. ### Available filters | Filter | What it does | | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Date range | Pick which date the range applies to: **Created** (the default, when the Reward was created), **Updated**, or **Executed** (when the Consumer's transaction took place). Then set the **Date From** and **Date to** fields. | | **Brand** | Restrict to Rewards generated from Offers tied to a specific [Brand](/glossary#brand). | | **Status** | Restrict to one Reward status: `Cancelled`, `Pending validation`, `Validated`, `Pool`, `Paid`. | | **Offer** | Restrict to Rewards generated from one [Offer](/glossary#offer). | | **Invoice** | Filter by the invoice reference number tied to the Reward's commission. | | **Campaign** | Restrict to Rewards generated from one [Campaign](/glossary#campaign). | | **Type** | Restrict to one Reward type: **ALO Rewards**, **Gifts**, or **Reward LBS**. | | **Only valid rewards** | On by default. Keeps `Pending validation`, `Validated`, `Pool`, and `Paid`, and hides the `Cancelled` Rewards. Turn it off to investigate cancellations. | The report always covers a date range: it opens on the last 7 days and can start at most 365 days in the past. To cover a longer history, export several ranges and concatenate them. Click **Reset** to drop every filter at once and return to the default selection: date type back to **Created**, **Only valid rewards** back on, and the **Brand**, **Offer**, **Invoice**, and **Campaign** fields emptied. The date range stays in place. To reconcile against a Ventilation cycle, filter on `Status = Paid` over the cycle date range. The **Reward amount** total should match the cycle's **Total amount to allocate**. See [Ventilations](/program/shift/ventilations) to download the file and pay out the reconciled Cashbacks. ## Report columns The list pane shows one row per Reward with these columns: | Column | What it represents | | --------------- | ------------------------------------------------------------------- | | **Created** | Reward creation date. | | **Brand** | Brand attached to the originating Offer. | | **Campaign** | Campaign the Offer was derived from. | | **Offer ref.** | Offer reference. | | **Consumer ID** | Stable Consumer identifier. | | **Executed** | Date the underlying transaction was carried out by the Consumer. | | **Transaction** | Amount of the matched transaction. | | **Reward Rate** | Cashback rate configured on the Offer. | | **Reward** | Cashback amount due to the Consumer. | | **Commission** | Commission due to the [Program Manager](/glossary#program-manager). | | **Updated** | Date of the last Reward status change. | | **Type** | Reward type. | | **Status** | Current status. | For what each **Status** value means and the technical status behind it, see [Status reference](/program/shift/status-reference#rewards). ## CSV export The CSV is the full record: every column of the list pane, plus the identifiers you need to join Rewards to your own data (`transaction_external_id`, `payout_id`, `invoice_reference`) and one timestamp per status transition. | Field | Description | | ------------------------- | -------------------------------------------------------------------------------------------------------------------- | | `id` | Reward ID. | | `created_at` | Reward creation date. | | `updated_at` | Date of the latest status change. | | `status` | Current Reward status. | | `transaction_id` | ID of the transaction that triggered the Reward. | | `transaction_executed_at` | Date the Consumer's purchase was executed. | | `transaction_amount` | Amount of the matched transaction. | | `strategy_reference` | Reference of the Campaign tied to the Brand. | | `strategy_id` | Campaign ID. | | `brand_id` | Brand ID. | | `brand_name` | Brand name. | | `brand_reference` | Brand reference. | | `type` | Reward type. | | `amount` | Reward amount due to the Consumer. | | `fees` | Commission amount due to the Program Manager. | | `playground` | Total amount transferred to the Program Manager ([playground](/glossary#playground): Reward + Program fees). | | `consumer_id` | Consumer ID. | | `payout_id` | ID of the payment that transferred this Reward to the Consumer. | | `offer_id` | Offer ID. | | `offer_name` | Offer name. | | `offer_reference` | Offer reference. | | `offer_cashback_rate` | Cashback rate configured on the Offer. | | `invoice_reference` | Reference of the invoice tied to this Reward's commission. | | `transaction_external_id` | Transaction reference provided by the Program Manager at injection time. | | `segments` | [Segment(s)](/glossary#segment) the Consumer belonged to at transaction time and that matched the Offer's targeting. | | `cancelled_date` | Timestamp when the Reward switched to `cancelled`. | | `pending_validation_date` | Timestamp when the Reward switched to `pending_validation`. | | `validated_date` | Timestamp when the Reward switched to `validated`. | | `paid_in_date` | Timestamp when the Reward switched to `paid_in`. | | `paid_out_date` | Timestamp when the Reward switched to `paid_out`. | | `cancellation_reason` | Cancellation reason provided by the Brand. | This export describes your own customers. Handle the file as personal data, under your bank's own data protection rules. The CSV reflects the **current** state of each Reward, not a point-in-time snapshot. A Reward marked `Validated` last week and `Cancelled` today appears as `Cancelled` in today's export, so re-exporting the same date range next month returns different figures. For audit-grade history, subscribe to [Webhooks](/glossary#webhooks) and persist each event in your own store. See [Webhooks](/program/shift/webhooks) to set up that subscription in Shift. ## What's next The equivalent export for voucher-based Rewards. Pay out Cashbacks to your Consumers from the reconciled Ventilation data. # Segments Source: https://docs.paylead.fr/program/shift/segments Everything you do with audience Segments in Shift: request one from Paylead, assign Consumers to it, check membership, and target an Offer at it. Assigning Consumers to a Segment happens in the **Segments** section and needs **Consumer support**. Targeting an Offer at a Segment happens in the Offers section and needs **Offers**. A [Segment](/glossary#segment) is a group of [Consumers](/glossary#consumer) defined by criteria you established. You use Segments to target your [Offers](/glossary#offer) at a specific audience instead of your whole Consumer base. A single Consumer can belong to several Segments at once. Segments are what you reach for when an Offer should not go to everyone: a welcome Offer for Consumers who joined this quarter, a win-back Offer for dormant accounts, a premium rate reserved for one customer tier. Without a Segment, every published Offer is visible to your whole Consumer base. ## Create a Segment Paylead creates the Segments of your [Program](/glossary#program). Ask for one from the **Support** button in Shift, with the audience you want to define, and the Segment appears in **My account** > **Segments**, one row per Segment. A Segment carries only a name and an identifier. The criteria behind it stay in your systems, so defining an audience shares no personal data with Paylead. That list is where you read the two values you need: | Column | What it is | Where you use it | | -------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------- | | **ID** | The Segment's identifier, the `SEGMENT_ID` of the assignment file. | The second field of every line in the CSV below. | | **Name** | The readable label. | The entry you pick in the **Segments** field when publishing an Offer. | ## Assign Consumers to a Segment You populate a Segment by uploading a CSV file. In **My account** > **Segments**, click **Assign consumers**. Create a text file with one line per Consumer assignment. Each line holds two fields separated by a semicolon, in this order: ```csv theme={null} CONSUMER_ID;SEGMENT_ID ``` For example: ```csv theme={null} consumer-001;standard-users consumer-002;premium-users consumer-001;winter-promo ``` The same Consumer (here `consumer-001`) can appear on several lines to join several Segments. You build the left column from your own customer base, with the same [Consumer](/glossary#consumer) IDs your bank passed to Paylead. The right column is the **ID** column of the Segments list. In the modal, click **Select a file** and choose your CSV file. Shift checks the file in the browser and, if every line passes, uploads it straight away, with no confirmation step. If any line fails the check, nothing is uploaded: the modal lists the offending lines and offers **Close** to abandon the import, or **Start again** to pick another file. The import resynchronizes a Consumer's whole membership rather than adding to it: the lines you upload for a Consumer become their complete list of Segments. To drop one Segment while keeping the others, list the Segments to keep and omit the one to remove. To remove a Consumer from every Segment at once, add a line with the Consumer ID followed by a semicolon and no Segment ID: ```csv theme={null} consumer-001; ``` A removal applies as soon as the file passes the format check, and it cannot be undone. Re-read a removal file before you select it, and keep the assignment file that rebuilt the membership. For real-time programmatic assignment instead of a manual upload, use the public API. See the [Consumer lifecycle](/program/user-journey/guides/manage-consumers) guide. ## Check a Consumer's Segments A Consumer's Segment membership is shown on their profile. In the [Consumers](/program/shift/browse-consumers) section, open a Consumer and read the **Segments** box in the Consumer details: it lists every Segment that Consumer currently belongs to, up to 10 before the list folds. The box is hidden when the Consumer belongs to no Segment, and when Segments are not enabled on your Program. To audit a Segment's full membership, use the assignment file you uploaded or query the API. To confirm a Segment is populated, target it in an Offer and read the audience counter described below. ## Target an Offer at a Segment Segments are applied when you publish an Offer. In the Offer configuration window, the **Segments** field appears when Segments are enabled on your Program, and stays greyed out until Paylead has created your first one. You pick Segments by **Name**, and you can pick several. Next to the field sits a counter of two numbers separated by a slash, tooltipped **Audience**. It refreshes every time you change the selection: * The **left** number is how many Consumers the Offer would reach with the Segments currently selected. * The **right** number is the audience the Campaign reaches with no Segment filter at all. So `0 / 4,571` means your selection matches none of the 4,571 Consumers the Campaign could otherwise reach, and publishing as-is would show the Offer to nobody. It is also the quickest way to confirm a Segment is populated. See [Publish an Offer](/program/shift/publish-offers) for the full Offer configuration flow, including how the Segment field fits into the other Offer settings. ## What's next Create a Consumer-facing Offer from a Campaign and target it at a Segment. Look up the details of the Brands in your catalog. # Status reference Source: https://docs.paylead.fr/program/shift/status-reference Canonical reference for every status Shift surfaces: privacy consent, Pool, Vouchers, Rewards, Gifts, Ventilations, Offers, Campaigns, and bank synchronization, with the technical status behind each label. Every section of Shift surfaces its own status values, from Consumer consent to Cashback payouts. Use this page when a column does not match what you expected, or when reconciling a Shift label with the enum value returned by the API. ## How to read a status in Shift Two status vocabularies exist side by side, and confusing them is the most common source of wrong answers to a Consumer: * The **technical** status is the value the [Paylead API](/program/user-journey/quickstart) returns and your back-office reconciles on (`PENDING_VALIDATION`, `PAID_IN`, `PAID_OUT`, and so on). * The **Consumer-facing** status is the shorter track your bank app shows the Consumer (`Pending`, `Validated`, `Pool`, `Paid`, `Cancelled`). **Every screen in Shift shows the technical status, translated into a display label.** So when the [Rewards report](/program/shift/rewards-report) or a Consumer profile reads `Paid`, that is the accounting state `PAID_OUT`. Two labels differ from the technical value behind them, and both matter in a support call: | Label on screen | Technical status | Read it as | | --------------- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | `Pool` | `PAID_IN` | Paylead has received the funds from the merchant. The [Cashback](/glossary#cashback) is in the Consumer's pool, not yet on their bank account. | | `Paid` | `PAID_OUT` | The payout has left. The money is on the Consumer's bank account. | ## Privacy policy acceptance At enrollment, a [Consumer](/glossary#consumer) accepts the [Program](/glossary#program)'s terms, which authorizes Paylead to match [Offers](/glossary#offer) from their transaction data. On top of that baseline, the Consumer can grant several optional consents. The profile lists the consents the Consumer has granted, each with its acceptance date and an **Opt-out** action to revoke it. A consent absent from the box was never granted, or was revoked. | Consent | Notes | | ------------------------ | ----------------------------------------------------------------------------------------------------------- | | **Basic** | Baseline consent for Offer matching. | | **Statistics** | Usage statistics. | | **Targeting** | Audience targeting. | | **Smart ranking** | Personalized Offer ranking (`SMART_RANKING`). Enables [Offer Smart Ranking](/glossary#offer-smart-ranking). | | **Transaction triggers** | Real-time transaction reactions. | | **Web Analytics** | Web analytics measurement. | Revoking a consent from Shift is one-way: the Consumer grants it again from your own app. Revoking **Smart ranking** shows up directly in Shift, where the Consumer's **Offers** tab stops being ordered by the personalization algorithm. For the other consents, what the Consumer loses depends on how your Program's consents are configured with Paylead. ## Pool The Pool zone of a Consumer profile groups Cashbacks at every stage from creation to disbursement. In Shift, **Pool** names three things: the zone of the profile, the status of a Cashback sitting in that zone, and the Consumer's holding area itself (see [Pool](/glossary#pool) in the glossary). | Status | Technical status | Definition | | -------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Not attribued` | `NOT_ATTRIBUTED` | The [Cashback](/glossary#cashback) was discarded because the same purchase generated several candidates from different Consumer IDs (e.g. one bank feed + one account aggregator). Paylead keeps exactly one Cashback per purchase via the [Reward Attribution](/program/user-journey/guides/reward-lifecycle#reward-attribution) engine; the others are flagged `Not attribued` and never paid out. | | `Pending validation` | `PENDING_VALIDATION` | The Cashback is awaiting the merchant's validation window (typically 30 days). | | `Cancelled` | `CANCELLED` | The Cashback is no longer eligible (refund, dispute, matching issue, or technical cancellation). It will never be paid. | | `Validated` | `VALIDATED` | The merchant has not cancelled the Cashback. It will be invoiced at the end of the cycle. Payout is guaranteed but has not started. | | `Pool` | `PAID_IN` | The Cashback is pooled in the Consumer's wallet, awaiting transfer. This is where a Cashback waits when the Program's payout threshold has not been reached. | | `Paid` | `PAID_OUT` | The Cashback has been credited to the Consumer's bank account. Check the **Transfers** tab of the profile for the matching payout. | The nominal path is `Pending validation` to `Validated` to `Pool` to `Paid`. `Not attribued` and `Cancelled` are final states. ## Vouchers Vouchers cover the gift-card flow: a Consumer orders a voucher, pays for it, and receives it from an external provider. | Status | Definition | | ---------------- | ---------------------------------------------------------------------------------------------------------- | | `Created` | The order exists but has not been paid yet. | | `Confirmed` | The payment went through. The order waits for the external provider to generate the vouchers. | | `Ready` | The provider generated the vouchers and the Consumer received the PDF with its activation code. End state. | | `Payment failed` | The payment attempt failed. | | `Cancelled` | No payment was ever attempted, or the payment stayed stuck at the payment provider for too long. | The nominal path is `Created` to `Confirmed` to `Ready`. An unpaid `Created` order is cancelled automatically after 15 minutes. The [Vouchers report](/program/shift/vouchers-report) prints these statuses as uppercase API enum values, such as `READY` and `CONFIRMED`. Its status filter also carries four values inherited from a previous voucher flow (`Reserved`, `Refunding`, `Refunded`, `Refund rejected`): filter on the values in the table above. ## Rewards A [Reward](/glossary#reward) is either a Cashback or a [Gift](/glossary#gift), and both run on the status values above. **The Pool table is the Reward status table for Shift**: every Reward screen in the back-office prints those labels, from the Consumer profile to the [Rewards report](/program/shift/rewards-report) and the Rewards section. The bank app runs on a separate, shorter **Consumer-facing** track carried by `consumer_status`, which Shift never displays. `PENDING_ATTRIBUTION` (the attribution decision is still running) and `NOT_ATTRIBUTED` have no Consumer-facing equivalent at all, so a Consumer whose app shows nothing while Shift shows `Not attribued` is seeing the expected behavior of the two tracks. For the full definitions of both tracks and how they map, see the canonical [Reward status flow](/program/user-journey/guides/reward-lifecycle#the-reward-status-flow). ## Gifts [Gifts](/glossary#gift) follow the same lifecycle as Cashbacks but are issued directly by the [Program Manager](/glossary#program-manager) (welcome bonus, loyalty incentive, one-off promo) instead of being matched against a transaction. The [Gifts](/program/shift/gifts) list filters on these statuses through tabs that use different wording, so read the two columns together before answering a Consumer. | Status | Technical status | Tab that filters on it | Definition | | -------------------- | -------------------- | ---------------------- | ---------------------------------------------------------------- | | `Cancelled` | `CANCELLED` | none | The Gift was cancelled and is never credited. | | `Pending validation` | `PENDING_VALIDATION` | **Pending** | The Gift is awaiting validation. | | `Validated` | `VALIDATED` | **Validated** | The Gift is validated. Payout is guaranteed but has not started. | | `Pool` | `PAID_IN` | **Paid in** | The Gift is pooled in the Consumer's wallet, awaiting transfer. | | `Paid` | `PAID_OUT` | **Paid out** | The Gift has been credited to the Consumer's bank account. | A Gift stays in `Pending validation` for a few seconds only, so an imported Gift cannot be cancelled or corrected. A cancelled Gift carries its reason as a comment next to the status on the [Gifts](/program/shift/gifts) list. ## Ventilations A [Ventilation](/glossary#ventilation) status describes the payment Paylead executes, not the state of the Rewards inside it: the Rewards on a settled line are all in `Paid` (`PAID_OUT`). You read these lines in the [Ventilations](/program/shift/ventilations) section. | Status | Definition | | ----------- | ------------------------------------------------------------- | | `PENDING` | Paylead has not issued the transfer yet. | | `VALIDATED` | The transfer is validated, ahead of execution. | | `PAID` | Paylead executed the transfer to your Program. | | `ERROR` | The payment order returned an error. The funds did not leave. | ## Offers These statuses cover both [Offers](/program/shift/publish-offers) and [Coupons](/program/shift/coupons): the Coupons list groups its tabs on the same values. | Status | Definition | | ------------- | ------------------------------------------------------------------------------------------- | | `Draft` | The item was saved but never published. It is not visible to Consumers. | | `Waiting` | The item is scheduled for publication and waits for its publication date. | | `Published` | The item has been created but its start date is in the future. Consumers cannot see it yet. | | `Active` | The item is live and visible to Consumers. | | `Deactivated` | The item was manually deactivated by a Program Manager. | | `Ended` | The end date has passed. | | `Completed` | The budget cap has been reached. | `Draft`, `Waiting`, and `Published` all precede visibility: `Active` is the only status a Consumer sees. The **Live** tab of the Offers list groups `Active` and `Published`, so a `Published` row sitting in that tab is not on screen for anyone yet. ## Campaigns | Status | Definition | | ----------- | ---------------------------------------------------------------------------------------------------------------------------- | | `Available` | The [Campaign](/glossary#campaign) has been proposed by Paylead and is awaiting review. Not visible to Consumers. | | `Accepted` | The Program Manager converted the Campaign into an Offer. Visibility depends on the publication date of the resulting Offer. | | `Rejected` | The Program Manager rejected the Campaign. | ## Bank synchronization These statuses describe the state of the Consumer's bank connection. The **Status** column of a Consumer's **Synchronizations** tab shows the label, not the raw value. | Status | Label in Shift | Definition | | -------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------- | | `UNKNOWN` | none | The sync status is unknown, usually because the Consumer has not yet linked an account. | | `DISABLED` | Disabled | The synchronization has been disabled on this connection. | | `ERROR` | Error | A sync error occurred: bad credentials or an action required from the Consumer. | | `CHALLENGE_REQUIRED` | Challenge required | The Consumer must enter a one-time code sent by their bank to acknowledge the sync. | | `SCRAPPING` | Scrapping | The Consumer's bank account is currently being synced (see [Scraping](/glossary#scraper-scraping) in the glossary). | | `SUCCESS` | Ok | The Consumer's bank account sync succeeded. | | `SCA_REQUIRED` | Authentication required | A complete SCA (Strong Customer Authentication) flow must be performed by updating the connection. | | `WEBAUTH_REQUIRED` | Webauth required | A complete authentication flow is required via a redirect. | | `WRONG_PASS` | Wrong pass | The credentials are invalid or obsolete. The Consumer must re-enter them. | | `ACTION_NEEDED` | Action needed | The Consumer must perform a specific action on the bank's website or app (e.g. accept updated terms). | The deprecated `SCRAPPING_ERROR` [Webhook](/glossary#webhooks) fires when a sync error blocks a Consumer's bank connection (see [available events](/program/shift/webhooks#available-events)). ## What's next Read your Program's executive KPIs across Audience, Rewards, Gifts, Coupons, and Vouchers. Measure one Offer's turnover, Rewards, fees, and activity. # Ventilations Source: https://docs.paylead.fr/program/shift/ventilations Download Ventilation files to pay out Cashbacks to your Consumers. **Ventilations** carry the [Cashback](/glossary#cashback) amounts owed to your [Consumers](/glossary#consumer). Paylead computes who is owed what and pays your Program one lump sum per invoicing cycle. You then split that sum across your Consumers and execute the individual bank transfers yourself. The **Ventilation** section appears on Programs configured for external Ventilation, the model described here, on top of the role requirement above. On every other Program, Paylead runs the Consumer payout itself: see [Pool & payout](/program/user-journey/concepts/ventilation) for that model. ## Who pays whom Two distinct movements of money sit behind every row of this screen. ```mermaid theme={null} flowchart LR PL[Paylead] -->|Step 1: one wire transfer per cycle| PM[Your Program] PM -->|Step 2: one transfer per line of the CSV| C1[Consumer] PM --> C2[Consumer] PM --> C3[Consumer] classDef neutral fill:#f1efe8,stroke:#888780,color:#2c2c2a classDef primary fill:#e6f1fb,stroke:#0465ff,color:#042c53 classDef success fill:#eaf3de,stroke:#3b6d11,color:#173404 class PL neutral class PM primary class C1,C2,C3 success ``` 1. **Paylead pays your Program.** One wire transfer per invoicing cycle, for the whole **Total amount to allocate**. The **Date**, **Payout reference**, and **Status** columns describe that transfer. 2. **Your Program pays its Consumers.** One transfer per line of the downloaded CSV, from the sum you just received. You execute those transfers from your own banking tools and record them in your own accounting. The Program commission is settled separately, through the debit note described in [Pool & payout](/program/user-journey/concepts/ventilation#program-commission-settlement). ## Read and pay a Ventilation In **My account** > **Ventilation**, each row is a Ventilation file covering one invoicing cycle. The file lists the Cashback amount to transfer to each Consumer's bank account. Use the **Filter by keyword** field to find a specific Ventilation, or the **Date From** and **Date to** filters to narrow the list. Both date filters apply to the **Date** column: they select cycles by the day Paylead paid you, not by the cycle covered. ### Columns | Column | Description | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Date** | Date Paylead paid your Program. Blank means the payout has not been issued yet. | | **Cycle (YYYY-MM)** | The invoicing cycle during which the Rewards were validated. | | **Invoice reference** | The invoice reference number tied to this Ventilation. | | **Payout reference** | The reference of the wire transfer issued by Paylead. | | **Total amount to allocate** | The total Cashback amount to be distributed across the Consumers in the file. The lines of the CSV add up to it. | | **Status** | The status of the wire transfer Paylead issued to your Program for this cycle, and of that transfer only. See [Status reference](/program/shift/status-reference#ventilations). | **Date** and **Status** are filled in after Paylead's transfer, so they record it rather than authorize it: confirm the receipt on your own bank account. Before issuing that transfer, Paylead checks one thing, that the Ventilation total matches the invoice total. A Reward flips to the technical status `PAID_OUT`, which Shift prints as `Paid`, as soon as the payment provider confirms Paylead's transfer. Under external Ventilation that transfer goes to your Program, so `Paid` means "Paylead has paid the Program Manager", not "the Consumer has received the money". Check your own transfer records before telling a Consumer their Cashback has arrived. Both vocabularies are listed in the [Reward status flow](/program/user-journey/guides/reward-lifecycle#the-reward-status-flow) and in the [Status reference](/program/shift/status-reference). ### Pay out a cycle Read the **Date** and **Status** columns, then confirm the money has landed on your own bank account. Click the download icon on the row. Shift saves the Ventilation as a CSV named after the cycle, for example `2026-07.csv`. Each line is one Cashback owed to one Consumer. Pay each Consumer the **Amount** of their line, on the account identified by **External Account ID**. The lines of a file always add up to the cycle's **Total amount to allocate**. Log the cycle as settled in your own accounting system before moving on. This export describes your own customers. Handle the file as personal data, under your bank's own data protection rules. The same file can be downloaded any number of times and always exports the same lines. Your own accounting is the record of which cycles you have already paid, so keep it up to date: it is what protects a cycle from being paid out twice. ### Fields in the file | Field | Description | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Consumer ID** | The pseudonymized Paylead identifier for the Consumer. Use it to look the Consumer up in Shift. | | **External Account ID** | The Consumer account ID you provided. When a Consumer has several accounts, use this to route the payment to the correct one. | | **Amount** | The Cashback amount to pay to the Consumer. | | **Bankwire Ref** | The reference Paylead generates through the payment provider when it transfers the cycle to your Program. Do not carry it over into your own transfers to Consumers. | | **Execution Date** | The date of the underlying transaction. | To reconcile a Ventilation line by line against your Reward data, filter the [Rewards report](/program/shift/rewards-report) by `Status = Paid` (the technical `PAID_OUT`) over the same cycle dates, then export. The **Reward amount** total of the report should match the cycle's **Total amount to allocate**. ## What's next Retrieve the invoices Paylead issues for Gifts reimbursement and commissions. Generate and manage the API keys that authenticate your integration. # Vouchers report Source: https://docs.paylead.fr/program/shift/vouchers-report Export every voucher-based Reward issued by your Program to reconcile inventory and accounting. The **Vouchers** tab of the Reporting section in [Shift](/glossary#shift) lists every [Voucher](/glossary#voucher) order placed by your [Consumers](/glossary#consumer) and lets you filter, review, and export the list as CSV. Use it to reconcile voucher inventory against your accounting records. This report appears on Programs that run vouchers, through the [Easy Vouchers (EVO)](/glossary#easy-vouchers-evo) option. Elsewhere, the Reporting section opens straight on the [Rewards report](/program/shift/rewards-report). ## What a voucher order is A Voucher is not a [Cashback](/glossary#cashback): the Consumer buys it in the WebApp, for a code or a fixed value redeemable at a [Brand](/glossary#brand), and pays less than the card is worth. That gap is the benefit. Report the two separately: the [Rewards report](/program/shift/rewards-report) covers Cashback, this one covers vouchers. Three amounts describe the same order: | Column | What it is | Who it concerns | | -------------- | ----------------------------------- | ----------------------------- | | **Value** | What the card is worth at the Brand | The Consumer, when redeeming. | | **Price** | What the Consumer actually paid | The Consumer, at purchase. | | **Commission** | Your Program's fee on the order | Your Program. | **Value** minus **Price** is the discount passed to the Consumer, the figure the [Performance dashboard](/program/shift/performance-dashboard) plots as **Total voucher discount**. The debit note bills the discount and the commission together: it carries a single net amount owed by your Program per Brand for the billed period. Reconcile a debit note line against the Brand total over that period rather than voucher by voucher. ## Generate a report Click **Reporting** in the Shift sidebar, then select the **Vouchers** tab. Stack any combination of filters (see below), then click **Apply filters**. The filters are written into the page URL, so the link is shareable, and the results return to page 1. Click **Reset** to drop them all and return to the default selection. The report shows aggregated totals for the filtered set: **Voucher amount** (total face value), **Total vouchers**, **Total consumers**, and **Total commissions**. **Remaining voucher budget** is the exception: it ignores your filters and your date range, and shows the budget available on your Program right now. Click **Export** to download the filtered list as CSV, named `export-reports.csv`. ### Available filters | Filter | What it does | | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Date range | Pick which date the range applies to, **Created** or **Updated**, then set the **Date From** and **Date to** fields. The range always applies: Shift opens on the last 7 days, and the range can start at most 365 days in the past. To cover a longer history, export several ranges and concatenate them. | | **Brand** | Restrict to one merchant Brand. | | **Status** | Restrict to one voucher status. See [Status reference](/program/shift/status-reference#vouchers) for what each value means and which ones to filter on. | | **Offer** | Restrict to one [Offer](/glossary#offer). | | **Campaign** | Restrict to one [Campaign](/glossary#campaign). | | **Only paid vouchers** | Keeps only the orders the Consumer paid for. | Your Program funds **Remaining voucher budget** itself, by transferring money to its dedicated wallet. When it reaches zero, voucher orders are refused and Consumers can no longer buy. Watch that tile. ## Report columns | Column | Meaning | | -------------- | --------------------------------------------------------------------------------------------------------- | | **Created** | Date the voucher was created. | | **Brand** | Merchant Brand tied to the voucher. | | **Campaign** | Source Campaign. | | **Offer ref.** | Reference ID of the published Offer. | | **Value** | Face value of the voucher (redemption amount at the Brand). | | **Price** | Amount charged to the Consumer. | | **Commission** | Fee collected by your Program. | | **Updated** | Date of the latest status change. | | **Status** | Current voucher status. See [Status reference](/program/shift/status-reference#vouchers) for definitions. | The CSV carries more than the nine columns on screen: the server export produces around 24, adding identifiers such as `id`, `type`, `consumer_id`, the Consumer's Segments, and per-status dates. Open the file before mapping it into your tooling. This export describes your own customers. Handle the file as personal data, under your bank's own data protection rules. The CSV reflects the **current** state of each voucher, not a point-in-time snapshot. An order whose status changed since the exported period carries its current value, so re-exporting the same date range next month returns different figures. For audit-grade history, subscribe to [Webhooks](/glossary#webhooks) and persist each event in your own store. For a single Consumer's voucher detail, to run **Force sync**, or to download the voucher PDF, open the **Vouchers** tab of their profile in [Browse Consumers](/program/shift/browse-consumers#working-on-a-single-voucher). ## What's next Pay out Cashbacks to your Consumers. Retrieve invoices issued by Paylead. # Webhooks Source: https://docs.paylead.fr/program/shift/webhooks Set up Webhooks from Shift to receive real-time notifications from Paylead on Program events, verify their authenticity, and audit the delivery history. [Webhooks](/glossary#webhooks) let Paylead push notifications to your back-office the moment something happens on your [Program](/glossary#program): a [Reward](/glossary#reward) is created, a [Consumer](/glossary#consumer)'s bank synchronization fails, an [Offer](/glossary#offer) is about to expire. From [Shift](/glossary#shift), you declare which URL receives each event type, verify that deliveries genuinely come from Paylead, and inspect the dispatch history. Subscribe to an event when your back-office has to act on it: notify a Consumer, release a payout file, open a support ticket. Polling the API answers "what is true now"; a Webhook answers "something just changed" within seconds. For read-only screens and dashboards, query the API when the user opens them. This page covers the Shift screens. For the technical contract your endpoint implements (payload shape, retry policy, idempotency), see the [Webhooks concept](/program/user-journey/concepts/webhooks). Your system also needs an [API key](/program/shift/api-keys) to call back into the Platform. ## Set up a Webhook Each event type is configured independently and points at a single callback URL on your side. In Shift, go to **My account** > **Developers** > **Hooks**. The left side lists every event type Paylead supports. Click the **+** next to the event. Its configuration panel opens on the right. Each event carries one callback URL at a time, so an event you already subscribed to is greyed out. To fan an event out to several internal systems, point it at one endpoint of yours and dispatch from there. In the **Callback URL** field, enter the HTTPS endpoint that will receive the event. The endpoint must accept `POST` with a JSON body and respond `2xx` quickly. Click **Send test**. Paylead immediately posts a payload to the URL with mock data: non-nullable fields carry sample values, nullable fields are left blank. Click **Save**. The Webhook is live and Paylead dispatches real events to it from this moment forward. Nothing is written until you click **Save**: adding an event, editing a URL, and removing a card all stay local until then. To remove a Webhook, click the bin icon in the header of its card, confirm the dialog, then click **Save**. The Webhook keeps receiving events until you do. A subscription covers what happens after you save it. When you add one to a live Program, backfill the gap by querying the API for the objects you missed. ## Authenticate deliveries Anyone who discovers your callback URL can post a fake payload to it. Verify each delivery before you act on it. Credentials are set once for the whole Program. On the Hooks page, click **Settings** in the top right to open the credentials dialog. It offers three independent mechanisms, each enabled by its own checkbox: | Mechanism | Fields | | ------------------------- | ---------------------------------------------------------------------------------------- | | **Basic authentication** | **Username** and **Password**. | | **HMAC authentication** | **Secret**, 32 characters minimum, alphanumeric only. | | **Header authentication** | **Key** (appended to a fixed prefix that Shift displays before the field) and **Value**. | Tick as many as you need, fill in their fields, then click **Confirm**. Clearing a checkbox deletes that credential. The **Settings** button is hidden when your Program signs in through SSO. Paylead signs every request with HMAC-SHA256 over the raw request body, using the secret from the **HMAC authentication** block. The signature travels in the `X-paylead-signature-256` header as a hex digest, and an optional `X-paylead-timestamp` header protects against replay. Paylead can also set up mutual TLS on request: see [Securing your endpoint](/program/user-journey/concepts/webhooks#securing-your-endpoint). Verify against the raw request body, not the parsed JSON. Re-serializing the payload changes the bytes and breaks the signature. ## Available events Paylead groups events the same way Shift does, under Cashbacks, Payments, Consumers, and Offers. Subscribe only to the events your back-office reacts to: every extra subscription is traffic your endpoint has to accept, authenticate, and acknowledge in time. ### Cashbacks | Event key | Description | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `REWARD_CREATED` | A transaction is eligible for a [Cashback](/glossary#cashback). The Reward is visible to the Consumer in your app. | | `REWARD_VALIDATED` | The Reward has not been cancelled by the merchant. It will be invoiced to the merchant at the end of the month. | | `REWARD_PAID_IN` | The Reward amount has left the merchant's wallet for the [Program Manager](/glossary#program-manager)'s. Shift prints this moment as the `Pool` status. | ### Payments | Event key | Description | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | `REWARD_PAID_OUT` | The Consumer pool has been triggered and the Reward transferred to the payment account. Shift prints this moment as the `Paid` status. | | `PAYOUT_SUCCESS` | Two wire transfers have been sent to the Program account: one for the sum of the Rewards, one for the associated fees. | | `PAYOUT_ERROR` | A transfer error occurred, preventing the Reward from being paid to the Consumer account. | | `VENTILATION_FILE_AVAILABLE` | A [Ventilation](/glossary#ventilation) file is available for download. | `PAID_IN` and `PAID_OUT` name a movement of money, and Shift prints the matching Reward statuses as `Pool` and `Paid`. Check the [Status reference](/program/shift/status-reference#pool) before you wire an event to something a support agent will be asked about. ### Consumers | Event key | Description | | ---------------------------- | --------------------------------------------------------------------------------------- | | `SCRAPPING_ERROR` | Deprecated. A bank synchronization failure has blocked the Consumer's transaction feed. | | `CONSUMER_REWARD_POOLED` | The Consumer can be notified that a Reward has been deposited in their pool. | | `CONSUMER_REWARD_PAID` | The Reward has been paid to the Consumer's account. | | `CONSUMER_REWARD_CANCELLED` | The Reward was cancelled before being paid (refund, dispute, or expiry). | | `CONSUMER_REWARD_VALIDATION` | A Reward has been created and is in `Pending validation` status. | `SCRAPPING_ERROR` is deprecated: do not subscribe to it for a new integration. On a Program that still receives it, it tells you a Consumer stopped feeding transactions to Paylead, so they also stopped earning Cashback without necessarily noticing. Only the Consumer can unblock it. Read the Consumer's bank synchronization status in Shift to know what to ask for. `SCA_REQUIRED` and `WEBAUTH_REQUIRED` need the Consumer to redo an authentication flow, `ACTION_NEEDED` sends them to their bank's website, and `WRONG_PASS` means their stored credentials are stale. See the [Status reference](/program/shift/status-reference#bank-synchronization) for the full list. ### Offers | Event key | Description | | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- | | `NEW_OFFER_AVAILABLE` | A new Offer has been published and is available to Consumers. | | `OFFER_ENDING_SOON_DATE` | An Offer is about to expire. The Webhook is sent when the end date is less than 3 days away. | | `OFFER_ENDING_SOON_BUDGET` | The Offer budget is close to depletion. The Webhook is sent once the Campaign has consumed 90% of its [budget](/glossary#budget). | | `OFFER_CASHBACK_RATE_INCREASE` | The Cashback rate of an Offer has been increased. | Use the two `OFFER_ENDING_SOON_*` events to warn Consumers while an Offer is still redeemable. The subscription tooltip in Shift announces the budget event at 80% of the budget, while the threshold applied server side is 90%: reconcile on the event, not on the tooltip. ## Event logs **Event logs** is the landing entry of the **Developers** menu, reached from **My account** > **Developers**. It lists every Webhook delivery attempted on your Program, so it shows exactly what Paylead sent you. Go there when your back-office looks out of sync with the platform, or right after you put a new endpoint live. | Column | Description | | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------ | | **Date** | When the event was dispatched. | | **Consumer** | The Consumer ID the event relates to, when applicable. | | **Type** | The Webhook event type. | | **URL** | The callback URL that received the event. | | **Status** | The HTTP status code returned by your endpoint. Shift marks any code below `300` as a success. | | **Next Try** | When the delivery will be retried. Reads `Max retries reached` once Paylead stops retrying, and `-` when the status code is never retried. | Four filters scope the history: a keyword search, **Filter by type** (one event type), **Filter by status** (a status family, from `1xx` to `5xx`, plus **Others**), and the **Date From** / **Date to** range. Without filters, every event since the Program launched is shown. ### When a delivery fails Paylead drives the retries on its own, and what happens next depends only on the status code your endpoint returned. | What you see in **Next Try** | What it means | What to do | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | | A date | Paylead will try again on its own. Server errors qualify, and so do `408`, `425`, and `429`. | Fix the endpoint before that date and the retry lands. | | `Max retries reached` | The delivery was retryable, and Paylead has stopped trying. | Re-fetch the affected objects from the API to catch up. | | `-` | The code is never retried, which covers most client errors. A `404` or a `403` is a configuration problem on your side, not a transient one. | Fix the URL or the authentication, then use the API to catch up on what you missed. | Each delivery carries a unique `event_id`. Persist it on your side and dedupe on it, since Paylead may redeliver the same event after retries. See [Re-fetch before acting](/program/user-journey/concepts/webhooks#re-fetch-before-acting) for the recommended pattern. A day of downtime on your endpoint is a day of events you will not receive twice. Webhooks are a trigger, not a ledger: keep a path that reconciles your data from the API, and use Event logs to scope how far back to reconcile. ## What's next Payload shape, retry policy, and reliability guidance for your endpoint. Browse and download the current Platform API specification. # Authentication Source: https://docs.paylead.fr/program/user-journey/authentication Authenticate Paylead API calls with a JWT bearer token issued from Shift. One token per environment, carrying the scopes it needs. Every Paylead API call carries two things: 1. A **bearer access token** in the `Authorization` header. 2. The mandatory **`X-Api-Version`** header (see [Versioning](/program/user-journey/versioning)). **Why this matters.** Leaked credentials grant access to your [Program](/glossary#program) data. Treat your API client secret like a password: store it in a secret manager, and never commit it to source control. ## How authentication works Authentication is a two-step model. You hold long-lived **client credentials** and exchange them for short-lived **access tokens**. In Shift, create an API client for your service. Shift returns a `client_id` and a `client_secret` (prefixed `sk_…`). The secret is shown **once**; copy it into your secret manager immediately. Call the token endpoint (`POST /tokens`) and authenticate with **HTTP Basic**: the `client_id` is the username, the `client_secret` is the password. The request carries no body. Paylead returns a short-lived **access token** plus an `expires_in` (about an hour). Send the access token as a bearer credential, together with the `X-Api-Version` header. Refresh the token by calling the token endpoint again before it expires. ## Credentials vs. tokens These are two different things; keep them straight: | | Client secret | Access token | | -------------- | -------------------------------------- | -------------------------------------------------------- | | Looks like | `sk__…` (prefixed) | An **ES256 JWT** (`header.payload.signature`, no prefix) | | Lifetime | Long-lived; rotate on leak | Short-lived (\~1 hour, see `expires_in`) | | Where it lives | Your secret manager, never in code | In memory; fetch on demand and cache until expiry | | Used to | Obtain access tokens at `POST /tokens` | Authenticate each API call | Never send your `client_secret` on a regular API call. It is only ever used against the token endpoint to mint an access token. ## Get your API client credentials Create an API client in Shift (one per environment) under **Settings > API Keys**. Shift returns a `client_id` and a `client_secret`. For the full walkthrough (signing in, creating, viewing, and revoking clients) see [API keys](/program/shift/api-keys) and [Sign in to Shift](/program/shift/sign-in-and-users). The `client_secret` is shown exactly once. Copy it into your secret manager immediately. If you close the dialog without copying it, delete the client and create a new one. ## Exchange credentials for an access token Call `POST /tokens` and authenticate with **HTTP Basic**, not with a JSON payload: | Part of the request | Value | | ---------------------- | ------------------------------------------------------------ | | `Authorization` header | `Basic base64(client_id:client_secret)` | | `X-Api-Version` header | Required, see [Versioning](/program/user-journey/versioning) | | Request body | None | The credentials travel in the `Authorization` header, never in the payload. The response carries the access token and its lifetime (`expires_in`, in seconds). **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. Cache the access token until shortly before `expires_in` elapses, then request a new one. Do not call the token endpoint on every API request. ## Call the API Pass the access token as a bearer credential and set the mandatory `X-Api-Version` header. All calls must use HTTPS. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. A call without a valid token returns `401 Unauthorized`. A call missing the `X-Api-Version` header is rejected; see [Versioning](/program/user-journey/versioning). See [Errors](/program/user-journey/errors) for the full list. ## Sandbox vs. production credentials Sandbox and production credentials are separate. A sandbox client cannot mint tokens that work against production, and the reverse. | Property | Sandbox | Production | | ------------- | ------------------------------------------- | --------------------------------- | | Secret prefix | `sk_…` (sandbox) | `sk_…` (production) | | Base URL | | | | Access | Granted on signup | Granted after sandbox validation | | Data | Test entities created by the client, no PII | Real Consumers, real transactions | Use distinct secret-manager entries for each environment. Mixing them risks pointing your staging environment at production data. ## Rotate credentials Access tokens expire on their own (about an hour), so there is nothing to rotate there. What you protect and rotate is the **client secret**. In Shift, create a new API client for the same environment. It returns a fresh `client_id` and `client_secret`. Update the secret in your secret manager. Redeploy or hot-reload the services that read it, so they exchange the new secret at the token endpoint. Watch your logs or Shift's API activity panel. Confirm requests are succeeding with tokens minted from the new secret. Delete the old client in Shift. It can no longer mint tokens, and tokens already issued from it expire within the hour. Keep both clients active during rotation. Revoke the old one only after the new one is verified in production traffic. This avoids downtime if the rollout fails. ## Security checklist * Store the `client_secret` in a secret manager (Vault, AWS Secrets Manager, GCP Secret Manager). Never in code, never in environment files committed to Git. * Restrict who can create API clients in Shift. Audit the Program Manager role. * Use a separate API client per service. If one service is compromised, you revoke one client, not all. * Never log the `client_secret` or the access token. * Log token usage on your side (request ID, timestamp). Correlate with Shift's audit log if you suspect misuse. If a `client_secret` leaks, delete that client in Shift immediately. Tokens it already issued expire within the hour. Then audit the previous 30 days of API activity for unexpected calls. ## What's next The mandatory `X-Api-Version` header and the version policy. Per-token request limits and backoff strategy. Diagnose `401`, `403`, and other auth-related failures. Switch from sandbox to production safely. # Share transactions Source: https://docs.paylead.fr/program/user-journey/concepts/transaction-lifecycle How the bank shares Consumer transactions with Paylead: the platform-level feed every service builds on. Sharing the [Consumer](/glossary#consumer)'s bank transactions is a **platform-level** task, independent of any service: the bank pushes transactions once, and whichever service the Consumer joined consumes them. This page covers **how to share transactions** and how Paylead processes them. What a service then does with them (matching [Offers](/glossary#offer), creating [Rewards](/glossary#reward)) is downstream and summarized at the end. ## End-to-end flow Sharing happens in three moments across the Consumer's life with the service. **Your part is the sharing** (the API calls); everything from matching onward is downstream service behavior, summarized under [What Paylead does next](#what-paylead-does-next). The [Program Manager](/glossary#program-manager) (the bank itself, or an aggregator acting on its behalf) is the single entity exchanging data with Paylead. ### Enrollment and historical sharing When the Consumer joins a Paylead service, the Program creates the Consumer, then pushes the past 12 months of settled transactions in one shot to seed eligibility and [Offer Smart Ranking](/glossary#offer-smart-ranking). ```mermaid theme={null} %%{init: {'themeVariables': {'actorBorder':'#0465ff','signalColor':'#378add'}}}%% sequenceDiagram autonumber participant C as Consumer participant PM as Program participant P as Paylead C->>PM: Joins a Paylead service PM->>P: POST /consumers (create Consumer) PM->>P: POST /consumers/{id}/transactions/history P->>P: Seed eligibility and Smart Ranking ``` ### Real-time authorization (optional) At each authorized payment, the Program may send the transaction individually with `state: authorization`. This flow is **optional**: it lets Paylead emit `REWARD_CREATED` within a second of the purchase, which powers live animations. ```mermaid theme={null} %%{init: {'themeVariables': {'actorBorder':'#0465ff','signalColor':'#378add'}}}%% sequenceDiagram autonumber participant C as Consumer participant PM as Program participant P as Paylead C->>PM: Pays with linked card PM->>P: POST /consumers/{id}/transactions (state: authorization) P-->>PM: REWARD_CREATED Webhook (within 1s) ``` ### Settlement (mandatory) Once the transaction is cleared on the bank account, the Program sends it with `state: cleared`. This flow is **mandatory whether or not the authorization was shared**: the `cleared` record is what Paylead matches and turns into a confirmed Reward. ```mermaid theme={null} %%{init: {'themeVariables': {'actorBorder':'#0465ff','signalColor':'#378add'}}}%% sequenceDiagram autonumber participant PM as Program participant P as Paylead PM->>P: POST or PUT, same id (state: cleared) P->>P: Re-run matching, confirm Reward ``` These diagrams cover **card** transactions. Direct debit and bank transfer payments are also in scope: Paylead needs them to operate its services. ## How sharing works The [Program Manager](/glossary#program-manager) (the bank, or an aggregator acting on its behalf) shares transactions with Paylead through **three distinct flows**, each with its own purpose: 1. **Historical sharing**: a one-shot `POST` of the [Consumer](/glossary#consumer)'s past **12 months** of settled / compensation transactions. Triggered in two cases: * At enrollment in the [Perks](/glossary#perks) service, to determine eligibility and seed [Offer Smart Ranking](/glossary#offer-smart-ranking) from real purchase habits. * In the [Loyalty](/glossary#loyalty) domain, if the Consumer consents to sort partner loyalty programs by their purchase habits. Send this call even when the Consumer has no history. With no past transactions, the payload carries an empty `banks` array (`{ "banks": [] }`). 2. **Real-time sharing** (optional, recommended): transactions sent **individually in real time** as the bank authorizes the payment. Paylead can then emit `REWARD_CREATED` **within a second** of an eligible purchase, which is the foundation of live "your Cashback is on its way" [animations](/program/user-journey/guides/animate-your-program). 3. **Daily sharing** (mandatory): the **daily batch** of newly settled transactions (cleared card transactions, direct debits, and bank transfers), transferred to Paylead every day. The real-time and daily flows hit `POST /consumers/{consumer_id}/transactions`. Historical sharing uses its own endpoint, `POST /consumers/{consumer_id}/transactions/history`. **Push vs Pull.** By default, the Program pushes through the Transaction Hub. The [Transaction Fetch Hub](/glossary#transaction-fetch-hub) is the alternative where Paylead pulls: a bespoke, per-bank service scoped during the build phase of the integration. The three flows above apply in either mechanism. Each source pushes into a dedicated **transaction bucket**: a pool of bank connections grouping the accounts each Consumer has linked. Processing a bucket happens in three sub-steps: 1. **Bank connections** are resolved: the bank ID, user ID, and sync status. 2. **Bank accounts** linked to each connection are checked. 3. **Transactions** are persisted, then forwarded to the Transaction Worker queue. ## What Paylead does next Matching, Rewards, and attribution are **downstream of sharing** and service-specific: you do not implement them. They are summarized here for context; the detail lives in the [Perks](/glossary#perks) guides. Once transactions are ingested, the Perks service consumes them: * **Matching**: the Transaction Worker checks each transaction against the Consumer's active [Offers](/glossary#offer): the [Brand](/glossary#brand) is in the Offer's eligible Brands or [Stores](/glossary#stores), the date is inside the validity period, the Consumer is in any required [Segment](/glossary#segment), and the budget cap is not reached. No match → the transaction is kept for analytics, with no [Reward](/glossary#reward). * **Attribution**: when the same transaction arrives from several sources (for example, the bank and an account aggregator), the [Reward attribution](/program/user-journey/guides/reward-lifecycle#reward-attribution) engine issues a single Reward and drops the duplicates. * **Notification**: Paylead emits `REWARD_CREATED` ([Webhook](/program/user-journey/concepts/webhooks); `PENDING_VALIDATION` / `VALIDATION`), then `REWARD_VALIDATED` after the refund window. From there, [Ventilation](/program/user-journey/concepts/ventilation) takes over. ## Transaction payload The real-time and daily flows use `POST /consumers/{consumer_id}/transactions`, while historical sharing uses `POST /consumers/{consumer_id}/transactions/history`. Two payload conventions matter for the rest of this page: * **Sign.** Debits are **negative**, credits are **positive**. A €10.40 purchase is `amount: -10.40`; a refund landing back on the card is a positive amount on a new transaction. * **Unit.** Amounts are **floats in EUR** (for example `-10.40`), not cents. ### `state` maps to the flow The `state` field on each transaction tells Paylead where it sits in its life and which of the three flows it belongs to: | `state` | Used in | | --------------- | ------------------------------------------------------------------------------------ | | `authorization` | Authorization requests (real-time, optional flow) | | `cleared` | Historical sharing and daily transactions accounted for on the client's bank account | ### Required fields Every transaction must carry: | Field | Type | Notes | | ------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | string | Bank-defined ID linking the `authorization` to its `cleared` record. | | `type` | enum | One of 12 values (`bank`, `card`, `check`, `deferred_card`, `deposit`, `loan_payment`, `order`, `payback`, `summary_card`, `transfer`, `unknown`, `withdrawal`). Only `card`, `deferred_card`, `order`, and `payback` are eligible for Paylead services. | | `executed_at` | ISO 8601 | Authorization timestamp, including timezone. | | `amount` | float | Signed; debit `< 0`, credit `> 0`. | | `currency` | ISO 4217 | Any ISO 4217 code (typically `EUR`). | | `raw_label` | string | Free-text transaction label. | ### Recommended optional fields None of these are required, but matching quality improves significantly with each one you add: | Field | Type | Notes | | ---------------------------- | ---------- | -------------------------------------------------------------------------------- | | `state` | enum | `authorization` or `cleared`. | | `channel` | enum | `store` or `online`. | | `scheme` | string | Card scheme, free text (`Visa`, `MasterCard`, `CB`, and others). | | `scheme_id` | string | Scheme identifier assigned to the transaction by the card network, alphanumeric. | | `truncated_pan` | string | Last 4 digits of the physical card (4 characters). | | `truncated_dpan` | string | Last 4 digits of the device token for X-Pay payments (4 characters). | | `authorization_id_response` | string | Issuer authorization reference, alphanumeric, 6 chars max. | | `retrieval_reference_number` | string | Acquirer-generated unique reference, alphanumeric, 12 chars max. | | `acquirer_reference_number` | string | Acquirer-assigned unique reference, alphanumeric, 23 chars max. | | `is_realtime` | boolean | `true` for authorization requests only; defaults to `false`. | | `deleted` | ISO 8601 | Timestamp marking a previously created transaction as deleted. | | `brand.name` | string | Merchant brand name. | | `brand.mcc` | string | Merchant Category Code (ISO 18245, 4 digits). | | `store.name` | string | Merchant name as registered. | | `store.merchant_id` | string | Acquirer merchant ID (card acceptor ID), alphanumeric. | | `store.terminal_id` | string | Payment terminal ID, alphanumeric, 8 chars max. | | `store.public_reference` | string | Public business ID (SIRET, BCE, and others). | | `store.country` | ISO 3166-1 | Store country, alpha-2. | | `store.city` | string | Store city. | | `store.post_code` | string | Store postal code. | | `store.address` | string | Store street address. | The full schema is in the [API reference](/program/api/thub/bulk-transaction/create-a-bulk-of-transactions). **Send as many optional fields as you can.** The richer the data you share, the more Paylead can do with it: a larger Offer catalog surfaced to your Consumers, higher Cashback rates made available, and fewer support requests reaching the Program. Some Offers and services are conditioned on sharing specific optional fields. ### Network field mapping For teams building against acquiring or interbank feeds, these fields map to standard network references: | Field | ISO 8583 | ISO 20022 | CBAE | | ---------------------------- | -------------------------------------------------------- | --------------------------------------- | ----------------------------------------------------- | | `store.merchant_id` | Field 42 (Card Acceptor Identification Code) | `MerchantIdentification/Id` | Field 159, subfield 0202 (`Acceptor_contract_number`) | | `store.terminal_id` | Field 41 | | | | `scheme` | Derived from the BIN in field 2 (Primary Account Number) | `CardSchemeName` | | | `authorization_id_response` | Field 38 | `AuthorisationResult/AuthorisationCode` | | | `retrieval_reference_number` | Field 37 | | | ## Transaction updates and deletions Card authorizations are not final. A €100 fuel pre-authorization may settle at €25. You update or cancel a transaction by re-sending it with the same `id`. Two methods are equivalent and both handle every operation below: * `POST /consumers/{consumer_id}/transactions` (bulk), carrying the transaction with its original `id`. * `PUT /consumers/{consumer_id}/transactions/{transaction_id}`. | Operation | How | Notes | | ----------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------- | | Update an amount | Re-send with the new `amount` | Re-runs matching against the new amount. | | Settle an authorization | Re-send with `state: cleared` | Moves an `authorization` to its settled record. | | Cancel (soft) | Re-send with `amount: 0` | Equivalent to a deletion for matching purposes. | | Cancel (mark deleted) | Re-send with `deleted` set to the deletion timestamp | Flags the transaction as deleted while keeping its record; cancels any Reward in flight. | A dedicated `DELETE /consumers/{consumer_id}/transactions/{transaction_id}` is also available and cancels any Reward already in flight. Refunds use a different signal: the bank shares a positive-amount card transaction referencing the same Brand. Paylead reconciles the refund against the original debit and adjusts or cancels the Reward. ## Retention Transactions are not kept indefinitely. A transaction that never produced a Reward is deleted 2 years after its transaction date. Transactions that did produce a Reward are kept beyond that, because they carry accounting value. This clock runs on its own, independent of the API operations above. Deleting a transaction through the API removes it immediately; the 2-year rule removes what you never deleted. Off-boarding a Consumer overrides this clock. Their transactions are deleted immediately, whatever their age, except those that produced a Reward. See [Data retention after off-boarding](/program/user-journey/guides/manage-consumers#data-retention-after-off-boarding). ## Timing **Latency depends on the flow.** With **authorization-time sharing** enabled, Paylead emits `REWARD_CREATED` within a second of an eligible purchase made with a payment card. Programs running only the **daily compensation** flow see the Reward appear once the day's batch is processed. Contact your Paylead account manager for the timing applicable to your Program before exposing the flow to Consumers. **Sandbox is not production.** Sandbox transactions process in seconds, but real Programs run against batched aggregator feeds and end-to-end latency is materially longer. Always deploy a beta in production before going live to verify your transaction-sharing pipeline. **Currency.** All amounts handled by Paylead (transactions, Rewards, ventilation files) are denominated in **EUR**. Multi-currency Programs are not supported. **The Consumer ID is the linchpin.** Every transaction is scoped to a `consumer_id`. A mismatched or missing Consumer ID means the transaction is orphaned: no bucket, no match, no Reward. Validate Consumer creation before turning on transaction sharing. ## Data quality matters The Brand identifier (often called `merchant_id`) and the `executed_at` timestamp drive matching accuracy. Garbage in, garbage out: * A wrong `merchant_id` produces no match even when the Consumer shopped at an eligible Brand. * A wrong `executed_at` may push the transaction outside the Offer's validity period. Transactions older than 12 months are accepted (used to enrich Smart Ranking and analytics) but never generate Rewards. Only fresh transactions trigger matching. ## What's next Understand how Paylead picks one Program when several sources report the same transaction. Follow the validated Reward through to the Consumer's bank account. # Pool & payout Source: https://docs.paylead.fr/program/user-journey/concepts/ventilation How Paylead fills the Consumer pool, triggers the payout against the Program Manager's thresholds, and settles the Program's commission. [Ventilation](/glossary#ventilation) is how the value of each matched [Offer](/glossary#offer) is distributed: the [Consumer](/glossary#consumer)'s [Cashback](/glossary#cashback) into their [pool](/glossary#pool) (the cagnotte), and the [Program Manager](/glossary#program-manager)'s commission back to the Program. Paylead manages the pool, runs the Consumer payout, and settles the Program Manager's commission. The Cashback is owed by the Program Manager to its Consumers; Paylead distributes it on the Program Manager's behalf. ## Set up a Consumer for payout Before Paylead can pay a Consumer, two pieces of information must be registered for that Consumer. Identity data Paylead forwards to its payment provider to register the Consumer's payout account. Only `first_name`, `last_name`, `email`, and `address` are required. Register it with [Create or update a consumer's KYC](/program/api/perks/kyc/create-or-update-a-consumers-kyc-mangopay-natural-user). The bank account where the Consumer wants to be paid out, set through `target_account`. Designate it with [Designate the bank account where a consumer wants to be paid out](/program/api/perks/upm/designate-the-bank-account-where-a-consumer-wants-to-be-paid-out). You can also [read](/program/api/perks/upm/read-the-payment-account-currently-designated-for-a-consumer) or [revoke](/program/api/perks/upm/revoke-the-consumers-currently-designated-payment-account) it. KYC is **personal data**. Handle it under GDPR and send only what the payout requires. ## How Ventilation works Every pooled [Reward](/glossary#reward) feeds the Consumer's cagnotte. Paylead sums the Reward amounts and triggers the payout against two thresholds, both set by the Program Manager. ```mermaid theme={null} flowchart TD R[Pooled Rewards] --> POOL[Consumer cagnotte] POOL --> S{Sum of Reward amounts} S -->|Reaches the manual threshold| MAN[Consumer can trigger the payout] S -->|Reaches the auto threshold| AUTO[Paylead triggers the payout automatically] MAN --> PAY[Cashback paid to the Consumer] AUTO --> PAY classDef neutral fill:#f1efe8,stroke:#888780,color:#2c2c2a classDef decision fill:#ffffff,stroke:#888780,color:#2c2c2a classDef primary fill:#e6f1fb,stroke:#0465ff,color:#042c53 classDef success fill:#eaf3de,stroke:#3b6d11,color:#173404 class R,MAN,AUTO neutral class POOL primary class S decision class PAY success ``` ## When a Reward enters the pool A Reward feeds the cagnotte once it reaches the Consumer-facing `POOLED` status. **When** that happens depends on a Program-level model the Program Manager chooses. | Model | A Reward is pooled when | How it is funded | | ------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | **Best experience** | It is technically `VALIDATED`. | Paylead advances the funds from a working capital line, so the Cashback is available to the Consumer immediately after the validation delay. | | **On receipt** | The funds are available, technical status `PAID_IN`. | No advance: Paylead transfers the funds per the contractual payment term, 3 months after the last day of the month in which the Reward was validated. | Every `VALIDATED` Reward is guaranteed to be paid by Paylead. The **Best experience** model relies on that guarantee to front the Cashback to the Consumer at validation, instead of waiting for `PAID_IN`. For the full list of both status tracks and what each value means, see the canonical [Reward status flow](/program/user-journey/guides/reward-lifecycle#the-reward-status-flow). ## Triggering the payout The Program Manager defines two thresholds on the pooled amount: * **Manual threshold**: once the sum of pooled Reward amounts reaches it, the Consumer can [trigger the payout](/program/api/perks/upm/trigger-a-payout-of-the-consumers-pool) from the app. * **Auto threshold**: once the sum reaches it, Paylead pays out the cagnotte automatically. Letting the pool grow before payout keeps transfers meaningful, reduces transfer overhead, and turns the visible cagnotte into a marketing lever. The manual threshold lets motivated Consumers cash out sooner; the auto threshold guarantees nobody is left waiting indefinitely. ## Program commission settlement The Program Manager's commission (its share of the Offer value) is settled separately from the Consumer payout, through a **debit note**. | Moment | Event | | ------------- | ---------------------------------------------------------------------------------------------- | | Month M | Rewards reach `VALIDATED`. | | 01 / M+2 | Paylead issues the debit note for those commissions, by email and on [Shift](/glossary#shift). | | 01 / M+2 | The Program Manager issues an invoice from the debit note. | | 60 days later | Paylead settles the invoice. | Under European regulation, Paylead pays an invoice **60 days after it is issued**. Example: Rewards validated in March produce a debit note on 1 May; if the Program Manager invoices the same day, Paylead settles around 30 June. ## Check a Consumer's pool A Program Manager can read a Consumer's aggregated pool status (pooled amount and Reward counts) with [Get a consumer's aggregated reward information](/program/api/thub/rewards/get-a-consumers-aggregated-reward-information). The path is `/consumers/{consumer_id}/rewards/info`. It belongs to the Consumers component, so it sits outside the `/perks` prefix carried by the adjacent per-Consumer endpoints (`/perks/consumers/{consumer_id}/rewards`, `/voucher-orders`, `/accounts/payment`, `/pools/me/payouts`). The response carries one field per backend that actually answered. A backend that fails, times out, or has no data for the Consumer is omitted from the payload, so an absent field means "no data", not zero. Read the amounts under their backend key (`perks`), never at the root of the response: `validation`, `pooled`, `paid`, and `voucher` each carry an `amount` and a `count`. `perks.can_trigger_pooled` tells you whether the Consumer can request a payout right now, which is the check to run before offering the action. ## Reconciliation and reporting On a standard Program, the Program Manager does not pull a distribution file: Paylead runs the Consumer-level payout. For accounting and reconciliation, use the [Reporting](/program/user-journey/guides/reporting) exports via the [Paylead API](/program/user-journey/quickstart). Programs set up for **external Ventilation** work the other way round: Paylead computes who is owed what, and the Program pays its own Consumers from a distribution file it downloads in Shift. See [Ventilations](/program/shift/ventilations) for that flow. ## Edge cases Paylead stops the payout: the account link is no longer authoritative. What happens to each Reward depends on its status at that moment, see [Rewards in flight at off-boarding](/program/user-journey/guides/manage-consumers#rewards-in-flight-at-off-boarding). Paylead reconciles the refund against the original transaction and cancels the Reward during the refund window, before it reaches `VALIDATED`. Refunds that land after validation are handled according to the Program's terms and conditions. A Consumer's pool aggregates every pooled Reward. Paylead pays out the accumulated balance. All amounts are denominated in **EUR**. Paylead does not support multi-currency Programs. ## What's next The loyalty wallet Consumers build alongside their Rewards. Get notified when a payout succeeds or fails. # The WebApp Source: https://docs.paylead.fr/program/user-journey/concepts/web-app How Paylead delegates part of the Consumer journey, across both Perks and Loyalty, to an embedded webview inside the bank app. The **WebApp** is a Paylead-hosted application reached via a webview inside the Program Manager's mobile app. It lets a Program delegate part of the Consumer-facing journey to Paylead instead of building every screen natively. This page explains *what* the WebApp is and *what it delegates*. For *how to integrate it* (opening the webview, the functions it exposes) see the [WebApp (MFP)](/program/webapp/overview) tab. ## Two ways to build the Consumer experience A Program has two ways to surface Paylead value to [Consumers](/glossary#consumer): * **Build natively:** the bank's app calls the [Paylead API](/program/user-journey/quickstart) and renders Offers, Rewards, and the loyalty card wallet itself. Maximum control over the UI. * **Embed the WebApp:** the bank opens Paylead's webview at the right place in its app. Paylead renders the experience; the bank app only provides the native WebView that hosts it. Most Programs mix both: native entry points, with the WebApp handling the richer flows. ## What the WebApp handles When a Program embeds the WebApp, Paylead renders these flows so the bank does not build them natively. **[Perks](/glossary#perks) flows:** * **Offer catalog:** browsing the [Offers](/glossary#offer) surfaced to the Consumer. * **Offer detail:** the full terms of a single Offer (eligible [Brand](/glossary#brand), [Reward](/glossary#reward) terms, validity period, and channel). * **Pool (cagnotte) management:** tracking the Consumer's [Cashback](/glossary#cashback) [pool](/glossary#pool) (balance, pending and validated Rewards, and payout history). * **Reward listing:** the full list of Rewards the Consumer has generated through Perks Offers. * **Voucher purchase and list:** buying [Vouchers](/glossary#voucher) and viewing the ones the Consumer already owns. * **Post-onboarding consent management:** letting the Consumer review and adjust their Perks consent after enrollment. **[Loyalty](/program/user-journey/loyalty-journey) flows:** * **Loyalty account creation and connection.** * **Merchant loyalty space:** the branded loyalty area for each partner. * **Loyalty card wallet:** storing and managing the Consumer's loyalty cards (can also be built natively). The WebApp is **mandatory** for the loyalty account creation and connection flows. A Program cannot build these natively; they must run inside the WebApp. This shortens the bank's build: instead of implementing each screen against the API, the bank embeds a maintained, consistent experience. ## Customization The WebApp is **customized to blend into each bank's UX**: it is not a generic, off-brand surface. The bank can also adjust the UI to fit its own marketing needs, so the embedded experience stays consistent with the rest of the app. ## Early access to new features Embedding the WebApp also means **getting Paylead's new features first**: improvements ship inside the WebApp ahead of the API surface, so Programs on the WebApp benefit from them in preview without extra build work. ## What stays native (the Program's responsibilities) Even with the WebApp, the Program still owns these natively: * **Consumer enrollment** into the [Program](/glossary#program). * **Animation:** engagement and notifications (see [Animate your program](/program/user-journey/guides/animate-your-program)). * **Transaction sharing:** pushing or having Paylead pull transactions (see [transaction lifecycle](/program/user-journey/concepts/transaction-lifecycle)). * **Ventilation set-up:** configuring how [Cashback](/glossary#cashback) is paid out (see [Ventilation](/program/user-journey/concepts/ventilation)). We recommend the bank surfaces, natively, the Consumer's profile statistics and/or partner Brand logos, which reinforce the value of the Program right inside the bank's own UI and guide the Consumer toward the Perks and Loyalty services. ## How it fits the journey The WebApp is a delivery surface, not a separate product. Behind it, the same mechanics apply: transactions flow in (see [transaction lifecycle](/program/user-journey/concepts/transaction-lifecycle)), Rewards are attributed, and payouts run through [Ventilation](/program/user-journey/concepts/ventilation). The WebApp simply renders these to the Consumer. ## What's next The technical guide to embedding and opening the WebApp in your bank app. The loyalty wallet the WebApp can surface to Consumers. # Webhooks Source: https://docs.paylead.fr/program/user-journey/concepts/webhooks How Paylead pushes real-time events to your back-office and how to make your endpoint reliable. [Webhooks](/glossary#webhooks) are outbound HTTP notifications Paylead sends when something happens in the platform: a [Reward](/glossary#reward) is created, validated, or paid out. They let the [Program Manager](/glossary#program-manager) react in real time without polling the API. Two principles to remember: 1. The Webhook is a **trigger**, not a source of truth. Always re-fetch the underlying object via the API before acting on it. 2. **Ordering is not guaranteed.** Events for the same object may arrive out of order. Trust the status returned by the API, not the sequence of events. ## Payload structure Every Webhook is a `POST` request with a JSON body containing four fields. ```json theme={null} { "event_type": "REWARD_CREATED", "resource_id": "550e8400-e29b-41d4-a716-446655440000", "consumer_id": "ext-user-123", "user_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8" } ``` | Field | Type | Description | | ------------- | --------------------- | ----------------------------------------------------------------------------------------------------------- | | `event_type` | string | The event identifier. | | `resource_id` | string (UUID) | The ID of the primary object the event relates to. | | `consumer_id` | string or null | The external [Consumer](/glossary#consumer) ID. Null for payout, [Offer](/glossary#offer), and file events. | | `user_id` | string (UUID) or null | The internal Paylead user ID. Null for payout, Offer, and file events. | ## Event catalog Paylead emits two parallel event families for Rewards: **consumer-facing events** and **technical events**. They are independent, each tracking a different perspective on the same lifecycle. Use consumer-facing events to drive Consumer animation: push notifications, in-app Reward status updates, and any display visible to the Consumer. Technical events are for back-office processing (accounting, payout pipelines). Track what the [Consumer](/glossary#consumer) experiences in the bank app. These events fire when the Consumer's view of a Reward changes, independently of Paylead's internal processing. | Event | Description | `resource_id` | | ---------------------------- | --------------------------------------------------------------------------------- | ------------- | | `CONSUMER_REWARD_VALIDATION` | The Reward has entered validation; show a pending status to the Consumer. | Reward ID | | `CONSUMER_REWARD_POOLED` | The Reward has landed in the Consumer's pool; the Consumer can see it in the app. | Reward ID | | `CONSUMER_REWARD_PAID` | The Reward has been paid to the Consumer's account. | Reward ID | | `CONSUMER_REWARD_CANCELLED` | The Reward was cancelled (refund, dispute, or expiry). | Reward ID | Sent on every change to the internal processing status of a [Cashback](/glossary#cashback) or [Gift](/glossary#gift). Use these for back-office operations. | Event | Description | `resource_id` | | ------------------ | ------------------------------------------------------------- | ------------- | | `REWARD_CREATED` | A new Reward is created in `PENDING_VALIDATION`. | Reward ID | | `REWARD_VALIDATED` | The Reward is `VALIDATED`; Paylead now guarantees the payout. | Reward ID | | `REWARD_PAID_IN` | Paylead has received the funds from the merchant. | Reward ID | | `REWARD_PAID_OUT` | The Reward has been paid out to the Program. | Reward ID | Sent when an [Offer](/glossary#offer) changes or approaches its limits. `consumer_id` and `user_id` are null for these events. | Event | Description | `resource_id` | | ------------------------------ | ----------------------------------------------------------------------- | ------------- | | `NEW_OFFER_AVAILABLE` | A new Offer has been published and is available to Consumers. | None | | `OFFER_ENDING_SOON_DATE` | The Offer expires in less than 3 days. | Offer ID | | `OFFER_ENDING_SOON_BUDGET` | The Offer budget has exceeded 90% consumption. | Offer ID | | `OFFER_CASHBACK_RATE_INCREASE` | The [Cashback](/glossary#cashback) rate has been increased (new phase). | Offer ID | Sent when Paylead executes a payout batch for the Program. `consumer_id` and `user_id` are null for these events. | Event | Description | `resource_id` | | ---------------- | -------------------------------------------------------------------------------------------- | ------------- | | `PAYOUT_SUCCESS` | The payout batch completed successfully. Funds have been transferred to the Program account. | Payout ID | | `PAYOUT_ERROR` | The payout batch failed. No transfer was made. | Payout ID | | Event | Description | `resource_id` | | ---------------------------- | -------------------------------------------------------------------------------------------------------- | ------------- | | `VENTILATION_FILE_AVAILABLE` | A [Ventilation](/glossary#ventilation) file is ready for download. `consumer_id` and `user_id` are null. | File ID | Do not subscribe to these events for new integrations. * **`SCRAPPING_ERROR`**: the bank synchronization failure event is deprecated. ## Setting up your endpoint Each event type is configured independently in [Shift](/glossary#shift): you assign one HTTPS endpoint per event. The same endpoint URL can receive multiple event types. Acknowledge with `200` before doing any heavy work. Push the event into your own queue and process asynchronously. Slow endpoints get retried and pile up in Paylead's queue. ## Securing your endpoint Paylead offers three mechanisms to authenticate incoming Webhooks. They are all optional and can be combined on the same Program. Configure them per endpoint in [Shift](/glossary#shift). ### HMAC SHA-256 Paylead signs the raw request body with a shared secret (minimum 32 characters) using HMAC-SHA256. The signature travels in a dedicated header. * **Signature header:** `X-paylead-signature-256`, a hex digest (not base64). * **Timestamp header (optional):** `X-paylead-timestamp`, included in the signed string to protect against replay attacks. * **Verification:** recompute the HMAC with the same secret over the raw body and compare it against the header. Sign and verify against the **raw** request body, not the parsed JSON. Re-serializing the body changes the bytes and breaks the signature. ### Basic Auth Paylead adds a standard `Authorization: Basic ` header to every request. Use this when your endpoint already handles HTTP Basic authentication. ### Custom header Paylead injects an arbitrary header with a static name and value defined at configuration time. Use this to pass a proprietary token your system expects, for example `X-Api-Key: `. On request, Paylead can also set up a mutual TLS (**mTLS**) flow for the Webhook calls it makes to your endpoint. ## Reliability A robust Webhook integration handles delivery failures and ordering surprises. ### Retry policy Paylead retries any delivery that returns a non-`2xx` response or times out. The current policy is **5 attempts maximum** with an **exponential backoff of `2^n` minutes** between attempts, where `n` is the attempt number. | Attempt | Delay since previous | Time since first attempt | | ----------- | -------------------- | ------------------------ | | 1 (initial) | n/a | T+0 | | 2 | 2 min | T+2 min | | 3 | 4 min | T+6 min | | 4 | 8 min | T+14 min | | 5 | 16 min | T+30 min | | 6 | 32 min | T+62 min | After the final attempt fails, the event is marked as failed. Paylead drives the retries on its own, so recover a missed event by re-fetching the object from the API. This retry schedule is the current default and may evolve. Build your handler so it tolerates a stricter or looser cadence: what matters is that you ack quickly and re-fetch the object via the API. ### Ordering **Ordering is not guaranteed.** Paylead does not promise that `REWARD_VALIDATED` arrives after `REWARD_CREATED` at your endpoint. Building business logic that assumes "REWARD\_CREATED always comes first" will eventually break. ### Re-fetch before acting Webhooks reflect state at the moment of dispatch. Between dispatch and your handler running, the underlying object may have moved on. Always issue an API call to read the current state before triggering money movement or notifications. **Test in sandbox first.** The sandbox environment replays the full Webhook flow against your endpoint with synthetic transactions. Use it to verify signature validation and your retry behaviour before exposing a production endpoint. Sandbox is also the only safe place to deliberately return `500` responses and watch how Paylead retries. ## Common pitfalls | Symptom | Likely cause | Fix | | ----------------------------------- | ----------------------------------------------- | --------------------------------------------- | | Stale Reward status acted on | You trusted the Webhook payload | Re-fetch via the API before acting. | | Webhook retries flooding your queue | Endpoint returns `200` too late | Ack first, process async. | | Wrong signatures | Reading the parsed body instead of the raw body | Verify against `req.rawBody`, not `req.body`. | ## What's next The mandatory `X-Api-Version` header and the version policy. Per-token request limits and backoff strategy. # Environments Source: https://docs.paylead.fr/program/user-journey/environments Paylead exposes two environments: sandbox for integration work and production for live traffic. Each has its own URL, tokens, and data. Paylead runs two fully isolated environments. Build and validate against the sandbox. Switch to production only after Paylead approves your integration. **Why this matters.** Sandbox and production do not share data, tokens, or Consumers. A token from one will not work against the other. Treat them as two separate platforms. ## Comparison Sandbox and production have **full feature parity**. The only differences are the URL, the data they hold, performance, and who is responsible for what. Each Program gets a dedicated subdomain keyed by its **`programRef`**, a unique identifier issued by Paylead at onboarding. Substitute it into the URLs below; the rest of the host is fixed per environment. | Property | Sandbox | Production | | ---------------- | ----------------------------------------- | ------------------------------------------------------- | | Base URL | | | | Data | Test entities you create yourself, no PII | Real [Consumers](/glossary#consumer), real transactions | | Persistence | Permanent (you manage your own cleanup) | Permanent | | Access | Granted on signup | Granted after sandbox validation | | Feature set | 100% of production features | Same | | Webhook delivery | Sandbox signing secret | Production signing secret | | Pricing | Free | Per contract | Sandbox and production hold separate datasets. IDs created in sandbox never appear in production and the reverse. ## Pick the right environment | You are... | Use | | -------------------------------------------- | ------------------------------ | | Building the first integration | Sandbox | | Running automated tests in CI | Sandbox | | Demoing to internal stakeholders | Sandbox | | Validating PSD2 transaction ingestion | Sandbox first, then Production | | Serving real [Consumers](/glossary#consumer) | Production (staged, see below) | ### Production rollout phases Going live in production is staged. Paylead validates your integration at each phase before opening the next: | Phase | Audience | Purpose | | ------------------------ | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | | **Alpha** | A restricted, controlled cohort (typically your own test users and Paylead team) | Paylead validates the end-to-end integration against production plumbing. | | **Beta** | A limited group of real [Consumers](/glossary#consumer) | Pilot run at small scale before full availability. | | **General availability** | All your Consumers | Full production rollout. | Paylead gates the move from one phase to the next; coordinate the schedule with your account manager. ## Switching environments in code The only differences between environments are the base URL and the token. Keep both behind environment variables. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. Never hardcode the base URL or token in source. A single misconfigured deploy can leak production data to a staging service. ## Get sandbox access Paylead grants sandbox access when you sign up for an account in [Shift](/glossary#shift). If you are not yet a [Program Manager](/glossary#program-manager), contact your Paylead representative. ## Promote to production Implement the [Paylead API](/program/user-journey/quickstart) endpoints you need against the sandbox. Cover every endpoint you will call in production. Paylead provides an integration checklist. Execute end-to-end scenarios: Consumer enrollment, transaction ingestion, Reward attribution, Ventilation export. Open a ticket in Shift or contact your Paylead representative with your integration summary. Paylead reviews logs and edge cases. Once validated, generate your production tokens in Shift's **Settings > API Keys**. Roll them through your secret manager. Your services run against `api-{programRef}.paylead.eu` with production tokens. Sandbox tokens stay in CI and staging. ## Sandbox limits The sandbox is shaped for development, not load testing. * Data is **not** reset automatically; you manage your own cleanup. * Per-Program rate limits apply. See [Rate limits](/program/user-journey/rate-limits) and confirm your thresholds with your account manager. * Feature parity with production is complete. Anything you can do in production, you can do in sandbox. ## What's next Enroll Consumers and manage their accounts. How a transaction becomes an attributed Reward. Sandbox vs production throughput. # Errors Source: https://docs.paylead.fr/program/user-journey/errors Paylead application errors carry a problem-details envelope (a machine-readable code, a human title, and field-level errors), while some responses are raised at the edge without it. Paylead uses standard HTTP status codes for protocol-level outcomes and a JSON error envelope for application-level detail. Errors come from two layers: * **The application** handles most calls and, on failure, returns the structured [error envelope](#error-envelope) below; parse it for the precise cause. * **The infrastructure in front of the API** (gateway, authentication, throttling) can answer first, and those responses may not carry the envelope. Always branch on the HTTP status first, then enrich with the envelope when it is present. **Why this matters.** A `400` from malformed JSON and a `400` from a field that fails validation require different fixes. The envelope's `code` and `errors` disambiguate them. ## Error envelope Errors raised by the application share the same JSON shape: a problem-details-style object (the Paylead error profile). Three fields are always present (`code`, `title`, `status`); `errors` and `instance` are added when relevant. Errors raised [at the edge](#raised-at-the-edge) may not include it. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. | Field | Type | Always present | Description | | ---------- | ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `code` | string | Yes | Stable, machine-readable Paylead error code. Switch your logic on this, never on `title`. | | `title` | string | Yes | Human-readable explanation. The wording may change between versions. | | `status` | integer | Yes | The HTTP status code, repeated in the body for convenience. | | `errors` | array of objects | No | Present on validation failures. Each item describes one problem; its fields are endpoint-specific (offending location, expected format, …). `null` when there are no field-level details. | | `instance` | string | No | Reference to this specific occurrence of the failure, when the platform sets one. Include it in support tickets if present. May be `null`. | ```json Example 400 response theme={null} { "code": "PL-400-00", "title": "The request payload is invalid.", "status": 400, "instance": "req_01J9Z3K8QY", "errors": [ { "loc": ["body", "id"], "msg": "String should match pattern '^[a-zA-Z0-9_-]+$'", "type": "string_pattern_mismatch" } ] } ``` ### Locating the failing field in nested payloads `errors[].loc` appears when the failure traces back to a specific field of the input payload, for example a missing value, a wrong type, or a format mismatch. Most other failures, including business-rule errors such as `409 Conflict`, do not carry field-level detail: `errors` is `null` in that case. When present, `loc` is a path from the request body down to the offending field: one segment per level, either an object key or the numeric index of an item inside a list. Read it left to right to walk down to the exact field that failed. Some payloads nest several levels of lists. Creating transactions, for example, sends a list of banks, each holding a list of accounts, each holding a list of transactions. A failure on the `type` of the first transaction of the first account of the first bank looks like this: ```json Nested loc example theme={null} { "loc": ["body", "banks", 0, "accounts", 0, "transactions", 0, "type"], "msg": "Not a valid choice.", "type": "invalid" } ``` Log the full error envelope (`code`, `title`, `status`). When the response carries an `instance`, include it in any bug report you open; it is the fastest way for Paylead support to find the failure in our logs. ## HTTP status codes ### Returned by the application On failure, these carry the [error envelope](#error-envelope) above. | Code | Meaning | When you see it | | --------------------------- | ------------ | -------------------------------------------------------------------------------------------------------------------- | | `200 OK` | Success | Read or update succeeded. | | `201 Created` | Success | Resource was created (Consumer, payment account, …). | | `202 Accepted` | Success | Request accepted for asynchronous processing, e.g. a payout is initiated synchronously but settled later by the PSP. | | `204 No Content` | Success | Delete or update succeeded; no body. | | `400 Bad Request` | Client error | Payload invalid, missing field, or malformed JSON. The `errors` array carries the field-level detail. | | `401 Unauthorized` | Auth error | Missing, expired, or invalid credentials/token. | | `403 Forbidden` | Auth error | Authenticated, but not allowed: wrong scope, [Program](/glossary#program), or environment. | | `404 Not Found` | Client error | Resource ID does not exist. | | `409 Conflict` | Client error | Resource already exists, or the state transition is illegal. | | `500 Internal Server Error` | Server error | Unexpected failure inside the API. Retry with backoff. | | `502 Bad Gateway` | Server error | An upstream dependency (for example the PSP) was unavailable. Retry with backoff. | ### Raised at the edge Some requests never reach the application: the API gateway and upstream infrastructure answer first (throttling and gateway failures). **These responses may not carry the error envelope**: the body can be empty, plain text, or a different JSON shape, so branch on the HTTP status and never assume a parseable `code` / `title`. | Code | Meaning | Typical cause | | ----------------------- | ---------- | ---------------------------------------------------------------------------------- | | `429 Too Many Requests` | Throttling | Program rate limit exceeded. See [Rate limits](/program/user-journey/rate-limits). | | `504 Gateway Timeout` | Server | A gateway or upstream dependency timed out. Retry idempotent calls only. | Authentication is also enforced here: `401` and `403` (listed above) are returned by the application **with** the envelope, but an edge rejection may arrive **without** it. `502` behaves the same way: the application returns it with the envelope when an upstream dependency such as the PSP is unavailable, while a gateway can also emit a `502` without one. Handle both. ## Paylead error codes The `code` field is what you branch on. The codes below are the ones the Perks endpoints return, grouped by the operation that raises them. Each endpoint's own reference page lists the codes it can return. Match the full code. Two codes sharing an HTTP status carry unrelated causes, and each one maps to its own message on the payout and IBAN flows. **Returned by every endpoint** | Code | HTTP | Title | When you see it | | ----------- | ----- | --------------------- | ------------------------------------------------------------------------------------------------------------------- | | `PL-400-00` | `400` | Bad Request | Payload or query parameter invalid. Read the `errors` array. | | `PL-401-00` | `401` | Unauthorized | Token missing, expired, or invalid. | | `PL-404-00` | `404` | Not Found | The `offer_id`, `brand_id`, or `reward_id` does not exist. | | `PL-404-02` | `404` | Consumer Not Enrolled | The `consumer_id` is unknown to this [Program](/glossary#program). Enroll the [Consumer](/glossary#consumer) first. | **Enrollment** (`POST /perks/consumers`) | Code | HTTP | Title | When you see it | | ----------- | ----- | --------------------------------- | ----------------------------------------------------------------------- | | `PL-409-09` | `409` | Consumer Not Enrolled On Platform | The Consumer must exist on the platform before being enrolled on Perks. | | `PL-409-10` | `409` | Consumer Already Enrolled | The Consumer is already enrolled. Read it instead of recreating it. | **Pool and KYC** | Code | HTTP | Title | When you see it | | ----------- | ----- | ------------------------- | ----------------------------------------------------------------------------------------------------- | | `PL-403-01` | `403` | Consumer Pool Not Enabled | The Consumer has no [pool](/glossary#pool). Raised on the payment account, KYC, and payout endpoints. | | `PL-409-05` | `409` | Consumer KYC Not Ready | KYC is incomplete or still under review. Blocks IBAN designation and payout. | | `PL-400-06` | `400` | KYC Rejected | The PSP rejected the submitted KYC data. | **Payment account** (`/perks/consumers/{consumer_id}/accounts/payment`) | Code | HTTP | Title | When you see it | | ----------- | ----- | ---------------------------------- | ---------------------------------------------------------------------------- | | `PL-400-05` | `400` | Payment Account Recipient Rejected | The PSP refused the IBAN, on creation or on deletion. | | `PL-400-08` | `400` | Natural User Address Missing | The Consumer has no address, which the PSP requires to register a recipient. | | `PL-409-04` | `409` | Payment Account Already Exists | An IBAN is already designated. Delete it before designating another. | | `PL-404-05` | `404` | Payment Account Not Found | No IBAN designated for this Consumer. | **Payout** (`POST /perks/consumers/{consumer_id}/pools/me/payouts`) | Code | HTTP | Title | When you see it | | ------------ | ----- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | `PL-409-07` | `409` | Pool Below Threshold | The pool balance is under the payout threshold the Program Manager configured. See [Ventilation](/program/user-journey/concepts/ventilation). | | `PL-409-08` | `409` | Payment Account Missing | No IBAN designated. Collect one first. | | `PL-409-11` | `409` | Payment Account Not Validated | The designated IBAN is not validated yet. | | `PL-409-06` | `409` | Consumer Outflow Blocked | Payouts are blocked for this Consumer. | | `PL-400-07` | `400` | Payout Rejected | The PSP refused the transfer. | | `PL-409-999` | `409` | Contact Admin User | The payout cannot proceed and needs Paylead intervention. | **Segments** (`/perks/consumers/{consumer_id}/segments/{segment_reference}`) | Code | HTTP | Title | When you see it | | ----------- | ----- | ------------------------------------ | ------------------------------------------------------------------- | | `PL-404-03` | `404` | Segment Not Found | No [Segment](/glossary#segment) with that reference in the Program. | | `PL-404-04` | `404` | Segment Assignation Not Found | The Consumer is not assigned to that Segment. | | `PL-409-03` | `409` | Segment Already Assigned To Consumer | The assignation already exists. | **Upstream** (any PSP-backed operation) | Code | HTTP | Title | When you see it | | ----------- | ----- | ----------------------- | --------------------------------------------------------- | | `PL-502-03` | `502` | PSP Service Unavailable | The payment provider was unreachable. Retry with backoff. | ## Handling common errors The payload is malformed JSON, or a field fails validation. **Fix.** Read the `errors` array: each entry points at the offending field and the rule it broke. Coerce the value on the client and resend. If `errors` is empty, the body itself was not valid JSON. The credentials or bearer token are missing, malformed, or expired. **Fix.** Verify the `Authorization` header. For OAuth2, request a fresh token from `/tokens` (client-credentials flow) and check the API key in [Shift](/glossary#shift). See [Authentication](/program/user-journey/authentication). The token is valid but is not allowed to access this resource, for example it was issued for a different [Program](/glossary#program) or environment, or it lacks the required scope (`LOYALTIES`, `PERKS`, `TX_INJECTION`, or `ALL`). **Fix.** Confirm you are using the token issued for this Program and this environment (sandbox vs production), and that it carries the scope the endpoint needs. See [Authentication](/program/user-journey/authentication). No resource matches the given ID, for example no [Consumer](/glossary#consumer) with that `consumer_id`. **Fix.** Verify the ID and confirm the resource was created against the same environment. Create it if needed. The resource already exists, or the requested state transition is illegal, for example creating a [Consumer](/glossary#consumer) whose `id` is already in your [Program](/glossary#program). **Fix.** Read the resource first, then update it instead of recreating it, or pick a new identifier. Never reuse an ID for a different resource. Something failed inside Paylead (`500`) or in an upstream dependency (`502`). Not your fault, but you still need to handle it. **Fix.** Retry idempotent calls with exponential backoff. If the issue persists, share the response body (including the `instance` when present) with Paylead support. ## Retry strategy | Status code | Retry? | Strategy | | -------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------- | | `4xx` (except `429`) | No | Fix the client. Retrying gives the same error. | | `429` | Yes | Honor `Retry-After`. Exponential backoff with jitter. See [Rate limits](/program/user-journey/rate-limits). | | `500`, `502` | Yes | Exponential backoff. Cap at 5 attempts. | | `504` | Yes, idempotent only | `GET` and `DELETE` are safe to retry. Retrying a timed-out or `POST` may create a duplicate. | Paylead does **not** support an `Idempotency-Key` request header. When a `POST` times out, you cannot ask the server to deduplicate the retry. Mitigate by re-reading the resource via `GET` before retrying, or by using deterministic identifiers (for example, your own Consumer ID) so a re-creation surfaces as `409` instead of a duplicate. ## What's next Common integration questions, answered. Data protection and regulatory compliance for your integration. Contact Paylead support. Share the failing response, including its `instance` when present. # FAQ Source: https://docs.paylead.fr/program/user-journey/faq Common questions from banks evaluating or onboarding Paylead: pricing, integration, data handling, and operations. This page answers the questions partner banks ask most often during evaluation and onboarding. For specifics tied to your contract or use case, contact your Paylead account manager. ## Business and pricing Pricing depends on Program scope, transaction volume, and use case. Contact your Paylead account manager for a tailored proposal. A standard integration takes a few weeks for the API layer and a few additional weeks for production validation and Consumer onboarding. Timelines vary with internal review cycles and specific development.  Paylead operates across the Eurozone today. Reach out to your account manager for the current list of supported markets. ## Integration and tech No. Paylead is a SaaS platform. Your bank calls REST APIs and consumes [Webhooks](/program/user-journey/concepts/webhooks). In some cases you may also use our white-labelled [WebApp](/program/user-journey/concepts/web-app) as a touchpoint in your own mobile app.  On Cashback or Loyalty Reward, latency depends on how often you push transactions to Paylead. The more frequent your integration's cadence, the closer to real-time the Consumer experience feels. Most Rewards surface as pending within minutes after Offer usage. Yes. [Offers](/glossary#offer) can be scoped to specific [Segments](/glossary#segment) and [Campaigns](/glossary#campaign), allowing different Cashback rates per audience, for example on Premium users. Yes. The Paylead sandbox exposes the same endpoints, payloads, and behaviors as production. The only differences are isolation (no real payouts), a separate base URL and Offer contents. See [Environments](/program/user-journey/environments). ## Operations Paylead handles refunds as part of normal transaction processing. Use [Shift](/glossary#shift) for the day-to-day back-office view (Offers, Campaigns, Consumers, Rewards), and the [Reporting guide](/program/user-journey/guides/reporting) for KPIs and exports. Each Program has a dedicated customer success manager who handles Program performance reviews. Specifics are defined in your contract. ## What's next Data protection and regulatory compliance for your integration. Browse the Program API endpoints and download the OpenAPI specs. # Consumer lifecycle Source: https://docs.paylead.fr/program/user-journey/guides/manage-consumers Create a Consumer on the platform, opt them in to Perks or Loyalty, set up transaction sharing, and off-board them. The service-agnostic Consumer lifecycle. A [Consumer](/glossary#consumer) is the anchor of your [Program](/glossary#program). Every [Reward](/glossary#reward), [Offer](/glossary#offer) eligibility check, and [Webhook](/glossary#webhooks) references one. This guide follows the Consumer lifecycle: the Consumer is created on the platform, opts in to one or both services, and then transaction sharing is set up. For the wider picture, see the [User journey](/program/user-journey/overview). ## The Consumer lifecycle Create the Consumer with their `consumer_id`, the only required field. Service-agnostic: it registers the end user before any service opt-in. Enroll the Consumer in [Perks](/glossary#perks), [Loyalty](/glossary#loyalty), or both. Each opt-in accepts that service's terms and unlocks it. Share the Consumer's transaction history (typically the last 12 months), then keep pushing new transactions. On Perks, the Consumer can grant the `SMART_RANKING` consent to enable [Offer Smart Ranking](/glossary#offer-smart-ranking). On Perks, the Program Manager can assign one or more Segments to scope which Offers the Consumer sees. Deactivate the Consumer when they unsubscribe from all Paylead services. The Consumer is created, opts in to a service, and then transaction sharing is set up. The Perks add-ons are optional; off-boarding is the terminal, irreversible state. ```mermaid theme={null} flowchart TD A["Create on the platform
(consumer_id)"] --> C{"Opt in
(Perks, Loyalty, or both)"} C -->|Perks| PB["Set up transaction sharing"] C -->|Loyalty| LB["Set up transaction sharing"] subgraph Perks["Perks add-ons (optional)"] direction TB P2["Grant SMART_RANKING consent"] --> P3["Assign Segments"] end PB --> P2 PB --> O["Off-board
(unsubscribe, irreversible)"] P3 --> O LB --> O classDef neutral fill:#f1efe8,stroke:#888780,color:#2c2c2a classDef decision fill:#ffffff,stroke:#888780,color:#2c2c2a classDef primary fill:#e6f1fb,stroke:#0465ff,color:#042c53 classDef accent fill:#e1f5ee,stroke:#0f6e56,color:#04342c classDef danger fill:#fcebeb,stroke:#a32d2d,color:#501313 class A,PB,LB neutral class C decision class P2,P3 primary class O danger style Perks fill:transparent,stroke:#85b7eb,color:#185fa5 ``` *** ## Create a Consumer on the platform The Consumer ID you pass is the bank's internal identifier. Paylead reuses it across every downstream call (transactions, Rewards, Webhooks). Once chosen, it cannot be changed without a full off-board and re-onboard. It is also the identifier Paylead displays to represent the Consumer across all business units (support, marketing, technical). Create the Consumer with [Onboard a consumer on Paylead platform](/program/api/thub/consumers/onboard-a-consumer-on-paylead-platform). **Payload essentials** * `id`: bank-internal Consumer ID. The only required field. Must be unique and stable across the Consumer's lifetime. * `banks`: optional. The bank connections and accounts to link. One Consumer can hold several accounts under the same `id`, and accounts can be added later. The Consumer exists on the platform and is ready to opt in to a service. ## Opt in to Perks Enroll the Consumer in the Perks service with [Enroll a consumer into the perks program](/program/api/perks/consumers/enroll-a-consumer-into-the-perks-program-accept-cgu). Enrolling accepts the Program's terms and makes the Consumer eligible to match Offers. Enrollment marks the start of Reward eligibility on the Consumer's linked bank accounts. Opting in is per service. A Consumer can be enrolled in Perks, Loyalty, or both. This guide covers the Perks-side operations; the Loyalty opt-in is covered in the [User journey](/program/user-journey/overview#the-loyalty-journey). ## Set up transaction sharing Transactions are shared at the platform level and reused by whichever service the Consumer joins. Push the Consumer's history with [Create a bulk of historical transactions](/program/api/thub/bulk-transaction/create-a-bulk-of-historical-transactions), then keep them current with [Create a bulk of transactions](/program/api/thub/bulk-transaction/create-a-bulk-of-transactions). Always call the historical endpoint, even when the Consumer has no history to share. With no past transactions, send an empty payload (`{ "banks": [] }`) to complete this step. For how Paylead ingests and matches transactions, see [Share transactions](/program/user-journey/concepts/transaction-lifecycle). ## Smart Ranking consent (Perks, optional) [Offer Smart Ranking](/glossary#offer-smart-ranking) personalizes the order of Offers from the Consumer's transaction data. It requires the Consumer's explicit `SMART_RANKING` consent. Manage it through the Perks enrollment call: pass `SMART_RANKING` in `extra_consents` to grant it, and in `removed_consents` to withdraw it. **Capturing consent is the bank's responsibility.** Collect the Consumer's explicit choice in your own UI before sending it to Paylead. The Paylead call records the result; it does not replace your consent-capture flow under GDPR. ## Assign Segments (Perks, optional) [Segments](/glossary#segment) let you expose Offers to a defined audience, set by your bank's own criteria, for example *Premium*, *New*, or *Gold*. A Consumer can belong to several Segments at once. Segmentation is optional and managed by the Program Manager in [Shift](/glossary#shift) or through the API. Segment definitions are provisioned by your Paylead account manager after a compliance check on the criteria. The Program Manager then assigns Consumers to them in Shift or through the API. This keeps targeting rules under business control. ## Off-board a Consumer Off-boarding stops Reward generation, revokes the Consumer's identifier, and locks their record. Use it when the Consumer leaves your Program, closes their bank account, or exercises their right to be forgotten under GDPR. Off-board with [Offboard a consumer from Paylead platform](/program/api/thub/consumers/offboard-a-consumer-from-paylead-platform). Off-boarding is irreversible. No new Rewards are generated. Rewards already issued are kept for accounting, but a Reward that has not been paid out yet is handled per [Rewards in flight at off-boarding](#rewards-in-flight-at-off-boarding). To re-enroll the Consumer later, use a new `id`. ### Rewards in flight at off-boarding Off-boarding closes the Consumer's [pool](/glossary#pool). What happens to a Reward that has not been paid out yet depends on the technical status it holds at that moment. A Reward still in `PENDING_VALIDATION` is cancelled: no Cashback and no commission are ever due. A Reward already in `PAID_OUT` is settled on both sides and nothing is reversed. Everything in between is decided by the payout model your Program runs. Paylead holds the pool and pays the Consumer directly. An off-boarded Consumer can no longer be paid, so the pooled amount is forfeited and retained by Paylead. The Program Manager's commission is unaffected and is settled as usual. A Consumer who off-boards with a non-empty pool loses the pooled amount. Warn them in your off-boarding flow, and offer a payout before the off-board call whenever the manual threshold is reached. Check `perks.can_trigger_pooled`, then [trigger the payout](/program/api/perks/upm/trigger-a-payout-of-the-consumers-pool). See [Triggering the payout](/program/user-journey/concepts/ventilation#triggering-the-payout). **With advance of funds** | Technical status | Consumer status | Cashback | Commission | | -------------------- | --------------- | ------------------- | -------------------------- | | `PENDING_VALIDATION` | `Pending` | Cancelled | Cancelled | | `VALIDATED` | `Pool` | Retained by Paylead | Due to the Program Manager | | `VALIDATED` | `Paid` | Already paid | Already settled | | `PAID_IN` | `Pool` | Retained by Paylead | Due to the Program Manager | | `PAID_IN` | `Paid` | Already paid | Already settled | | `PAID_OUT` | `Paid` | Already paid | Already settled | **Without advance of funds** | Technical status | Consumer status | Cashback | Commission | | -------------------- | --------------- | ------------------- | -------------------------- | | `PENDING_VALIDATION` | `Pending` | Cancelled | Cancelled | | `VALIDATED` | `Pending` | Retained by Paylead | Due to the Program Manager | | `PAID_IN` | `Pool` | Retained by Paylead | Due to the Program Manager | | `PAID_OUT` | `Paid` | Already paid | Already settled | #### Payout that failed before off-boarding A payout can fail for a technical reason, for example a rejected bank transfer, and leave the amount unpaid. If the Consumer then off-boards, that amount is not forfeited straight away: Paylead keeps it available for **6 months**. During that window, the Program Manager can raise a claim on behalf of its Consumer and the amount is paid. After 6 months without a claim, Paylead retains it. The Program Manager is the claim channel: an off-boarded Consumer no longer exists on the Paylead side and cannot be identified. Raise the claim through your Paylead account manager or on [Shift](/glossary#shift). Paylead settles Cashback and commission to the Program Manager, which credits its own Consumers. Off-boarding on the Paylead side changes nothing to that settlement: the amounts still reach the Program Manager. What happens to the off-boarded Consumer's balance from there is the Program Manager's call, under its own terms and conditions. The mapping is identical whether the Program runs with or without advance of funds. | Technical status | Consumer status | Cashback | Commission | | -------------------- | --------------- | ------------------------------ | -------------------------- | | `PENDING_VALIDATION` | `Pending` | Cancelled | Cancelled | | `VALIDATED` | `Pending` | Settled to the Program Manager | Due to the Program Manager | | `PAID_IN` | `Pool` | Settled to the Program Manager | Due to the Program Manager | | `PAID_OUT` | `Paid` | Already paid | Already settled | ### Data retention after off-boarding Off-boarding deletes all of the Consumer's transactions, except those that produced a Reward. Paylead keeps those for 5 years, for their accounting value and to meet its legal and regulatory archiving obligations. Deletion is immediate. The [2-year retention window](/program/user-journey/concepts/transaction-lifecycle#retention) that applies while the Consumer is active does not carry over. The transactions that are kept are dissociated from the `consumer_id`. They remain as standalone records, with no link back to the Consumer. Dissociation is not reversible. Once the link to the `consumer_id` is removed, a Reward can no longer be traced back to the Consumer who generated it. The Consumer is off-boarded. Reward generation stops and the pool is closed. ## What's next Surface partner Brands and Offers to your onboarded Consumers. Track the Reward lifecycle and display statuses in your app. Subscribe to Consumer and Reward events for real-time updates. # Promote your program Source: https://docs.paylead.fr/program/user-journey/guides/promote-program Use public Offers to attract prospects before they enroll. Highlight Brands and promotions on landing pages, marketing emails, and onboarding flows. A prospect cannot see personalized [Offers](/glossary#offer): they are not a [Consumer](/glossary#consumer) yet. Public Offers solve this gap. They are universally eligible, displayable without authentication, and built for acquisition. ## Quick start Fetch the public Offers for your [Program](/glossary#program) and display 4 to 6 partner [Brand](/glossary#brand) logos where prospects decide to enroll. Keep the order Paylead returns them in. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. ## What is a public Offer A public Offer is an [Offer](/glossary#offer) that every Consumer of your [Program](/glossary#program) is eligible for, with no segmentation and no targeting. That makes it safe to display anywhere: marketing pages, public app screens, comparison ads, onboarding flows. Use public Offers to answer the prospect's question: *"What would I actually get if I joined this Program?"* *** ## Recommended display Displaying partner [Brand](/glossary#brand) logos on your acquisition surfaces significantly increases the onboarding rate. Prospects recognize the Brands they already shop with and grasp the value of joining straight away. The recommended setup is to show **4 to 6 partner logos** for Brands that carry a public Offer, placed where prospects decide whether to enroll. By default, Paylead sorts the Brands it returns to maximize performance: a smart ranking applied at the scale of your [Program](/glossary#program). Display the Brands in the order Paylead returns them rather than reordering them yourself. Brand visibility is not only for acquisition. Highlighting partner Brands also drives engagement among enrolled Consumers: more visibility means more views on individual Offers, and higher Offer traffic lifts overall Offer performance. Always pick Brands that carry a public Offer. A logo with no active public Offer gives the prospect nothing to act on. ## What drives Program performance Three levers compound to accelerate a Program's performance: * **Onboarding access positioning.** Where the entry point to onboarding sits on your surfaces is decisive. Keep it prominent and easy to reach. * **Partner Brand display.** Showing recognizable partner logos turns abstract value into something concrete for the prospect. * **Active animation.** A Program animated through regular [Campaigns](/glossary#campaign) and seasonal pushes performs significantly better than a static one. *** ## What's next Common questions about running your Program. Data protection and regulatory compliance for your integration. # Reward lifecycle Source: https://docs.paylead.fr/program/user-journey/guides/reward-lifecycle The Reward lifecycle: types, the two status tracks, listing and retrieving Rewards through the Paylead API, and how attribution guarantees one Reward per purchase. A [Reward](/glossary#reward) is what a [Consumer](/glossary#consumer) earns when they use an [Offer](/glossary#offer). This page covers the Reward lifecycle: the types Paylead generates, the two status tracks, how to list and retrieve Rewards through the [Paylead API](/program/user-journey/quickstart), and how attribution guarantees one Reward per purchase. For how a Consumer earns a Cashback or buys a Voucher in the first place, see [Use an offer](/program/user-journey/guides/use-an-offer). ## Reward types Paylead generates four types of Rewards. Treat them identically on the Consumer screen: they all credit the bank account the same way. | Type | Source | | -------------- | -------------------------------------------------------------------------------------------- | | `CASHBACK` | A bank transaction matched an Offer. Detected via [ALO](/glossary#alo-account-linked-offer). | | `LBS_CASHBACK` | A local merchant Campaign via [LBS](/glossary#lbs-local-business-solution). | | `GIFT` | A welcome bonus, loyalty incentive, or promotional one-off. | *** ## The Reward status flow Every Reward carries **two parallel status tracks**: a **technical** status your back-office uses for accounting and [Ventilation](/glossary#ventilation), and a **Consumer-facing** status to surface in the bank app. Show the Consumer status in the UI; reconcile on the technical status. **Rewards are near-instant.** Over 95% of Rewards are created and set to `VALIDATION` within 10 seconds of the Consumer using the Offer. You can surface the Reward in the app almost immediately, no polling delay to design around. What the Consumer sees in your app. Four values, returned in the `consumer_status` field. | `consumer_status` | What it means | Display tip | | ----------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------- | | `VALIDATION` | A Reward is likely. This is the point where it becomes visible to the Consumer. | "Earning: confirms within 30 days". Display it immediately. | | `POOLED` | The Reward is processed. The Consumer can request a payout. | "Confirmed, ready to pay out", and surface the payout action. | | `PAID` | The Consumer has been paid. | Show the credit date and amount. | | `CANCELLED` | The Reward is cancelled and will not be paid. | Show with reason, archive after 30 days. | `VALIDATION` covers a Reward that is earned and one that is confirmed. The technical `status` tells those two apart. What your back-office systems track (seven values). | Status | What it means | | --------------------- | ------------------------------------------------------------------------------------------------------------------------- | | `PENDING_ATTRIBUTION` | Awaiting the attribution decision: which Consumer owns the purchase. See [Reward attribution](#reward-attribution) below. | | `NOT_ATTRIBUTED` | Discarded as a duplicate of the same purchase; never paid out. | | `PENDING_VALIDATION` | Attributed, inside the refund window (typically 30 days). | | `VALIDATED` | Paylead guarantees the payout. | | `PAID_IN` | Funds received from the merchant. | | `PAID_OUT` | Funds disbursed via the Ventilation pipeline. | | `CANCELLED` | Reward cancelled (refund, dispute) before validation. | As soon as a Reward is visible to the Consumer (`VALIDATION`), display it. Don't wait for validation: the early signal is what drives engagement. The two tracks are decoupled: the Consumer status follows UX moments, not the exact accounting state. *** ## List rewards Return every Reward generated for a specific Consumer. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. Each item in the response includes the `id`, `amount`, `type`, `created_at`, the originating `transaction` (`null` for a Reward without one, such as a Gift), the origin `brand`, and both status fields: `status` for the technical track and `consumer_status` for the Consumer-facing one. Filter the listing on `type`, and on the `created_at__gte` / `created_at__lte` / `executed_at__gte` / `executed_at__lte` date bounds. ## Get reward details Fetch the full payload for a single Reward. Show it on the detail screen with the estimated payout date, the originating transaction, and the source Offer. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. Need real-time status updates instead of polling? Subscribe to the `reward.*` events on the [Webhooks reference](/program/user-journey/concepts/webhooks). Paylead pushes a notification on every status transition so you can drive in-app notifications, CRM updates, and accounting reconciliation without batch jobs. ## Reward attribution A single Consumer purchase can land in Paylead from multiple sources at the same time: the bank's own feed, an account aggregator. Without arbitration, the merchant could be billed twice and the Consumer rewarded twice. [Reward attribution](/glossary#reward-attribution) prevents that: it runs automatically on every eligible transaction, in two stages. ```mermaid theme={null} flowchart LR T1[Transaction A - Bank] --> D{Duplication engine} T2[Transaction B - Aggregator] --> D D -->|Same purchase| A{Attribution engine} D -->|Distinct purchases| R0[Reward each] A -->|Winner| R1[One Reward issued] A -->|Losers| R2[Not attributed Reward] classDef neutral fill:#f1efe8,stroke:#888780,color:#2c2c2a classDef decision fill:#ffffff,stroke:#888780,color:#2c2c2a classDef success fill:#eaf3de,stroke:#3b6d11,color:#173404 classDef danger fill:#fcebeb,stroke:#a32d2d,color:#501313 class T1,T2 neutral class D,A decision class R0,R1 success class R2 danger ``` The duplication engine inspects incoming transactions against a battery of signals (IBAN, issuing bank, amount, executed-at timestamp, Brand identifier, and sequence proximity) to detect when several records describe the same underlying purchase. When two or more transactions resolve to the same purchase, only one is allowed to generate a Reward. The others are flagged as duplicates and excluded. If the deduplicated transaction is eligible to be rewarded under more than one Program, the attribution engine picks the winning Program based on a scoring system. Only the winner issues a Reward. ### When no Reward is attributed Not every eligible transaction generates a Reward. Common reasons: * The Offer's budget cap was reached before the transaction settled. * The transaction was cancelled or refunded before validation. * A duplicate was processed and the current record lost the attribution round. Paylead drops the un-attributed transaction. No `REWARD_CREATED` Webhook fires. Use Consumer detail on Shift if a Consumer disputes a missing Cashback. *** ## FAQ Up to 30 days, matching the refund window of most card networks. The exact validation date is exposed as `executed_at` plus the brand's validation delay. If the refund occurs before validation, the Reward transitions to `CANCELLED` automatically. Once a Reward reaches `VALIDATED`, it can no longer be cancelled or modified: a later refund is **not** clawed back. For disputes, use the form on Shift; there is no public dispute API endpoint. No. Paylead's [Reward attribution](#reward-attribution) mechanism guarantees exactly one Reward per qualifying purchase, even when the same transaction is reported by multiple sources (bank feed plus aggregator). *** ## What's next How a validated Reward reaches the Consumer's pool and gets paid out. React to Reward lifecycle events in real time. The loyalty wallet Consumers build alongside their Rewards. # Seamless Payment Source: https://docs.paylead.fr/program/user-journey/guides/seamless-payment Program × Developer: let a Consumer pay for an order while Paylead delegates the payment to the payment method your Program already runs. Seamless Payment lets a [Consumer](/glossary#consumer) pay for an order without leaving the environment they already trust. Paylead initiates the payment; your Program executes it with its own payment method and returns the result. Fewer checkout steps means a higher completion rate. This page is for the **product and engineering teams** of a Program integrating as the payment delegation provider. It covers the Consumer experience, what you must build, and how the flow works both **in the Paylead WebApp** and **via API integration**. **In progress.** Seamless Payment is being implemented on API version `2.0.0`. The contract below may still be adjusted through the API. Contact your Paylead operations manager for more details. ## Roles * **Paylead** owns the order, **generates the `payment_id`**, initiates the payment when the purchase is confirmed, completes the order on success, and handles any refunds (partial or total). * **You (the Program)** receive the payment request on your endpoints, execute it with your payment method, return the result, and reconcile against your banking system. **Identifiers.** * `payment_id`: a **UUID generated by Paylead**, matching the internal order (the generic term that covers both a WebApp purchase and a one-click API purchase). It is your **idempotency key**; echo it on every callback and, critically, in the wire reference (see Reconciliation). * `consumer_id`: Paylead's identifier for the user. * `account_id`: the account external\_id provided through the PM hub integration. ## Two purchase modes, one payment contract The delegated payment contract below is identical in both cases: * **WebApp**: the Consumer completes a purchase inside the Paylead WebApp opened from your app. * **API integration (coming)**: your app triggers a purchase through the Paylead API (one-click), without the WebApp. ## Consumer experience (WebApp) 1. The Consumer opens the WebApp from your app. 2. The Consumer selects what to buy and an amount, then confirms. 3. Paylead sends the payment request to your endpoint. 4. You authorize or reject the payment, synchronously or asynchronously. 5. On success, Paylead completes the order and redirects the Consumer to it. 6. On failure, Paylead shows an error and lets the Consumer retry. ## Authentication Both directions must be authenticated before go-live. * **Paylead to your endpoints:** Paylead authenticates its requests with the mechanism agreed for your Program (e.g. mTLS or a signed token). Reject unauthenticated calls. * **You to Paylead callbacks:** authenticate with the credentials Paylead issues for your Program. A `payment_id` alone must never be enough to trigger order completion. ## Delegated payment flow A two-step process, plus an optional status endpoint. ### Step 1: Payment authorization (required) When the purchase is confirmed, Paylead sends a `POST` to your authorization endpoint (URL configured per Program): ```json theme={null} { "consumer_id": "bank-user-1234", "account_id": "acct-ext-5678", "payment_id": "9f2c1a44-6b7e-4c1d-9a2f-1e5c3b0a7d21", "amount": 1000 } ``` `amount` is in **minor units** (`1000` = `10.00`). Respond with one of: | HTTP | Meaning | | ----- | ------------------------------------------------------------------------ | | `201` | Accepted synchronously. Paylead completes the order immediately. | | `202` | Pending extra validation (e.g. SCA). You will send the result in Step 2. | | `400` | Failed. Include a `failure_reason`. | `failure_reason` values (on `400` and in Step 2 failures): * `INSUFFICIENT_FUNDS` * `PAYMENT_LIMIT_EXCEEDED` * `TECHNICAL_ISSUE` * `USER_NOT_FOUND` ### Step 2: Payment result callback (asynchronous only) If Step 1 returned `202`, notify Paylead once validation completes. Paylead provides the callback base URL for your Program. `payment_status` is a path segment: `success` or `failure`. Success, empty JSON body: ```http theme={null} POST {paylead_base_url}/consumers/{consumer_id}/payments/{payment_id}/success Content-Type: application/json {} ``` Failure: ```http theme={null} POST {paylead_base_url}/consumers/{consumer_id}/payments/{payment_id}/failure Content-Type: application/json { "failure_reason": "INSUFFICIENT_FUNDS" } ``` **Resolve async payments in time.** With no callback within the finalization window, Paylead treats the payment as failed (`TECHNICAL_ISSUE`) and releases the order. **Idempotency.** Paylead accepts one final result per `payment_id`; later callbacks on an already-resolved payment are rejected, and the callback is validated against the owning `consumer_id`. ### Step 3: Status check (optional) Expose an endpoint so Paylead can check a payment's outcome, for incident recovery and audit (URL to be confirmed per Program): ```http theme={null} GET {program_base_url}/consumers/{consumer_id}/payments/{payment_id} ``` ```json theme={null} { "status": "success", "failure_reason": null } ``` `status` is `success`, `failure`, or `pending`. `failure_reason` is `null` unless `status` is `failure`. ## Refunds An order may be refunded, partially or in full. Paylead handles refunds. ## Reconciliation Paylead reconciles each order with the payin it receives. You **MUST** include the `payment_id` in the **wire reference** of every bank transfer used to fund a purchase. It is the only key linking the order, the payment execution, the payin received, and any later refund. Without it, reconciliation and refunds are impossible. ## Error handling shown to the Consumer On failure at Step 1 or Step 2, the WebApp shows: > The payment could not be completed. No charge was made. You may try again with a different amount. ## Sequence diagram ```mermaid theme={null} %%{init: {'themeVariables': {'actorBorder':'#0465ff','signalColor':'#378add'}}}%% sequenceDiagram autonumber participant User as Consumer participant Webapp as Paylead WebApp participant PayleadBE as Paylead Backend participant PartnerBE as Your Backend (Payments) User->>Webapp: Selects what to buy and an amount, confirms Note over PayleadBE,PartnerBE: Delegated payment (endpoint provided by the Program) PayleadBE->>PartnerBE: POST authorization {consumer_id, account_id, payment_id, amount} alt Sync success (201) PartnerBE-->>PayleadBE: Accepted PayleadBE-->>Webapp: Complete order and redirect else Sync error (400) PartnerBE-->>PayleadBE: {failure_reason} Webapp-->>User: Payment error, option to retry else Async (202) PartnerBE-->>PayleadBE: Accepted, awaiting validation alt Async success PartnerBE->>PayleadBE: POST /payments/{payment_id}/success PayleadBE-->>Webapp: Complete order and redirect else Async failure PartnerBE->>PayleadBE: POST /payments/{payment_id}/failure {failure_reason} Webapp-->>User: Payment error, option to retry else No callback in time Note over PayleadBE: Finalization timeout, payment failed PayleadBE-->>Webapp: Payment error, option to retry end end ``` ## Your responsibilities **You must:** * Authenticate Paylead's requests, and your own callbacks to Paylead. * Expose the Step 1 authorization endpoint; respond `201`/`400` synchronously, or `202` then call Step 2. * Resolve every `202` before the finalization window closes. * Include `payment_id` in the wire reference of every funding transfer. * Return documented, uppercase `failure_reason` values. **You must not:** * Approve or resolve the same `payment_id` more than once. * Leave asynchronous transactions unresolved. ## What's next The SSO flow the Consumer goes through before reaching the purchase. How you create Consumers and get the `consumer_id` and `account_id` used in the payment request. # Use an offer Source: https://docs.paylead.fr/program/user-journey/guides/use-an-offer The two ways a Consumer uses an Offer: a Cashback Offer rewards automatically from a shared transaction, a Voucher Offer is bought up front through the Paylead API. A [Consumer](/glossary#consumer) uses an [Offer](/glossary#offer) in one of two ways, depending on its type. A **Cashback Offer** rewards them automatically when a transaction matches the Offer's terms. A **Voucher Offer** is activated by purchasing a Voucher. This page covers both flows. For what happens to the [Reward](/glossary#reward) once it exists, see [Reward lifecycle](/program/user-journey/guides/reward-lifecycle). ## Cashback offers (automatic) A Cashback Offer needs no action from the Consumer. Once they are enrolled in [Perks](/glossary#perks), every eligible transaction the bank shares with Paylead is matched against the Consumer's active Offers, and a match creates a [Cashback](/glossary#cashback) Reward automatically. Onboarding and consent put the Consumer into the Perks service. From that point their transactions are eligible for matching. The bank pushes the transaction to Paylead through the [Share transactions](/program/user-journey/concepts/transaction-lifecycle) flow. This is a platform-level task, independent of any single Offer. Paylead checks the transaction against the Consumer's active Offers (Brand, amount, channel, validity, targeting). On a match, Paylead creates a Reward. Over 95% of Rewards reach the `VALIDATION` status within 10 seconds of the transaction being shared. There is nothing to render for the act of earning itself: the Consumer does not tap or confirm anything. Your job is to surface the resulting Reward. See [Reward lifecycle](/program/user-journey/guides/reward-lifecycle) for the status tracks and the list and detail endpoints. ## Voucher offers (bought up front) The Voucher API is in **beta**. The endpoints and payloads below describe the main flow; the exact fields are still subject to change. A [Voucher](/glossary#voucher) Offer lets the Consumer buy a prepaid value redeemable at a participating [Brand](/glossary#brand). Unlike a Cashback Offer, the Consumer actively places an order and pays for it. The whole flow runs through the Paylead API: Voucher order payment no longer depends on a WebApp. ### The purchase flow Voucher Offers are the `VOUCHER` entries in the catalog. Surface them like any other Offer (see [The Offer catalog](/program/user-journey/guides/work-with-offers)). Place an order on the chosen Offer with `POST /offers/{offer_id}/vouchers/orders`. The body carries one or more `amount_selections`, each an `amount` and a `quantity`. The order starts in `CREATED`. ```json theme={null} { "amount_selections": [ { "amount": 50, "quantity": 1 } ] } ``` Two payment models are available. Pick the one that matches your integration. Paylead processes the payment page. 1. Call `POST /vouchers/orders/{order_id}/payments/webview` to get a `redirect_url`. 2. Redirect the Consumer to that payment webview. 3. When the Consumer returns, call `POST /vouchers/orders/{order_id}/payments/confirm`. The bank charges the Consumer on its own platform, then notifies Paylead with `POST /vouchers/orders/{order_id}/payments` once the payment has succeeded. Once payment is confirmed, the order moves to `READY` and the Vouchers are issued. A failed or abandoned payment leaves the order in `PAYMENT_FAILED` or `CANCELLED`. List the Consumer's Vouchers with `GET /vouchers`, fetch one with `GET /vouchers/{voucher_id}`, and download its file with `GET /vouchers/{voucher_id}/pdf`. Display the code, PIN, validity date, and Brand. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. ### Order states | Status | What it means | | ---------------- | ------------------------------------------------- | | `CREATED` | Order placed, payment not yet completed. | | `CONFIRMED` | Payment confirmed, Vouchers being issued. | | `READY` | Vouchers issued and ready to use. | | `PAYMENT_FAILED` | Payment did not go through. No Voucher is issued. | | `CANCELLED` | Order cancelled before completion. | ### What a Voucher carries | Field | Description | | ---------------------------- | --------------------------------------------------------------- | | `id` | Unique identifier of the Voucher. | | `order_id` | The order the Voucher was issued from. | | `status` | The order status the Voucher reflects. | | `brand` | The Brand the Voucher is redeemable at (identity, logo, color). | | `amount` | Face value of the Voucher. | | `valid_until` | Expiry date. | | `pin_code_1`, `pin_code_2` | PIN codes, when the Brand uses them. | | `card_number` | Voucher or gift card number. | | `card_url` | Link to the Brand's redemption page, when provided. | | `pdf_id` | Identifier of the downloadable Voucher file. | | `archived_at`, `refunded_at` | When the Voucher was archived or refunded, if applicable. | Let the Consumer tidy their wallet by archiving used or expired Vouchers with `POST /vouchers/{voucher_id}/archive`, and restore them with `POST /vouchers/{voucher_id}/unarchive`. ## What's next Track and display the Rewards a Cashback Offer generates. How a validated Reward reaches the Consumer's pool and gets paid out. React to Reward and Voucher events in real time. # The Offer catalog Source: https://docs.paylead.fr/program/user-journey/guides/work-with-offers What an Offer is, how it funds your Program, and how to fetch, filter, and display the catalog through the Paylead API. An [Offer](/glossary#offer) is the unit of value at the heart of Paylead: a published promotion that defines the conditions a [Consumer](/glossary#consumer) transaction must meet to earn a [Reward](/glossary#reward). It is **what the Consumer actually sees** in the bank app, and what funds your [Program](/glossary#program). This page covers what an Offer is, how it funds your Program, and how to surface the catalog through the [Paylead API](/program/user-journey/quickstart). ## From Campaign to Offer An Offer is never created in a vacuum. It is the published outcome of a Paylead proposal for a partner merchant that the [Program Manager](/glossary#program-manager) has reviewed and accepted. Paylead submits a [Campaign](/glossary#campaign): a raw, unpublished commercial proposal carrying its conditions: eligible [Brand](/glossary#brand), duration, [playground](/glossary#playground) range, channel, and targeting rules. The Program Manager reviews each Campaign in [Shift](/glossary#shift) and either publishes it as an Offer or rejects it. This is where the Program Manager sets how the [playground](/glossary#playground) is split between its own commission and the [Cashback](/glossary#cashback) returned to the Consumer. Once published, the Offer enters the Program catalog and starts surfacing to eligible Consumers. A **Campaign** is Paylead's draft proposal; an **Offer** is the curated, published promotion the Consumer sees. Only the Program Manager turns one into the other. ## How an Offer funds the Program Offers are not a cost: they are the revenue mechanism. When a Consumer transaction matches an active Offer (a [Commissioned Transaction](/glossary#commissioned-transaction)): * Paylead returns a [**playground**](/glossary#playground) to your Program for that transaction. * The playground splits (per Offer, as the Program Manager decided at publication) between the **Program Manager's commission** and the **Consumer's [Cashback](/glossary#cashback)**. This is why curating Offers is a Program Manager lever, not just a catalog task: each Offer's split shapes both Consumer value and Program economics. ## Offer types and states An Offer's `type` sets how the Consumer earns. It also tells you **which member of `perks` is populated**, so read `type` first and then the matching object. | `type` | What it is | Populated member | | ---------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------- | | `CASHBACK` | Rewards a share of each qualifying purchase, credited to the Consumer's [pool](/glossary#pool). | `perks.cashback` | | `LBS_CASHBACK` | Same mechanism, for an Offer published by a local merchant through [LBS](/glossary#lbs-local-business-solution). | `perks.cashback` | | `VOUCHER` | A [Voucher](/glossary#voucher) bought up front, below face value. | `perks.voucher` | | `UNIQUE_COUPON` | A coupon code issued to one Consumer. | `perks.coupon` | | `GENERIC_COUPON` | A single coupon code shared by every Consumer. | `perks.coupon` | A [Loyalty Offer](/glossary#loyalty-offer) is a `CASHBACK` Offer whose `perks.cashback.frequency` is `true`. Two states change how you render an Offer: | State | Field | What it means | | ------------ | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Boosted** | `perks.cashback.boosted` | The Cashback rate is currently above the Offer's default rate. Surface it as a badge next to the rate. | | **Consumed** | `is_consumed` | The Consumer already used the Offer: a claimed coupon, or Cashback earned up to the cap. Keep it visible in a dimmed "already claimed" state rather than hiding it. | A single Brand can publish multiple Offers to the same Consumer simultaneously, for example a default 3% Offer and a boosted 7% Offer. Aggregate them at the Brand level for the catalog index, and expand to individual Offers on tap. ## What an Offer carries Every Offer defines the terms a transaction must satisfy to be rewarded: * **Eligible Brand**: where the purchase must happen. * **A rate**: the share of the [playground](/glossary#playground) returned to the Consumer. * **Validity period**: the window during which the Offer is active. * **Channel**: the transactional channel through which the purchase is rewarded: online, in-store, or both. * **Specific conditions**: minimum and maximum amounts, capping, targeting. The payload nests every type-specific condition under `perks`. Read `type` first, then the matching member, where the rates and the eligibility amounts live. The Offer listing returns the validity window, the channel, the rate, and every eligibility condition. The detail call adds three fields on top, marked **Detail only** in the tables below: `description`, `legal_terms`, and `perks.cashback.loyalty_frequency`. **Top level** | Field | Description | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | Unique identifier of the Offer. | | `type` | Offer mechanism, see [Offer types and states](#offer-types-and-states). | | `brand` | The [Brand](/glossary#brand) the Offer belongs to: `id`, `name`, and `logo`. | | `picture` | The Offer's own illustration, distinct from `brand.logo`. `null` when the Offer carries none. | | `application_channel` | Where the Offer applies: `ONLINE`, `OFFLINE`, or `BOTH`. | | `highlight_level` | Editorial prominence for contextual displays such as banners or carousels: `HIGHEST`, `HIGH`, or `NORMAL`. An Offer with no prominence set is reported as `NORMAL`. | | `start_date` | When the Offer became available to this Consumer: the Offer's start date, or the date the Consumer was reached when that happened later. | | `end_date` | When the Offer stops being available, `null` when open-ended. For a Cashback Offer running through successive phases, the current phase's end date bounds this window. | | `is_consumed` | Whether this Consumer already used the Offer: a claimed coupon, or Cashback earned up to the cap. | | `perks` | Holds `cashback`, `voucher`, and `coupon`. Only the member matching `type` is set, the others are `null`. | | `description` | **Detail only.** Localized Offer description, resolved from the `Accept-Language` header. | | `legal_terms` | **Detail only.** Localized legal terms, with the date placeholders already substituted for the current window. | **`perks.cashback`** (`CASHBACK` and `LBS_CASHBACK` Offers) | Field | Description | | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `cashback_rate` | [Cashback](/glossary#cashback) rate as a percentage (`5.00` for 5%). | | `boosted` | Whether the rate is currently above the Offer's default rate. | | `frequency` | Boolean: whether the Offer rewards repeat purchases. | | `min_amount` | Transactions below this amount earn no Cashback. `null` when unbounded. | | `max_amount` | Caps the share of a transaction that earns Cashback: above it the Cashback stops growing, and the transaction stays eligible. `null` when unbounded. | | `max_eligible_amount` | Disqualifies the transaction: above it the purchase earns nothing at all. `null` when unbounded. | | `max_cashbacks_per_consumer` | How many Cashbacks this Consumer may earn on the Offer. `null` when unbounded. | | `loyalty_frequency` | **Detail only.** How many qualifying purchases the Consumer must make before earning the Cashback. | The two ceilings are distinct: `max_amount` bounds the reward, `max_eligible_amount` bounds eligibility. **`perks.voucher`** (`VOUCHER` Offers) | Field | Description | | --------------------------- | -------------------------------------------------------------------------------------- | | `discount_rate` | Consumer-facing [Voucher](/glossary#voucher) discount as a percentage. | | `min_amount` / `max_amount` | Lowest and highest purchasable Voucher amount. | | `amounts` | Fixed purchasable amounts. Empty when the Offer sells any amount in the min/max range. | | `amount_step` | Increment purchasable amounts must follow inside the min/max range. | | `validity_months` | How many months a purchased Voucher stays valid. | **`perks.coupon`** (`UNIQUE_COUPON` and `GENERIC_COUPON` Offers) | Field | Description | | ------------------ | --------------------------------------------------------------------------------------------------- | | `discount_rate` | Coupon discount as a percentage. `null` when the coupon carries a fixed amount instead. | | `discount_value` | Coupon discount as a fixed amount, in the Offer currency. | | `diffusion_type` | How the code is rendered to the Consumer: `QR`, `EAN` (barcode), or `CODE` (plain alphanumeric). | | `max_per_consumer` | How many coupons this Consumer may claim. `null` for a generic coupon, whose single code is shared. | ## Fetch the catalog The Paylead API exposes three entry points. Pick the one that matches your UI. Return one entry per Brand the Consumer is eligible for, with aggregated statistics. Use this for the catalog index screen. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. Each entry returns the Brand identity (`id`, `name`, `logo`, `universe`) plus two headline values: `max_rate`, the highest rate the Brand advertises across its Cashback and Voucher perks, and `max_highlight_level`, its highest prominence. For a Brand listed only through a coupon Offer, `max_rate` is `null` and `max_highlight_level` is `NORMAL`: the Brand aggregate covers Cashback and Vouchers only. Under `perks`, each perk the Brand carries reports its own `active_offers_count`: how many Offers of that type are currently active and visible to this Consumer, and therefore how many Offers the aggregate was computed over. It is always at least `1`, since a perk is only reported when such an Offer exists. **Filters**: `name`, `universe__name`, `perks__cashbacks`, `perks__vouchers`, `max_highlight_level`. Return every Offer the Consumer is eligible for, personalized by [Offer Smart Ranking](/glossary#offer-smart-ranking). **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. **Filters**: `brand_id`, `brand__name`, `universe__name`, `type`, `highlight_level`, `is_boosted`, `is_consumed`. * `brand_id=`: every Offer of one Brand. This is how you fill a Brand page, in a single call. * `is_consumed=false`: hide Offers the Consumer has already maxed out. * `is_boosted=true`: return only Offers with an active boost. **Sort**: `rate` or `start_date`, prefixed with `-` for descending. `rate` compares whichever rate the Offer advertises, so Offer types rank against each other; an Offer advertising no rate at all, such as a coupon carrying a fixed value, sorts last either way. Return one Offer with its `description`, `legal_terms`, and `perks.cashback.loyalty_frequency`. Everything else on the payload was already in the listing. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. Call this for the detail screen, where the legal terms are displayed. **Ordering.** The Offer listing is personalized. The Brand listing comes back in Brand-name order, and `sort` reorders it on `max_highlight_level` or `max_rate` (prefix `-` for descending). A "recommended Brands" surface passes an explicit `sort`, or is driven from the Offer listing. Every Offer detail display must show at minimum: the Brand logo, the application channel (online, in-store, or both), the legal terms, and the Cashback rate. Skipping any of these breaks the Paylead contract. `legal_terms` lives on the detail payloads, Offer detail and Brand detail. A list shows the logo, the channel, and the rate, and the Consumer reaches the legal terms on the detail screen before acting on the Offer. ## Personalization: Offer Smart Ranking Consumers do not see the catalog in a fixed order. [Offer Smart Ranking](/glossary#offer-smart-ranking) personalizes the order of Offers per Consumer, using purchase habits, location, Brand power, and editorial spotlight. It improves catalog relevance and conversion, and requires the Consumer's explicit consent to perform best. ## Display and filter behaviors Three behaviors shape how you render and filter the catalog. The underlying fields are listed in [What an Offer carries](#what-an-offer-carries). * **Boosted Offers**: `perks.cashback.boosted` marks an active boost, and `is_boosted=true` filters on it. Show a "Boosted" badge next to `cashback_rate`. * **[Loyalty Offers](/glossary#loyalty-offer)**: `perks.cashback.frequency` marks them, on the listing and on the detail. The number of qualifying purchases required, `loyalty_frequency`, comes with the detail payload. * **Consumed Offers**: flagged `is_consumed=true` once the per-Consumer cap is reached. Don't hide them. Display a dimmed "Already claimed" state, and use `is_consumed=false` only on dedicated "available now" screens. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. ## What's next Track Rewards generated when Consumers transact on an Offer. How a Consumer redeems an Offer to earn a Reward. Surface public Offers to prospects who are not Consumers yet. # Loyalty journey Source: https://docs.paylead.fr/program/user-journey/loyalty-journey Program × Product Manager: how the Loyalty domain links bank and loyalty accounts for Automatic Earn. **Integration not yet documented.** This page describes the Loyalty domain at a conceptual level. The integration guides (onboarding, account creation, Automatic Earn) are not published yet; **contact the Paylead teams** to scope a Loyalty integration. The [Perks](/glossary#perks) flow is the one the Paylead APIs implement today. [Loyalty](/glossary#loyalty) is the second domain of the Paylead [Embedded Loyalty](/program/user-journey/what-is-paylead) platform. Where [Perks](/glossary#perks) helps [Consumers](/glossary#consumer) save money on purchases, Loyalty centralizes and activates retailer loyalty inside the banking experience. The Loyalty domain is still under development, so public documentation is not available yet. Please ask your dedicated Customer Success manager to learn how to integrate Seamless Loyalty Card (SLC). ## Seamless Loyalty Card (SLC) Paylead has designed **Seamless Loyalty Card (SLC)**, allowing the Consumer to: * Create or link Loyalty accounts from the bank app. * Automatically earn Loyalty Rewards by using their payment method. This is **Automatic Earn**: no loyalty card (or any other authentication method like a client identifier) to present at checkout. The bank card is now the authentication method on the retailer side. * Access information about their connected Loyalty Programs. * Where applicable, convert their points into benefits: Burn the Loyalty balance. Most Programs mix both WebApp and API integration to create an enriched hybrid experience: native entry points for tight integration (such as the Consumer's connected Loyalty accounts list), with the [WebApp](/program/user-journey/concepts/web-app) handling richer flows. Complex flows such as Loyalty account creation or Brand Hubs are only available in Paylead's WebApp. ## The journey Like Perks, Loyalty sits on the shared [platform foundation](/program/user-journey/overview#the-platform-foundation): the [Consumer](/glossary#consumer) is already created at the platform level and their transactions are managed there. Unlike Perks, Loyalty does **not** rely on transaction-analysis consent or segmentation; those are Perks-specific. On top of that foundation, the Consumer opts in to the Loyalty service. From the bank app, the Consumer joins the Loyalty service. Opting in runs inside the Paylead [WebApp](/program/user-journey/concepts/web-app) and is reduced to accepting the Program's terms. With the Consumer opted in, available Loyalty Programs are surfaced inside your bank's Loyalty section. Loyalty Programs are curated by your team through the available catalog. The Consumer creates a new **retailer loyalty account** or links an existing one (one per Brand), binding it to their bank card. This step runs inside the [WebApp](/program/user-journey/concepts/web-app). To reduce friction, Paylead can pre-fill the form through [Frictionless account creation](#frictionless-account-creation). The Consumer pays with their bank card as their default payment instrument at a Loyalty Program eligible point of sale. No loyalty card or other authentication method is needed at checkout. Loyalty benefits accrue automatically to the linked account. This is Automatic Earn. Webhooks are available to the Program to animate and engage Consumers at the right moment, such as when a new Loyalty Reward is earned. The Consumer manages their loyalty account from the bank app, not from separate merchant apps. Once a Consumer has linked a loyalty account, they gain access to a dedicated **Brand Hub** within the bank app for each connected Loyalty Program. From this space, the Consumer can check their Loyalty balance and access additional services depending on the Loyalty Program's configuration. Depending on the type of Loyalty Program, Consumers have a Loyalty balance where earned Loyalty Rewards accumulate. They can then Burn their Loyalty Rewards by converting them to tangible merchandise or gifts. This part of the process also runs in the Paylead [WebApp](/program/user-journey/concepts/web-app). ## Frictionless account creation The Consumer is in a **known context**: they are already authenticated in their bank app, so the bank can pass that context to Paylead (Paylead only relays it). This lets Paylead **pre-fill the loyalty account creation form**. With the Consumer's prior consent, data already known from the banking context (such as first name, email address, or postal address) is automatically populated in the WebApp registration form. When pre-filling is enabled, account creation may require nothing more than reviewing pre-populated fields and accepting the program's terms and conditions. This feature is optional and must be configured at the Program level. It requires a dedicated consent step to be presented to the Consumer before their banking data is used in this way. When active, pre-filled forms significantly improve enrollment conversion rates and the quality of data received by the Merchant. Pre-filled does not mean locked: the Consumer can review and edit any personal information before validating. ## The WebApp is required The Paylead [WebApp](/program/user-journey/concepts/web-app) is **mandatory** on the loyalty account **creation and connection** journey. The bank delegates these flows to the WebApp rather than building them natively. ## What Loyalty drives for the bank * Differentiation: the banking experience tied to real-life Brands. * Stronger top-of-wallet behavior: Automatic Earn rewards paying with the bank card. * Higher engagement in a loyalty hub Consumers can use daily. ## Why Perks and Loyalty stay separate Perks and Loyalty are both loyalty, but not the same product: * **Perks** is primarily a *savings engine*: immediate, monetary, easy to grasp. * **Loyalty** is primarily a *relationship engine*: accounts, Brands, ongoing engagement. Keeping them distinct lets a Program design clearer UX, measure each funnel separately, and roll out progressively. ## What's next Event notifications Paylead pushes to your endpoints. Drive enrollment and engagement across your Consumer base. # User journey Source: https://docs.paylead.fr/program/user-journey/overview Program × Product Manager: how the Paylead integration works end to end. Paylead is an [Embedded Loyalty](/program/user-journey/what-is-paylead) platform built on two domains: [Perks](/glossary#perks) (savings on everyday spending, delivered through [Cashback](/glossary#cashback), vouchers, and bookings) and [Loyalty](/glossary#loyalty) (an embedded loyalty wallet). Each domain has its own Consumer journey. This page walks through both, from sign-up to payout. ## At a glance Both journeys start from the same Consumer, created at the platform level. The Consumer opts in to a domain, then shares their transactions, which determine how they earn and receive value. ```mermaid theme={null} flowchart TD A["Create Consumer (consumer_id)"] --> C{"Consumer opts in"} C -->|Perks| PB["Share transactions"] C -->|Loyalty| LB["Share transactions"] subgraph Perks["Perks journey"] direction TB PB --> P1["Discover targeted Offers"] P1 --> P2["Use the Offer"] P2 --> P3["Reward created"] P3 --> P4["Pool and Ventilation"] end subgraph Loyalty["Loyalty journey"] direction TB LB --> L1["Link retailer loyalty account"] L1 --> L2["Pay with bank card"] L2 --> L3["Automatic Earn"] end classDef neutral fill:#f1efe8,stroke:#888780,color:#2c2c2a classDef decision fill:#ffffff,stroke:#888780,color:#2c2c2a classDef primary fill:#e6f1fb,stroke:#0465ff,color:#042c53 classDef accent fill:#e1f5ee,stroke:#0f6e56,color:#04342c class A,PB,LB neutral class C decision class P1,P2,P3,P4 primary class L1,L2,L3 accent style Perks fill:transparent,stroke:#85b7eb,color:#185fa5 style Loyalty fill:transparent,stroke:#5dcaa5,color:#0f6e56 ``` ## The platform foundation Both journeys sit on a shared, **service-agnostic Consumer**. The bank first **creates the Consumer at the platform level**: a unique **`consumer_id`**, the single identifier for that end user **across your whole Program** (not one per account). A Consumer can link **one or several bank accounts** under that same identifier. The Consumer then **opts in to a service**: Perks, Loyalty, or both. Opting in is what unlocks that service's features. **Consent and segmentation, for example, belong to Perks**, not to the platform foundation. Once opted in, the bank **shares the Consumer's transactions at the platform level**: typically the last 12 months of history, then ongoing transactions. They are pushed once and reused by whichever service the Consumer joined. The `consumer_id` is the backbone of the integration. You reuse it to push transactions, authenticate the Consumer into the [WebApp](/program/user-journey/concepts/web-app), match incoming [Webhooks](/program/user-journey/concepts/webhooks), and (for support and operations) investigate a missing Reward or attribute a [Gift](/glossary#gift). ## The Perks journey In the Perks domain, every Perk is an [Offer](/glossary#offer): the [Consumer](/glossary#consumer) realizes a saving by **using** that Offer. Two things are common to every Perk: the saving for the Consumer, and the **targeting on transactional data**. Offers are matched and ranked from real spending habits, so each Consumer sees the ones that fit how they actually spend. What changes from one Perk to the next is the **Perk type**: how the Consumer uses the Offer, and how the saving reaches them: | Perk type | How the Consumer uses the Offer | How the saving is delivered | | ------------------------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Cashback by Paylead** | Pays at an eligible [Brand](/glossary#brand) (fully automatic: no code, no coupon, no activation, no card) | [Cashback](/glossary#cashback) credited to the [pool](/glossary#pool) (cagnotte), paid out via [Ventilation](/program/user-journey/concepts/ventilation) | | **Voucher** | Buys a voucher up front, below its face value | Saving built into the purchase price | | **Voucher as a cashback** | Buys the voucher at face value | Discount credited to the pool (cagnotte) | A [**Gift**](/glossary#gift) is the exception: a Reward the [Program Manager](/glossary#program-manager) grants directly, such as a welcome gift, a birthday reward, a special offer, or recognition for an action. It is neither purchase-driven nor targeted, but it is credited and paid out exactly like a Cashback (pool → Ventilation). The walkthrough below follows **Cashback by Paylead**, the fully automatic type. Every Perk type shares the first phases (opting in to Perks and targeted Offer discovery); they differ only in how the Consumer then uses the Offer. On top of the [platform foundation](#the-platform-foundation) (Consumer created), the Consumer **opts in to Perks** by consenting to Paylead using their banking data to receive matching Offers. Enrolling accepts the Program's terms and makes matching Offers available. The bank then shares the Consumer's transactions at the platform level. The Consumer can optionally grant the `SMART_RANKING` consent to enable [Offer Smart Ranking](/glossary#offer-smart-ranking), and the Program can optionally place them in [Segments](/glossary#segment) to scope which Offers they see. See the [Consumer lifecycle](/program/user-journey/guides/manage-consumers) for both flows. Once opted in and their transactions are shared, the Consumer is eligible to receive Offers, ranked from the platform transaction data via [Offer Smart Ranking](/glossary#offer-smart-ranking). With the Consumer enrolled and their history shared, available Offers are surfaced inside your bank's loyalty section. Your Program chooses **how** to render them: * **Native rendering**: your app fetches Offers from the API and displays them with your own components. * **Embedded WebApp**: you embed Paylead's white-label [WebApp](/program/user-journey/concepts/web-app), a Paylead-hosted webview customized to blend into your bank's UX via webview redirection. Paylead renders Offer discovery, Reward history, and (for the Loyalty domain) the wallet; your app only provides the container and authenticates the Consumer with their `consumer_id`. Most Programs mix both: native entry points for tight integration, with the WebApp handling the richer flows. Embedding the WebApp also means **getting Paylead's new features first**: improvements ship inside the WebApp ahead of the API surface. Either way, Offers are curated by your team in [Shift](/glossary#shift) and carry the merchant's conditions: eligible Brand, Reward terms, validity period, and channel (in-store, online, or both). Once Offers are surfaced, the Consumer **uses** them, and Paylead detects that usage to trigger the Reward. How usage is captured depends on the Perk type. In every case, a validated usage becomes a Reward. If the same purchase arrives from multiple sources (e.g. your core banking system and an account aggregator), the Reward Attribution engine prevents duplicate Rewards and selects the winning Program automatically. A matched transaction creates a Reward. For the **cashback-type** Perks (Cashback by Paylead, Voucher as a cashback, and Booking as a cashback), as well as for [**Gifts**](/glossary#gift), Paylead manages the Consumer's [pool](/glossary#pool) (the cagnotte). Once a Reward reaches `VALIDATED`, Paylead guarantees the payout. ## The Loyalty journey In the Loyalty domain, Paylead links the Consumer's bank account to their retailer loyalty accounts inside the banking experience. The Consumer earns Brand benefits automatically when they pay with their bank card. This is **Automatic Earn**: no loyalty card to present at checkout. Like Perks, Loyalty sits on the [platform foundation](#the-platform-foundation) (Consumer created), with transactions shared after opt-in. Unlike Perks, it does **not** rely on transaction-analysis consent or segmentation; those are Perks-specific. For the full Loyalty journey, see [Loyalty journey](/program/user-journey/loyalty-journey). On top of the [platform foundation](#the-platform-foundation), the Consumer **opts in to the Loyalty service** from the bank app. Opting in runs in the Paylead [WebApp](/program/user-journey/concepts/web-app) and is reduced to accepting the Program's terms; the form is pre-filled from the known banking context. Having joined the service, the Consumer creates or links a **retailer loyalty account** (one per Brand) from the bank app, binding it to their bank card. The Consumer pays with their bank card as their default payment instrument at a Loyalty Program eligible point of sale. No loyalty card or other authentication method is needed at checkout. Loyalty benefits accrue automatically to the linked account. This is Automatic Earn. Webhooks are available to the Program to animate and engage Consumers at the right moment, such as when a new Loyalty reward is earned. The Consumer manages their loyalty account from the bank app, not from separate merchant apps. Once a Consumer has linked a loyalty account, they gain access to a dedicated **Brand Hub** within the bank app for each connected Loyalty program. From this space, the Consumer can check their Loyalty balance and access additional services, depending on the Loyalty program's configuration. Depending on the type of Loyalty program, the Consumer has a Loyalty balance where earned Loyalty rewards accumulate. They can then Burn their Loyalty rewards by converting them into tangible merchandise or gifts. This part of the process also runs in the Paylead [WebApp](/program/user-journey/concepts/web-app). ## Key concepts The end user registered in your Program and eligible to earn Rewards. A published promotion tied to a Brand, a Cashback rate, and a validity period. What a Consumer earns after a transaction matches an Offer's terms. The payout process that distributes Cashback amounts to Consumer accounts. ## What's next Make your first authenticated API call in minutes. Get your credentials and authenticate against the Paylead API. See what changed in each API version. # Quickstart Source: https://docs.paylead.fr/program/user-journey/quickstart Make your first Paylead API call in under 15 minutes. Get an API key, pick an environment, and read a live response. Paylead powers bank-linked cashback. Your bank sends transactions, Paylead matches them against active [Offers](/glossary#offer), and your [Consumers](/glossary#consumer) earn [Rewards](/glossary#reward), with no codes, vouchers, or clicks. This page walks you from zero to a working API call. By the end, you have a valid bearer token, a chosen environment, and a verified response from the Paylead sandbox. ## Before you start You need: * A [Program Manager](/glossary#program-manager) account in [Shift](/glossary#shift). * A REST client (`curl`, Postman, or your language's HTTP library). * Five minutes to read, ten to copy-paste. ## Make your first call Sign in to the sandbox Shift () with your Program Manager account, then create an API client under **Settings > API Keys** (see [API keys](/program/shift/api-keys)). Copy the `client_secret` immediately; Paylead shows it once. Exchange the `client_id` and `client_secret` for a short-lived access token. See [Authentication](/program/user-journey/authentication) for the two-step flow. Use the sandbox for integration work. Switch to production only after Paylead validates your integration. | Environment | Base URL | | ----------- | -------- | | Sandbox | | | Production | | Replace `{programRef}` with your Program's identifier, issued by Paylead at onboarding. See [Environments](/program/user-journey/environments) for the full comparison. List the [Brands](/glossary#brand) available in your [Program](/glossary#program). Pass your access token as a bearer credential and set the mandatory `X-Api-Version` header (for example `2.0.0`). This is a safe read-only call that confirms your token works. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. A successful call returns `200 OK` and a JSON array of Brands. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. If you see `401 Unauthorized`, your token is wrong or expired. See [Errors](/program/user-journey/errors). You received a `200 OK` and a JSON payload. Your integration is connected to the Paylead sandbox. ## What's next Explore the deeper guides for your use case. Token format, header, and key rotation. Move from sandbox to production safely. HTTP codes, Paylead error codes, and remediation. # Rate limits & Caching Source: https://docs.paylead.fr/program/user-journey/rate-limits Paylead applies rate limits. Back off on 429, and cache safe reads. Paylead enforces rate limits. **Why this matters.** Hitting your Program's limit returns `429 Too Many Requests` and the call fails. A correct client treats `429` as expected back-pressure, backs off, and retries. ## Detecting throttling A throttled call returns HTTP `429 Too Many Requests`. Treat any `429` as the signal to back off, regardless of which headers are present. ## Back off correctly Retrying a `429` immediately makes the problem worse. Use exponential backoff with jitter, and honor `Retry-After` whenever the platform sets it. **Code examples coming soon.** The Paylead API (v2) is still under construction. Request and response examples for this section will be published once the contract is finalized. In the meantime, contact your Paylead account manager for early-access details. Always add jitter (a small random delay on top of the backoff). Without jitter, a fleet of clients retries in sync and re-hits the limit at the same moment. ## Cache safe reads Most read endpoints are stable for seconds to minutes. Some resources may be Consumer-specific, depending on how they're implemented and configured. We encourage caching them, but on a per-Consumer basis, to preserve these personalizations. | Endpoint | Suggested TTL | | ------------------------------------------------------------------ | ------------- | | [Consumer](/glossary#consumer) [Segments](/glossary#segment) | 5 minutes | | [Consumer](/glossary#consumer) [Voucher](/glossary#voucher) orders | 2 minutes | | [Consumer](/glossary#consumer) payment account | 1 minute | | [Consumer](/glossary#consumer) [Rewards](/glossary#reward) | 30 seconds | Never cache Webhook payloads; the platform delivers them once. See [Webhooks](/program/user-journey/concepts/webhooks). ## Avoid hitting the limit * **Batch where the API allows it.** Prefer one call returning 100 items over 100 calls returning 1. * **Subscribe to [Webhooks](/glossary#webhooks)** for state changes instead of polling. * **Spread cron jobs.** Schedule back-office jobs at random minutes inside the hour, not on the round minute. * **Talk to your account manager early.** If you expect a traffic spike (campaign launch, migration), request a temporary increase ahead of time. ## What's next Other HTTP error codes and how to remediate. Common integration questions, answered. # Security Source: https://docs.paylead.fr/program/user-journey/security How Paylead enforce security mechanisms to ensure safe use of its API. ## Security controls in place Paylead is implementing a subset of mechanisms to ensure safe implementation and use of its APIs. Paylead enforce use of cryptography with strong algorithms and parameters. * **In transit.** All API endpoints and Webhooks use TLS 1.2 or higher with secured ciphersuites. * **At rest.** Paylead encrypts stored data with industry-standard cryptography. Program Managers interact with Paylead either through the [Shift](/glossary#shift) web portal, or directly with the Paylead [API](/program/user-journey/quickstart). * Role-based access is enforced on Shift Portal. Refer to [Sign in and users](/program/shift/sign-in-and-users#manage-users) for more information on available roles. * When resources are requested through API, the application backend enforce authorization check prior to process the operation. While Paylead is implementing Single Sign-On (SSO) authentication for most of its web portals, password-based authentication may be used on the Shift portal (while not recommended). Minimal password requirement are enforced, as follow: * minimal lengh of 14 characters * at least 4 type of characters (uppercase, lowercase, digit, special) * password must not includes the username While Paylead APIs are stateless, mechanisms are implemented to control duration of validity of user sessions. * When authenticated with SSO, active session are handled by the IDP server and remains valid during 30 minutes. * In password-based authentication mode, all calls performed from the Shift web portal are authenticated with authorization http header. JWT bearer tokens remains valid during 8 hours. **NB:** *On SSO mode, the session duration may be updated upon request. Contact your Paylead account manager.* * APIs are filtered with a Web Application Firewall and [Rate limits](/program/user-journey/rate-limits) are implemented. * Security headers baseline is enforce on every API endpoints. Web interfaces enforce Content-Security-Policy as well. * The [Google Recaptcha](https://docs.cloud.google.com/recaptcha) solution is implemented on web interfaces with password-based authentication. [Webhooks](/program/user-journey/concepts/webhooks) carry an HMAC-SHA256 signature so your back-office can verify each event was emitted by Paylead. Each event also carries an `event_id` to enable idempotent processing on your side. ## Report a vulnerability At Paylead, we are eager to protect our customers data and ensure the security of our services at all times. We are deeply grateful to researchers and our community who report issues so that we can coordinate a fix and responsible disclosure. All reports are thoroughly investigated internally. If you would like to report a potential weakness, you can contact us at the following address: [vulnerabilities@paylead.fr](mailto:vulnerabilities@paylead.fr) You may encrypt your report to this list using the **GPG key** of Security team. Encryption using GPG is **NOT** required to make a disclosure. ``` -----BEGIN PGP PUBLIC KEY BLOCK----- mQINBGlBNlABEADjWb4lz5N7qAqKRdS72EFvuJ8+tiVz6L9J1TTCdPIQmZy+qaZD thp+i5LVAXcFNiK5h+qkZSGdpof0mShvQtaYCPRtMI+YjS+yvKh2VzjdAAPQnjEi fJMWGBCIhgTkMCt0iDF2Zm2P4F1ZLO0eSOw3qKhvHCSojfMhCYH+qFoRmXIGujQt lnbl9QUAlIIErmxylTiNGVylNUAqUEFBVYVeWc1oAteDkAtOYrghcw94ZxlSeR7x ZzPP7Yk0/SAFF2o8MqzWGL5wMZqqPMg2mxR91eDGKYSQzYtJ8u4H6uuwkXm/S264 Id7bsx95lChJozmkssRRtBW4KD2tKxNRBu+CHwWzc8p/ddCQn46+/vbJcUWSqJz2 AO3tFkrKqObGJdI8xgtjrt8tVzsQpytz2ldHO2PjQpLgak1sH+kx6AUc/cnLAzVu qkccdRujEimW6UxKEa3e2tPUoru4MrDDDvBxPwJovdvZyWnx+2V7yIMkrcsnEfwF JdALxDVaCEbyT5e9QrXSpj/sEj1j2ooo+9CXafcptm5jwY8o13yFey31tY63IPF3 Oj34gKueH+vTxuY82wRXoDC5wvZ9bKiCwI/hGK17FRnW86auu+ZXMnt83rHrj23T Ljn4MsqvrhsLoL+hvY7hMRt3TjORyphAKa0RQoN1IAuzkksmrcJPOryxLwARAQAB tCtQYXlsZWFkIFNlY3VyaXR5IFRlYW0gPHNlY3VyaXR5QHBheWxlYWQuZnI+iQJU BBMBCAA+FiEE0T34aTGjA/3yxnAjTsth9YkCwMMFAmlBNlACGwMFCQetrC0FCwkI BwIGFQoJCAsCBBYCAwECHgECF4AACgkQTsth9YkCwMPosA//SYdUFG4tj4gQk4ZX 4ymPz7JeF/XeIJLDzkVMIYNWgE+jEZP1FQKSPqyWctZMNipYal8Q+G5TJ0iJAIre gNZIYC668faz/4+yZD6a/or+rd+jVyN8BXW8vXvi4waWGDmlq1lt3MErdi1tVwLS RGGgL8EjBwhkNbo7o89doHBqx04mMQ3AaLso4ucd3x4/9hQ+y5/BLIzhRRsQQL07 JMGcCReM6pVjc+JQGdwgZlZuD1F2NbVJbm+1uB3DCv7bZZhCwHk+swBjrS4ky2Jn mV/I3VvrSG0Q9SyTHIbLRYVNwkiQR2AlaGPw/aeaExSAUgPbkqGaRguR81XQzDx4 tzWpQ2fk+WVfAYzM+K19qEV3bsZNpiN2GqF3u0Jiqs563K1qqP44yHfPxVYbTjqD o8kvelJVNmBu5rYiKBH7fUlsUYwg/yEfYv/TRacYhb3NMzspRdnn0yiwng9b9BhY lxeRKjK7y3klAafom3xrrLqGamj4zyxVK3rFrRYqJ9EQBOzZM+3XFUNk46/DawEv e8wGWLZbiEwpnA3m8Z226+AJTzlo5ysbQY/nGz2NIHISpqg/eUfVQPcwxX5gzUHr 3Ta6OXgsRboXZaqlRY7HUkaSdXpGId0xDnkAMy0aag7A6/8HZ2rUitCFVNqotWAJ kxbnxmMS7Z9QSEtnnYMIrpiLfXm5Ag0EaUE2UAEQAMQ9SDd9LLghxVftekuamIZC NJOjrMnh7gyxDjKzH1QK8U1sfVfFVisorHixfkNhiFNjWbUE5QSXH0UWIEp6KA2C lSyqv4tNcrUSzHIzGfLgVU+kZw7Ogdc4mA8b0cQ6M5ViUB9+4/9/2ltCew6JIl0w /wnfQzQvuOO+1X7ZMhLbLBjNY3j1OXprBdq9j7ge3qloyRQedrTIxK2+SE2NcmsY HHyXiudtVfNSPSX1vzxdbmQCYsIyiFjwRe4oMboJ6AobxjuQ6x0BzhtQTjYGI5T7 ljy7yYER7XI/pVQRCJk23OPuWh41jAV2X658Uk6NFr9yOaCXUdUwx1uWzwRC8gzt WczHVwGCNZl0AmdFE9dBBbEMJDm4VkuoaGu4CMIuVS7YDFX3K90oA8EcGmR4LAVe k+OoQuDaBovdcCkpNJi+9VYS+UFigNVaVMPbYirSWegz7ZG1TgpP5h3z/qo6q3wn 2Wc8WC2F/VbxTthetyMBFi+grrMojpGRzws8zgbda+PZu9SiCLl+T2vtZDuOHJda lEDa3CncqONwhNopoaWMob/FoGSbxs17M60JgePuKQ0ys0zCZxEdzD+RHbu+6d8g dg2nXM0o+xmteMduiMP4irzKJVHY7nNjH+UZ1uiDonI7v41rBEwk03Qh7yR4dLv7 wo6+1FMPwmC7LkcqFLuJABEBAAGJAjwEGAEIACYWIQTRPfhpMaMD/fLGcCNOy2H1 iQLAwwUCaUE2UAIbDAUJB62sLQAKCRBOy2H1iQLAwwmzD/0aYKKlumJYn8qaTatC tYKdGrTYSRIuQeswyhcgvlUOYB9qhdx31klB5VittFrO48mgABJQqtmRavwIMj09 vrEONu0kPrabdf90/c5rKowqHDrBIVVeOtmFvn2AM4WVTDdL5vCkLJFrW//pMCcI 2vEW2Qs6f/D316sBu5RG/xwjTTUTlmPNZbVL1aeCyqDJaSC/U1L0/87yfw0zNc9j I/y9J5fSPVrTDqDw2TZe/9QmWLH8KvJSQFFQmcHFXc1J/zhBFvdXFjDYEfDGGBVI qL9ROkIHwduUZuRvXNpmOvunaoxyZzUWCvQPO5vqdKFZtauZxq0EZi2O4TWkgcUn sxC5R6bFZuLU9QRsnfhRoWLrrQX6X68NXSRlF+OjKfp2c3yRvabMsvkfbvYrp3fR iAqqrB7yC58Afw8JRZLsgVYO29HvOjo7mNnOabxGf7UKmQhMEkxzBHNYCIYRvkry leMD0lhezPi208X/T6zMyYEP3QIbtm3wiSUBeJH8+rl9WXM7ZZnJIal+ey1Uqu0I gMGVgSZbDav5lHxme6i7zkB3eccY7Qj7MVxKXVfx7Mz5U+SOm7G2LyL3vXgab09p Ar9sX4eUd6vj+Dhnzj0KI93zOF/uOHpmPwMhU0ne6KwqdNMBmk5y+l1fht6JPLmW XBgyXarBYA86tOj5vzaWCuNALg== =TpIO -----END PGP PUBLIC KEY BLOCK----- ``` You should use this mailing-list if: * You think you discovered a potential security vulnerability in Paylead's APIs or services * You are unsure how a vulnerability affects Paylead's APIs or services * You think you discovered a vulnerability in another project that Paylead may depends on ## What's next Browse the Program API endpoints and download the OpenAPI specs. Embed the Paylead WebApp inside your bank mobile app. # Versioning Source: https://docs.paylead.fr/program/user-journey/versioning Paylead versions its API so that our services can keep evolving while your integration stays stable. New features ship in new versions, and you upgrade on your own schedule. Paylead recommends running the latest version to get new functionality and the best experience. **Why this matters.** The version policy tells you what can change without warning (backward-compatible minors) and what requires you to update your integration (major and core releases). ## Version number A version number has three parts, `x.y.z`: **X**: the **Core** version. **Y**: the **Major** version. **Z**: the **Minor** version. This is **not** standard Semantic Versioning. Minor releases (`z`) are always backward compatible; major (`y`) and core (`x`) releases are backward incompatible and may require you to update your code. ## Select a version The version is **not** part of the URL path. You select it with the mandatory **`X-Api-Version`** header on every call. **A call without this header is rejected.** ```http theme={null} X-Api-Version: 2.0.3 ``` The current production-grade version is the **Core 2** line; use it for any new integration. See [Environments](/program/user-journey/environments) for the base URLs and [Authentication](/program/user-journey/authentication) for the bearer token. ## What ships in each release ### Minor releases (`z`): backward compatible Safe to adopt without changing your code. A non-exhaustive list of changes that ship in a minor: | API element | Change event | | ------------- | ----------------------------------------------------------------------------------------------------------------------- | | Path | Adding an endpoint | | Request body | Adding an authentication method | | Request body | Adding an optional field | | Response body | Changing the functional behavior of a field (e.g. `is_consumed` meaning "has consumed" → "the Offer is fully consumed") | | Response body | Adding an attribute | | Response body | Removing an element from an enum | | Status code | Changing the status code of an existing query (e.g. `400` → `422`, `400` → `409`) | ### Major releases (`y`): backward incompatible Moving to a new major may require you to update your integration: | API element | Change event | | ----------------------- | ------------------------------------------------------------------- | | Path | Removing an endpoint | | Request body | Adding a required field (header, body property, or query parameter) | | Request body | Hardening validation of a property (`anyOf` / `oneOf` / `allOf`) | | Authentication | Deleting or updating an authentication method | | Request / Response body | Changing an attribute data type (e.g. `integer` → `float`) | | Response body | Renaming an attribute (e.g. `name` → `productName`) | | Response body | Removing an attribute | | Response body | Adding an element to an enum | | Status code | Changing a status code in the `2xx` range | ### Core releases (`x`): backward incompatible The deepest changes. Moving to a new core will require you to update your integration: | API element | Change event | | ------------- | --------------------------------------------------------- | | Request body | Changing the request format (e.g. XML → JSON) | | Response body | Changing the response format (e.g. XML → JSON) | | Global | A cross-cutting change (response envelope, pagination, …) | ## API lifecycle Each major version (`X.Y.*`) moves through the following statuses. Every minor follows the lifecycle of its major. | Status | Meaning | Duration | | -------------------------------- | ----------------------------------------------------------------------------------------------------- | -------------- | | **Experimental** | The definition may change at any time. You must explicitly request it via the `X-Api-Version` header. | Not applicable | | **Stable** | The definition is stable. | ≥ 6 months | | **Stable - pending deprecation** | Still stable, but the removal date is now fixed. | = 6 months | | **Deprecated** | Still available, but you should migrate. Requests no longer count toward performance metrics. | ≥ 12 months | | **Gone** | No longer available. Requests return `410 Gone`. | Not applicable | ## Deprecation timeline Paylead communicates every deprecation to your Program **by email**. You get **at least 6 months** to migrate to a newer version, with availability and performance maintained. A further **12 months** of availability follows, but performance is no longer guaranteed. On the removal date, requests targeting the version return `410 Gone`. Each deprecation notice states **what** is being deprecated (an entire core line such as `1.*.*`, or a major such as `1.2.*`) and **when** it takes effect. ## Webhooks Webhooks are **not** versioned; there is a single version. The `X-Api-Version` header does not apply to Webhook payloads. ## Older versions Versions before the current core (including the pre-platform per-component specs) are archived on the [Releases](/program/api/releases) page, where you can view the rendered reference or download the OpenAPI spec for each. ## What's next Every published version, with docs and OpenAPI downloads. Per-token request limits and backoff strategy. HTTP codes and Paylead error envelopes. # What is Paylead? Source: https://docs.paylead.fr/program/user-journey/what-is-paylead Embedded Loyalty platform for financial institutions. Paylead is an **Embedded Loyalty platform** for financial institutions. It helps banks and fintechs strengthen customer loyalty and grow payment-related revenues by embedding loyalty value directly inside the banking experience. Embedded Loyalty is not a single product. It's a platform composed of two distinct domains: Help customers *save money*: [Cashback](/glossary#cashback), vouchers, and complementary savings products. Help customers *earn and use brand loyalty* from their bank. Embedding loyalty accounts into the banking experience. The two domains can be launched independently, but are designed to reinforce each other under one cohesive [Program](/glossary#program) narrative. Both build on the **same platform foundation** (the bank creates the [Consumer](/glossary#consumer) and manages their transactions once, at the platform level), and the Consumer then **opts in to each domain separately**. Consent and segmentation belong to Perks; Loyalty only requires opting in to the service. ## Why Embedded Loyalty matters for a bank In retail banking, loyalty is won through habits: the app customers open every week, the card they use by default, the bank they choose as their primary account. Embedded Loyalty targets these habits by making everyday spending more rewarding: * **More app engagement**: customers return to see benefits, track earnings, and discover new value. * **More card preference**: customers choose the bank card more often because it is connected to tangible value. * **Higher primary bank adoption**: your bank becomes the default for daily purchases. * **Better revenue capture**: when share-of-wallet increases, so do economics linked to payments and cross-sell opportunities. ## Two domains, two user journeys **Perks** is about helping [Consumers](/glossary#consumer) save money on purchases. The journey varies depending on the product: [Cashback](/glossary#cashback), [Voucher](/glossary#voucher), or other savings mechanics. #### Automatic Cashback [Cashback](/glossary#cashback) earning is designed to be frictionless: no code, no voucher, no card switch. When customers pay with their bank card, Cashback is **automatic** and follows [Program](/glossary#program) rules: validity period, minimum spend, exclusions. Browse eligible [Offers](/glossary#offer) in the bank app. Pay as usual with the bank card. [Cashback](/glossary#cashback) credited automatically: no code, no manual step. Come back to track earnings and repeat. #### Easy Voucher [Vouchers](/glossary#voucher) leverage engagement and deliver high perceived value: Browse [Offers](/glossary#offer) in the bank app. Define the voucher value and purchase with a discount. The [Voucher](/glossary#voucher) is emitted automatically and accessible in the bank app. Use the voucher in store or online. The discount can be credited to the [Consumer](/glossary#consumer)'s Reward pool inside the bank app. #### Additional savings mechanics To widen coverage and match different customer preferences, Perks can also include: * **Travel / hotel reservations** * Other add-on benefits depending on the Program design #### What Perks drives for the bank * Frequent reasons to open the app * Increased card usage for everyday purchases * A value proposition customers understand immediately * Regular promotional activations to keep customers engaged **Loyalty** is about centralizing and activating retailer loyalty inside the banking experience. It follows a different journey: Opt in to the Loyalty service, then create or link a **retailer loyalty account** from within the bank app. Use the bank card as the default payment instrument. Earn loyalty benefits seamlessly. Manage loyalty from the bank app, not from separate merchant apps. A simple mental model: a **loyalty wallet embedded into the bank app**, designed to reduce fragmentation and make the bank experience the daily hub. #### What Loyalty drives for the bank * Differentiation: the banking experience tied to real-life brands * Stronger top-of-wallet behavior * Higher engagement in a loyalty hub customers can use daily *** ## Why Perks and Loyalty are separate Perks and Loyalty are two distinct products, both built on merchant-funded content to help financial institutions offer loyalty to their customers. * **Perks** is primarily a *savings engine*: immediate, monetary, easy to grasp * **Loyalty** is primarily a *relationship engine*: accounts, brands, ongoing engagement Keeping them as distinct domains helps financial institutions: * design clearer UX and messaging, * measure impact more accurately (different funnels, different KPIs), * roll out progressively without forcing a "big bang" [Program](/glossary#program). ## How Paylead fits into your ecosystem A typical setup: 1. **Your banking channels** surface Perks and/or Loyalty experiences to [Consumers](/glossary#consumer). 2. **Paylead orchestrates** [Program](/glossary#program) logic, integrations, eligibility, and Reward or loyalty flows, via APIs and/or white-label components depending on the chosen deployment. 3. **Merchant ecosystem** provides Consumer value (merchant-funded benefits depending on the model), enabling measurable, performance-driven programs. 4. **You iterate** using performance monitoring and optimization loops. ## Program performance Paylead also provides the operating model and tooling to help financial institutions run a Program that performs over time: * [Program](/glossary#program) setup and rollout support * Performance monitoring and optimization loops * [Offer](/glossary#offer) strategy support: assortment, freshness, personalization levers depending on model * Continuous improvement of activation and repeat usage ## What's next Walk through the end-to-end [Consumer](/glossary#consumer) lifecycle and the [Reward](/glossary#reward) payout flow. Make your first API call and explore the three API roles. Understand the Paylead API security baseline. # Authentication Source: https://docs.paylead.fr/program/webapp/authentication Program × Developer: SSO integration between your bank app and the Paylead WebApp (MFP). The goal is a smooth SSO integration between your bank app and the Paylead WebApp, ensuring: * correct cookie and session handling between the WebView and the IdPs, * no spurious redirects to the authentication screen, * and silent re-authentication as long as the IdP sessions are valid. ## Authentication flow architecture ### Actors The end-user interface. The Paylead Identity Provider. Manages the WebApp session (the Paylead session cookie). Authenticates the bank user. OIDC delegation flows from the Partner IdP to the Paylead IdP. The Consumer URL for your Program is provided by your Paylead contact, and differs per environment: `https://consumer-.sandbox.paylead.tech` in sandbox, `https://consumer-.paylead.eu` in production. The examples below use the production host. See [Page URLs](/program/webapp/page-urls) for both. ### Flow at a glance The user opens the WebApp from the partner app. The WebApp queries the Paylead IdP. The Paylead IdP redirects to the Partner IdP if needed. The Partner IdP authenticates the user. The Paylead IdP creates a Paylead session and redirects back to the WebApp. The WebApp opens for the user with an active session. ```mermaid theme={null} %%{init: {'themeVariables': {'actorBorder':'#0465ff','signalColor':'#378add'}}}%% sequenceDiagram autonumber participant U as User (bank app) participant A as Bank application participant W as Paylead WebApp
consumer-.paylead.eu participant K as Paylead IdP participant L as Partner IdP U->>A: Opens the Paylead WebApp A->>W: GET https://consumer-.paylead.eu W-->>K: Redirect to /auth (Paylead IdP SSO) K-->>L: OIDC delegation to the Partner IdP L->>L: Authenticates the user L-->>K: Returns authorization_code K-->>W: Creates Paylead session + redirects to the WebApp W-->>A: Serves the authenticated Paylead WebApp A-->>U: User sees their Cashback space with no auth screen ``` ## Session management ### Session types | Level | IdP | Lifetime | Impact | | ----------- | ----------- | ------------------------------- | ------------------------------ | | Paylead SSO | Paylead IdP | 30 min idle / 10h max (default) | Manages the SSO authentication | | Partner IdP | Partner | Variable | Authenticates the bank user | ### Recommended durations * **Paylead IdP** (configurable): * SSO Session Idle: 30 min * SSO Session Max: 10h * **Partner IdP**: must be **≥** the Paylead IdP session to avoid showing the authentication screen after a redirect to `/authorize`. The idle session timer counts from the moment the session stops being active, not from the moment it was created. ### Expected behaviour by session state | Paylead IdP session | Partner IdP session | Result | | ------------------- | ------------------- | ------------------------ | | ✅ Valid | ✅ Valid | Direct access | | ⚙️ Expired | ✅ Valid | Silent re-authentication | | ⚠️ Expired | ⚠️ Expired | Partner IdP auth screen | | ⚠️ Valid | ⚠️ Expired | Partner IdP auth screen | | ❌ Cookies lost | n/a | Redirect to `/auth` | ## Access check & re-authentication ### Step 1: Pre-check before opening Before opening the WebApp, perform a `GET` **without automatically following redirects**: ```http theme={null} GET https://consumer-.paylead.eu ``` Expected handling: * If the response is **2xx** → the session is considered valid, **open the WebApp directly**. * If the response is a **3xx redirect** and the `Location` header points to **`/auth`** (the Paylead IdP auth route) → **start the full SSO flow** (Step 2). The response of this `GET` is also useful for what follows, as it carries: * **`state`**: lets you send the user back to the page they originally requested. * **`nonce`**: lets you bind the session to the token we create. ### Step 2: Web authentication Follow all redirects present in the `Location` header. Keep every cookie (`Set-Cookie`) received at each step. Check that the last redirect contains `scope`, `state`, `nonce`, `client_id` and `redirect_uri`. Otherwise, clear the cookies for the Paylead domain and retry once. Generate the `authorization_code` via the custom Paylead IdP plugin. ```http theme={null} redirect_uri?code=&state= ``` Perform a `GET` on this callback, following redirects and storing cookies. Open the WebApp with the updated cookies. ## What's next Cookie and WebView setup required for the flow above to work reliably. Diagnose a recurring auth screen, lost cookies, or hard-to-trace behaviour. # Mobile Bridge Source: https://docs.paylead.fr/program/webapp/bridge/overview Program × Developer: how the Paylead WebApp (MFP) calls native iOS/Android capabilities from inside your WebView. The **Mobile Bridge** lets the Paylead WebApp (MFP) running inside your native WebView invoke native device capabilities: opening a URL in the system browser, writing to the clipboard, downloading a file. It uses the **JSON-RPC 2.0** protocol over `postMessage`. Your native app receives requests from the WebApp and responds by calling back into JavaScript. ```mermaid theme={null} %%{init: {'themeVariables': {'actorBorder':'#0465ff','signalColor':'#378add'}}}%% sequenceDiagram participant W as Paylead WebApp
(WebView) participant N as Native app W->>N: postMessage({ jsonrpc, method, params, id }) Note right of N: Validate envelope
Validate params
Execute action alt Success N-->>W: response({ jsonrpc, result: {}, id }) Note left of W: Promise resolves else Failure (invalid params,
permission denied, runtime error…) N-->>W: response({ jsonrpc, error: { code, message }, id }) Note left of W: Promise rejects
with error.code else No response within timeout
(5s / 30s for file.download) Note left of W: Promise rejects
with timeout error end ``` The bridge JavaScript is versioned (`v1`, `v2`, …). The machine-readable contract for each version is published as a `schema.json`. See the [Methods](#methods) reference below for the current version, and the [Versions & download](/program/webapp/bridge/releases) page to download a schema or browse older versions. ## Transport The WebApp communicates with your native app through the `postMessage` API. Your native app is responsible for exposing this channel at the exact location where the WebApp expects to find it. The location depends on the platform: **The inbound channel name is `PayleadBridge` (capital P, capital B), identical across iOS, Android, Flutter, React Native, and any other platform your app targets.** This casing is part of the contract and is not negotiable. If your app registers a single shared channel name for multiple platforms (common in Flutter and React Native), use this exact casing everywhere, not one platform's convention on one side and a different one on the other. A mismatch fails **silently**: on the platform where the casing doesn't match, the WebApp never reaches your native handler, every bridge call falls back to standard web APIs instead, and nothing surfaces an error. The bug can go unnoticed until a partner reports missing native behaviour. **WebApp → Native** The `PayleadBridge` channel must be exposed to `window.webkit.messageHandlers.PayleadBridge`. Once the channel is registered, the WebApp sends messages to your app by calling `postMessage` on it. For example, on iOS: ```js WebApp theme={null} window.webkit.messageHandlers.PayleadBridge.postMessage(msg) ``` You never call this yourself: the WebApp does it internally. Your app only needs to (1) register the channel at the expected location and (2) handle the incoming payloads. WKWebView auto-deserializes the JSON, so your handler receives a `[String: Any]` dictionary. **Native → WebApp** Call back with argument binding; never interpolate the JSON into the source. ```swift Native theme={null} webView.callAsyncJavaScript( "window.payleadBridge.response(jsonString)", arguments: ["jsonString": jsonStr], ... ) ``` **WebApp → Native** The `PayleadBridge` channel must be exposed to `window.PayleadBridge`. Once the channel is registered, the WebApp sends messages to your app by calling `postMessage` on it. For example, on Android: ```js WebApp theme={null} window.PayleadBridge.postMessage(JSON.stringify(msg)) ``` You never call this yourself: the WebApp does it internally. Your app only needs to (1) register the channel at the expected location and (2) handle the incoming payloads. Android's `@JavascriptInterface` only accepts primitives, so you parse the JSON string yourself. **Native → WebApp** Quote the payload with `JSONObject.quote()`; never interpolate the JSON into the source. ```kotlin Native theme={null} webView.evaluateJavascript( "window.payleadBridge.response(" + JSONObject.quote(jsonStr) + ")", null ) ``` **WebApp → Native** The `PayleadBridge` channel must be exposed to `window.PayleadBridge`, matching the name of the `JavascriptChannel` you register with `webview_flutter`. Once the channel is registered, the WebApp sends messages to your app by calling `postMessage` on it. For example, on Flutter: ```js WebApp theme={null} window.PayleadBridge.postMessage(JSON.stringify(msg)) ``` You never call this yourself: the WebApp does it internally. Your app only needs to (1) register the channel at the expected location and (2) handle the incoming payloads in `onMessageReceived`. Like Android, a `JavascriptChannel` only accepts a string, so you parse the JSON yourself. **Native → WebApp** Dispatch through the live `WebViewController`; never interpolate the JSON into the source. Encode the payload with `dart:convert` and escape it before building the JS string literal. ```dart Native theme={null} final jsonStr = jsonEncode(response); final escaped = jsonStr.replaceAll('\\', '\\\\').replaceAll("'", "\\'"); await controller.runJavaScript("window.payleadBridge.response('$escaped');"); ``` **Never interpolate JSON strings into JavaScript source.** Use argument binding (`callAsyncJavaScript` on iOS), `JSONObject.quote()` (Android), or a careful `dart:convert` encode-and-escape (Flutter). Direct interpolation such as `"response('${json}')"` creates a JS injection vector. This rule applies every time you call back into the WebApp. Separately, `window.payleadBridge` (lowercase) is the WebApp's own object, registered automatically and used only to call back with `.response(...)`. Never read from or write to it from native code. ## Message format ### Request (WebApp → Native) Your handler receives JSON-RPC 2.0 request objects: ```json theme={null} { "jsonrpc": "2.0", "method": "browser.open", "params": { "url": "https://example.com" }, "id": "89d89a45-4f57-4e68-9f61-dc71434b2f26" } ``` ### Success response (Native → WebApp) Call `window.payleadBridge.response(jsonString)` with a serialized JSON-RPC 2.0 result: ```json theme={null} { "jsonrpc": "2.0", "result": {}, "id": "89d89a45-4f57-4e68-9f61-dc71434b2f26" } ``` ### Error response (Native → WebApp) If the action fails, respond with a JSON-RPC 2.0 error (see [Error codes](#error-codes)): ```json theme={null} { "jsonrpc": "2.0", "error": { "code": -32000, "message": "Download failed" }, "id": "89d89a45-4f57-4e68-9f61-dc71434b2f26" } ``` ### Envelope constraints * **`jsonrpc` must equal `"2.0"`.** Reject any other value with error code `-32600`. If the envelope cannot be parsed at all, respond with `"id": null` and error code `-32600`. * **`id` must be a UUID v4 string.** The WebApp always sends a randomly generated UUID v4; non-string ids are silently dropped by the WebApp. * **The `id` in the response must match the `id` from the request.** * **`result` and `error` are mutually exclusive.** On success include `result` and omit `error`; on failure include `error` and omit `result`. If the WebApp receives both, `error` takes precedence and the call rejects. * **Timeouts.** The WebApp rejects requests that don't receive a response within **5 seconds** for `browser.open` and `clipboard.write`, and **30 seconds** for `file.download`. For `file.download`, respond once the download has been *triggered* (consent granted, transfer started), not once it completes. ## Methods ### `browser.open` Opens a URL in the device's native browser (outside the WebView). URL to open. Must use the https\:// scheme. Pattern `^https://` · max length 2048 ```json Request theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} { "jsonrpc": "2.0", "method": "browser.open", "params": { "url": "https://www.paylead.fr" }, "id": 1 } ``` ```json Response theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} { "jsonrpc": "2.0", "result": {}, "id": 1 } ``` ### `clipboard.write` Copies text to the device clipboard. Text to copy to clipboard. max length 4096 ```json Request theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} { "jsonrpc": "2.0", "method": "clipboard.write", "params": { "text": "voucher:89d89a45-4f57-4e68-9f61-dc71434b2f26" }, "id": 1 } ``` ```json Response theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} { "jsonrpc": "2.0", "result": {}, "id": 1 } ``` ### `file.download` Downloads a file and presents it to the user. URL of the file to download. Must use the https\:// scheme. Pattern `^https://` · max length 200 Suggested filename. Allowed characters: letters, digits, underscore, hyphen, dot. Must start with a letter or digit. The native app must still sanitise before writing to disk. Pattern `^[a-zA-Z0-9][a-zA-Z0-9_\-.]*$` · max length 255 MIME type hint (e.g. application/pdf). one of `application/pdf`, `text/csv`, `image/jpeg`, `image/jpg`, `image/png` ```json Request theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} { "jsonrpc": "2.0", "method": "file.download", "params": { "url": "https://api.paylead.fr/voucher/89d89a45-4f57-4e68-9f61-dc71434b2f26.pdf", "filename": "89d89a45-4f57-4e68-9f61-dc71434b2f26.pdf", "mimeType": "application/pdf" }, "id": 1 } ``` ```json Response theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} theme={null} { "jsonrpc": "2.0", "result": {}, "id": 1 } ``` ## Error codes When a method fails, the native app responds with a JSON-RPC 2.0 error object carrying one of these codes in `error.code`. `error.message` must never contain stack traces, filesystem paths, or other sensitive information. | Code | Description | | -------- | ----------------------------------------------------------------------------------------------------------------------- | | `-32600` | Invalid JSON-RPC 2.0 request | | `-32601` | Method not found | | `-32602` | Invalid or missing params | | `-32000` | Runtime error (scheme blocked, download failed, etc.) — error.message must not contain stack traces or filesystem paths | | `-32001` | Permission denied (location, etc.) — error.message must not contain stack traces or filesystem paths | ## Integration guide Register a `WKScriptMessageHandler` named **`PayleadBridge`**. Receive JSON-RPC requests in `userContentController(_:didReceive:)`. Execute the action and call back with `callAsyncJavaScript` using named argument binding. ```swift theme={null} let config = WKWebViewConfiguration() config.userContentController.add(self, name: "PayleadBridge") // Recommended (iOS 14+): restrict navigation to your app's domains config.limitsNavigationsToAppBoundDomains = true // Hosts allowed to reach the bridge: any sub-domain of paylead.fr / .tech / .eu let allowedHost = #"\.paylead\.(fr|tech|eu)$"# func userContentController(_ controller: WKUserContentController, didReceive message: WKScriptMessage) { // Reject messages from sub-frames or unknown origins guard message.frameInfo.isMainFrame, let host = message.frameInfo.request.url?.host, host.range(of: allowedHost, options: .regularExpression) != nil else { return } guard message.name == "PayleadBridge", let body = message.body as? [String: Any], let jsonrpc = body["jsonrpc"] as? String, jsonrpc == "2.0", let method = body["method"] as? String, let id = body["id"] as? String else { return } let params = body["params"] as? [String: Any] ?? [:] // Validate params against the method's JSON Schema (schema.json). // On failure respond with error code -32602 (Invalid params). guard validateParams(method: method, params: params) else { return } handleBridgeMethod(method, params: params) { result in let response: [String: Any] = ["jsonrpc": "2.0", "result": result, "id": id] guard let data = try? JSONSerialization.data(withJSONObject: response), let jsonStr = String(data: data, encoding: .utf8) else { return } // Safe: jsonStr is passed as a named argument, no interpolation into JS webView.callAsyncJavaScript( "window.payleadBridge.response(jsonString)", arguments: ["jsonString": jsonStr], in: nil, in: .defaultClient, completionHandler: nil ) } } ``` * Check `message.frameInfo.isMainFrame` and verify the host against your allowlist before processing any message. Cross-origin iframes inside the WebView otherwise share access to `window.webkit.messageHandlers.PayleadBridge`. * Use `limitsNavigationsToAppBoundDomains = true` and declare your domains under `WKAppBoundDomains` in `Info.plist` (iOS 14+). * Block navigations to hosts outside your allowlist in `decidePolicyFor`. Android's `addJavascriptInterface` only takes effect on the next page load and, once registered, is exposed to **every frame** until removed and reloaded. The safest approach is to **block navigations to untrusted origins entirely**, register the interface once, and re-check the origin on every call as defense in depth. ```kotlin theme={null} // Hosts allowed to reach the bridge: any sub-domain of paylead.fr / .tech / .eu val allowedHost = Regex("""\.paylead\.(fr|tech|eu)$""") webView.addJavascriptInterface(PayleadBridgeInterface(webView), "PayleadBridge") webView.webViewClient = object : WebViewClient() { override fun shouldOverrideUrlLoading( view: WebView, request: WebResourceRequest ): Boolean { val host = request.url.host ?: return true return !allowedHost.containsMatchIn(host) // true = navigation blocked } } class PayleadBridgeInterface(private val webView: WebView) { @JavascriptInterface fun postMessage(json: String) { webView.post { // Defense in depth: re-check the current URL on every call val host = Uri.parse(webView.url).host ?: return@post if (!allowedHost.containsMatchIn(host)) return@post val request = try { JSONObject(json) } catch (_: Exception) { return@post } if (request.optString("jsonrpc") != "2.0") return@post val method = request.optString("method").ifEmpty { return@post } val id = request.optString("id").ifEmpty { return@post } val params = request.optJSONObject("params") ?: JSONObject() // Validate params against the method's JSON Schema (schema.json). // On failure respond with error code -32602 (Invalid params). if (!validateParams(method, params)) return@post handleBridgeMethod(method, params) { result -> val response = JSONObject().apply { put("jsonrpc", "2.0"); put("result", result); put("id", id) } webView.post { // Safe: JSONObject.quote() properly escapes the JSON string webView.evaluateJavascript( "window.payleadBridge.response(${JSONObject.quote(response.toString())})", null ) } } } } } ``` * Block navigations outside your allowlist in `shouldOverrideUrlLoading`. Removing the interface in `onPageStarted`/`onPageFinished` does **not** take effect until the next reload. * Re-check the current URL from inside `postMessage` itself. * Disable file access: `setAllowFileAccess(false)`, `setAllowFileAccessFromFileURLs(false)`, `setAllowUniversalAccessFromFileURLs(false)`, `setAllowContentAccess(false)`. * Enforce HTTPS only: `setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW)`. `webview_flutter`'s `JavascriptChannel` maps directly onto the native bridge: register a channel named **`PayleadBridge`** and dispatch responses through the `WebViewController` that's actually attached to the on-screen `WebViewWidget`. ```dart theme={null} final controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..addJavaScriptChannel( 'PayleadBridge', onMessageReceived: (JavaScriptMessage message) => _handlePostMessage(message.message), ); Future _dispatch(Map response) async { final jsonStr = jsonEncode(response); // dart:convert — never manual string concatenation final escaped = jsonStr.replaceAll('\\', '\\\\').replaceAll("'", "\\'"); // `controller` here must be the live controller — see warning below await controller.runJavaScript("window.payleadBridge.response('$escaped');"); } ``` * **Dispatch through the exact same `WebViewController` instance currently attached to the visible `WebViewWidget`.** Hold it in a `late final` field set once (typically in `initState()`); never recreate it on rebuild, read it from a stale closure, or instantiate a second, throwaway controller elsewhere. * Unlike a native iOS/Android WebView, whose lifetime is tied directly to its owning view controller or activity, a `WebViewController` lives inside ordinary widget/state lifecycle, so it's easy to end up holding a reference that no longer matches the WebView actually on screen. * Get this wrong and the failure is **silent**: `runJavaScript()` on a stale controller completes without throwing, no error surfaces anywhere, and the real page's pending promise times out after 5 seconds with zero console output. ## Security checklist for partners Before shipping your integration, verify each item: * [ ] **HTTPS only:** every URL received from the bridge is validated to start with `https://` before opening or downloading. `javascript:`, `data:`, `file:`, and `intent://` schemes are explicitly rejected. * [ ] **Filename sanitisation:** the schema restricts filenames to a safe character set (`^[a-zA-Z0-9][a-zA-Z0-9_\-.]*$`); as defense in depth, the native app re-validates and strips null bytes / OS-reserved names before writing to disk. * [ ] **Origin allowlist:** the bridge is only reachable from pages whose host matches your trusted allowlist (`*.paylead.fr`, `*.paylead.tech`, `*.paylead.eu`). Navigations outside the allowlist are blocked. * [ ] **User consent:** `file.download` triggers a native prompt so the user can confirm or cancel. * [ ] **App-bound domains** (iOS 14+): `limitsNavigationsToAppBoundDomains = true` and `WKAppBoundDomains` are configured in `Info.plist`. ## General recommendations * **Back/forward gestures:** disable `allowsBackForwardNavigationGestures` (iOS) and handle the back button explicitly (Android) to avoid accidental off-domain navigations. * **Loading indicators:** `file.download` can take up to 30 seconds; surface progress in your native UI. * **Correlation logging:** when logging bridge errors natively, include the request `id` so failures can be cross-referenced with the WebApp's client-side logs. ## What's next The WebApp URLs your app can open to land on a specific screen. Diagnose a recurring auth screen, lost cookies, or hard-to-trace behaviour. # Versions & download Source: https://docs.paylead.fr/program/webapp/bridge/releases Browse every published version of the Paylead Mobile Bridge and download its JSON Schema. The Mobile Bridge JavaScript is versioned (`v1`, `v2`, …). Each version ships a machine-readable **JSON Schema** describing every method, its parameters and the error codes, which are the source of truth for the [Methods](/program/webapp/bridge/overview#methods) reference. For each version you can preview the rendered reference in this site, or download the raw `schema.json` to compile into your own JSON Schema validator (AJV, networknt/json-schema-validator, JSONSchema.swift, …) and validate incoming `params` on the native side. ### v1 — **Latest** * [View documentation](/program/webapp/bridge/overview#methods) * [Download schema.json](/program/webapp/bridge/schema/v1/schema.json) # WebView configuration Source: https://docs.paylead.fr/program/webapp/configuration Program × Developer: WebView setup and opening URL parameters for embedding the Paylead WebApp (MFP). Correct cookie and WebView configuration is what keeps the [SSO flow](/program/webapp/authentication) working without showing the authentication screen on every open. ### Golden rule All steps of the flow (pre-check, authentication, callback, opening) must run in **the same WebView**, with **the same cookie jar**. ### A native WebView is required The WebApp runs in a native WebView: `WKWebView` on iOS, `WebView` on Android, `` in Electron. The Consumer origin authenticates server-side, and the Paylead identity provider it redirects to serves its pages as a top-level document, which is what a native WebView provides. The [Troubleshooting](/program/webapp/troubleshooting) page covers the symptom an HTML `