# Loybox Documentation > Loybox is a loyalty platform for brands: each brand builds its own membership > club, where members earn points on every purchase and redeem them for rewards, > with VIP tiers, referrals, reviews, recommendations and campaigns. This file is the full text of the entire documentation IN ENGLISH, in the order it is organized in: the product guides first, the API reference after. Each page opens with a `#` followed by its URL. The same docs in Spanish (Argentina): https://docs.loybox.com.ar/llms-full.txt The same docs in Spanish (Latin America): https://docs.loybox.com.ar/es-419/llms-full.txt Page index and API summary: https://docs.loybox.com.ar/en/llms.txt API specification to generate a client from: https://docs.loybox.com.ar/openapi.json --- # Introduction (https://docs.loybox.com.ar/en/introduccion) Ads bring customers in. Loyalty brings them back. **Loybox is the platform to build your own membership club**: an app with your branding for brick-and-mortar stores, or built into your online store, to reward your members, drive repeat purchases and grow the value of every relationship. ## The problem it solves Acquiring a customer is only the first step. Real profitability shows up when that customer comes back, spends more and brings someone else. Without a loyalty system, you depend on paying again and again to bring in the same customer profile. ## How it works, in one sentence Your members earn points on every purchase and redeem them for your brand's exclusive rewards. Around that, Loybox adds VIP tiers, challenges, referrals, campaigns and community, so buying becomes a habit. ## Your club, across every channel ## Where to start This documentation grows tool by tool. Start with the fundamentals: # Concepts (https://docs.loybox.com.ar/en/conceptos) Before configuring your club it helps to have the vocabulary straight. All of Loybox is built on four pieces. ## The pieces ## The loyalty cycle The heart of Loybox is a simple cycle that repeats and reinforces itself on every visit: ### The member buys In your store or in your online store. Every purchase is recorded as a consumption. ### They earn points The consumption generates points automatically, following the rules you define (see [Earning points](https://docs.loybox.com.ar/puntos-y-premios/ganar-puntos)). ### They redeem rewards Once they have enough points, they trade them for one of the rewards in your catalog. ### They come back The reward, and the progress toward the next one, brings them back. Buying becomes a habit. ## Point balance A member's balance is the result of adding up every point they earned (that has not expired) and subtracting everything they spent on redemptions. That guarantees the number is always consistent with their real history. ## Multichannel One brand can run its club in brick-and-mortar stores (a PWA app with your branding) and in its online store (wired into the checkout). The point rules and the reward catalog are shared: the member gets a single experience, no matter where they buy. # Fundamentals (https://docs.loybox.com.ar/en/puntos-y-premios) The points and rewards system is the engine of your club: members earn points on every purchase and redeem them for your brand's rewards. It is the mechanic that turns a one-off purchase into a relationship that comes back. ## At a glance ## The flow, end to end ### You configure the rules You define how many points each purchase is worth and (optionally) when they expire. ### You build the reward catalog You create rewards with their cost in points, redemption cap and validity. ### The member accumulates Every purchase adds points to their balance automatically. ### The member redeems They trade their points for a reward and your team validates it with a code. Each brand defines its own point rules, its expiration modes and its reward catalog. Nothing is fixed: the system adapts to how you want to reward your members. # Earning points (https://docs.loybox.com.ar/en/puntos-y-premios/ganar-puntos) Every purchase generates points automatically. How the purchase amount translates into points is up to you. ## The main rule: money per point The most direct way to configure your program is to define how much money one point is worth. With that rule, the calculation is: ``` points = floor( purchase amount ÷ money per point ) ``` If you set 100 = 1 point, a purchase of 1,750 earns 17 points (1750 ÷ 100 = 17.5, rounded down). The leftover cents are not lost: in practice they carry into the next purchase, because the calculation always runs on the real amount. It is a single value to tune: lower the "money per point" so points pile up faster, or raise it so they cost more. ## Automatic per-currency conversion If you do not define a money-per-point rule, Loybox uses a default conversion based on your brand's currency, so everything works from day one: | Currency | Default rule | | -------------------- | ------------------------------------------------------------------------- | | Euro (EUR) | 50 points per € | | Mexican peso (MXN) | 1 point per 50 MXN | | Every other currency | The amount is converted to dollars (MEP rate) and earns 50 points per USD | The MEP dollar rate updates automatically on a regular basis, so the currencies that depend on it always use an up-to-date value. As soon as you define your own "money per point" rule, this conversion stops applying. ## Multipliers On top of the base calculation, two adjustments can increase the points of a purchase: The base point is calculated first (following your money-per-point rule or the per-currency conversion), then double points are applied if they are active, and last the percentage bonus of the member's tier. The tier bonus applies according to the tier the member holds at the time of the purchase. ## Other ways to earn points Purchases are the main source, but not the only one. Loybox can also award points for: # Point expiration (https://docs.loybox.com.ar/en/puntos-y-premios/expiracion) Point expiration is a tool to create urgency: a balance that expires is a reason to come back before losing it. Loybox lets you choose how it works, or turn it off entirely. ## The three modes ## The expiration period When you turn expiration on, you define a period in days. The points of a purchase expire once that period has passed since they were earned. Expiration only applies if the mode is "rolling" or "per transaction" and the period in days is greater than zero. With the period at zero, points do not expire even if the mode is active. ## Rolling vs. per transaction The key difference is what happens when the member buys again: Rolling rewards consistency and is friendlier: only someone who leaves for good loses points. Per transaction pushes members to redeem often. If you are just starting and do not want friction, begin with no expiration and add a rule later. ## How the member sees it Expired points simply stop counting toward the balance: they are not "deleted" from the history, they just are not added when calculating how many points the member has available. That way, the balance they see is always the balance they can use. # Rewards (https://docs.loybox.com.ar/en/puntos-y-premios/premios) Rewards are what your members get in exchange for points. Your catalog is what makes accumulating worth it: the more desirable it is, the stronger the incentive to come back. The reward catalog in the Loybox dashboard Follow the step-by-step guide: [Create a reward](https://docs.loybox.com.ar/puntos-y-premios/crear-un-premio). ## What you configure in a reward Every reward is defined with a handful of fields: There is no need to write a title or a description: the text the member sees is generated automatically from the type and value you choose. Fewer fields, less friction. ## Reward types A reward can deliver different things: ## A reward's state At any moment, a reward sits in one of these states, based on its configuration: | State | What it means | | ------------ | ------------------------------------ | | **Active** | Available to redeem. | | **Inactive** | Paused manually from the catalog. | | **Expired** | Its expiration date has passed. | | **Sold out** | It reached its total redemption cap. | Only active rewards (valid, with redemptions left and not paused) show up for members to redeem. ## Rewards for special occasions Beyond the general catalog, you can reserve rewards for specific moments in the member's journey: # Create a reward (https://docs.loybox.com.ar/en/puntos-y-premios/crear-un-premio) Creating a reward takes less than a minute. In this guide we do it end to end from the dashboard. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. Everything else on this page is in English. The New reward modal in the Loybox dashboard ## Step by step ### Go to **Premios** (Rewards) In the sidebar, under **Fidelización** (Loyalty), tap **Premios**. You will see your **Catálogo de premios** (reward catalog). ### Tap **Nuevo premio** (New reward) The button sits at the top right of the catalog. A window opens to build the reward. (If you do not have any yet, the button reads **Crear premio**, "Create reward".) ### Pick the **Tipo de premio** (reward type) In the **Tipo de premio** dropdown, choose what the member will get: | Type | What it delivers | | -------------------------------------------------- | ---------------------------------------- | | **Producto gratis** (free product) | A product from your catalog, at no cost. | | **Vale de dinero ($)** (money voucher) | A fixed discount amount. | | **Descuento porcentual (%)** (percentage discount) | A percentage off. | | **2x1** (2-for-1) | A two-for-one promotion. | | **Envío gratis** (free shipping) | Shipping at no cost. | | **Otro** (other) | Any benefit you define as free text. | ### Fill in the reward's value A different field appears depending on the type: * **Vale de dinero** → **Monto del vale ($)**, the voucher amount (for example, `10.000`). * **Descuento porcentual** → **Porcentaje de descuento**, the percentage (1 to 100\). * **Producto gratis**, **2x1** or **Otro** → a **Detalle** (detail) field to describe it, up to 40 characters. * **Envío gratis** → needs no value. On the types with an amount or a percentage you can add a **Detalle (opcional)** to fine-tune the text the member reads (for example, "on your next purchase"). ### Upload an image *(optional)* Under **Imagen del premio (opcional)** you can upload a photo (PNG, JPG or WEBP, up to 5 MB). If you do not upload one, Loybox uses an icon based on the reward type. ### Set the **Precio (puntos)** (price in points) This is how many points it costs to redeem the reward. It is required and has to be greater than zero: until you fill it in, the save button stays disabled. ### Adjust the limits *(optional)* * **Límite de canjes (opcional)** (redemption cap): how many times it can be redeemed in total. Leave it at `0` for unlimited. * **Vencimiento (opcional)** (expiration): the date until which it is available. * **Otras restricciones (opcional)** (other restrictions): a free-text note (for example, "Cannot be combined with other promotions"). ### Check the **Vista previa** (preview) Off to one side you will see a **Vista previa** showing the reward exactly as the member will see it in their app, updating as you fill in the fields. ### Tap **Crear premio** (Create reward) That is it: the reward is saved and shows up in your **Catálogo de premios**, available for redemption. You can create as many as you want. ## Two things worth knowing There is no name field and no description field. The reward's title and text are generated automatically from the type and value you choose, and you can see them in the preview. There is no "active" toggle when creating. Whether a reward is available, sold out or expired follows from its configuration (price, redemption cap and expiration). You can see each reward's state in the catalog. ## If you have Tiendanube connected If your Tiendanube store is connected, creating a reward shows a **Cupón Tiendanube** (Tiendanube coupon) toggle. Turning it on makes the reward generate a real coupon in your store when the member redeems it, and you pick the **Tipo de cupón** (coupon type: percentage discount, fixed amount, free shipping or free product) and, where it applies, the **Categoría** (category) it covers. With the Tiendanube coupon enabled, the reward uses the coupon's configuration instead of the free-form image and detail. It is the ideal option for the redemption to apply on its own at your online store's checkout. # Redemption (https://docs.loybox.com.ar/en/puntos-y-premios/canje) Redemption is the moment points turn into real value for the member. Loybox handles it end to end: it deducts the points, hands over the reward and gives your team a simple way to validate it. ## The flow, step by step ### The member picks a reward From the app they see the catalog of available rewards and how much each one costs in points. ### Loybox checks the balance The redemption only goes through if the member has enough points to cover the reward's cost. If they fall short, they are told how many they are missing. ### The points are deducted On confirmation, the redemption is recorded and the reward's cost is subtracted from the balance. The member ends up with the reward in their name and a validation code. ### Your team validates the code In the store (or at your online store's checkout), your team enters the code to confirm the reward and mark it as used. ## The validation code Every redeemed reward carries a short, unique code that the member presents when using it. The code is bound to your brand and to that specific redemption. Your team looks it up, confirms it is still pending and marks it as used. Once used, it cannot be validated again: that prevents the same reward from being used twice. ## Redemption and balance Remember that a member's balance is computed: it is always the sum of live earned points minus redeemed ones. That is why, the moment a redemption is recorded, the balance drops consistently, with no manual adjustments. ## Validity of a redeemed reward A redeemed reward keeps the original reward's validity date: the member has it reserved, but has to use it before it expires. That keeps the catalog healthy and avoids "eternal" rewards piling up unused. # Fundamentals (https://docs.loybox.com.ar/en/niveles) Tiers are how you recognize your best members: as they spend, they move from one tier to the next and unlock better benefits. It is a way of rewarding sustained loyalty, beyond any single purchase. The Tiers section in the Loybox dashboard ## What a tier is A tier is a step inside your club. As the member spends, they move up from one tier to the next and unlock better benefits. Every tier has: ## The base tier Every member who joins your club enters the base tier (the first step, with no requirements). From there they start climbing. The base tier always exists and never expires: it is everyone's starting point. ## How it works, at a glance ### The member joins They enter the base tier automatically. ### They accumulate and move up Every purchase counts toward the next tier's threshold. On reaching it, they move up. ### They unlock benefits Each tier improves what they get: more points per purchase, exclusive rewards and recognition. ### They keep their status As long as they stay active, they hold (and keep climbing) their tier. Beyond the value of the benefits, reaching a tier works as an achievement: holding it and climbing further is a concrete reason for the member to return. # How members move up (https://docs.loybox.com.ar/en/niveles/como-suben-de-nivel) Every tier has a threshold: what the member needs to accumulate to reach it. You choose what that threshold is measured in. ## Two ways to measure progress Each tier is measured by its own criterion, so you can mix both within the same ladder if that makes sense for your brand. ## It is measured over the full history This is the key point: progress is calculated over what the member accumulated across their entire relationship with your brand, not over their current balance. When a member spends their points on a reward, their balance drops, but their tier does not. The tier reflects everything they earned or spent lifetime, so redeeming never sets them back. They can enjoy their rewards without fear of losing their status. ## How the tier is calculated After each purchase, Loybox reviews the member's history and places them in the highest tier whose threshold they already reached. If that purchase crossed the next step's threshold, they move up right away. A higher tier can never have a lower threshold than one below it. The ladder goes from less demanding to more, so moving up always means real progress. # Benefits of each tier (https://docs.loybox.com.ar/en/niveles/beneficios-de-nivel) Every tier can improve what the member gets in three ways. ## Points multiplier Each tier can award an extra percentage of points on every purchase. It is the most noticeable reward, because it accelerates everything else. The multiplier is a percentage bonus: 0% = no bonus, 10% = +10%, 100% = double points. A "Gold" member with +20% who makes a 100-point purchase takes home 120. It applies according to the tier the member holds at the time of the purchase, and only while that tier is active. It is a concrete reason to climb: the higher the tier, the faster the balance grows. ## Reward on reaching the tier You can award a welcome reward every time a member moves up a tier: a push of points, an exclusive benefit, a gift. This is the member's moment of greatest enthusiasm, and it is worth acknowledging. A tier's welcome reward is given once per member, the first time they reach it. Even if they later drop and climb back up, it does not repeat. ## Rewards exclusive to the tier Beyond the arrival reward, a tier can have rewards that only the members in it enjoy: ## Beyond points A tier does not have to be built on more points alone. You can also add benefits that do not depend on a discount: A good practice is to use the points multiplier to accelerate accumulation, and the exclusive benefits to make each tier feel different from the previous one. That way progress shows up both in the balance and in the experience. # Expiration and demotion (https://docs.loybox.com.ar/en/niveles/vencimiento-de-niveles) A tier can be forever, or something that has to be maintained. Both options are valid; they serve different purposes. ## Tiers that are maintained You can give a tier a validity in days. If the member reaches it and then goes inactive for that period, they drop one step. That way the tier is held through activity, instead of being kept forever after reaching it once. When a tier expires, the member does not fall all the way down: they drop a single tier, and the clock restarts from there. Demotion is gradual and always leaves room to react. ## Climbing back up is possible Demotion answers to inactivity, not to a permanent punishment. Since progress is calculated over the member's full history, if they buy again and their lifetime total still clears the higher tier, they move back up on the next purchase. In practice, expiration only "bites" the members who left for good. ## Where it applies Expiration only makes sense on the VIP tiers (the ones above the base) measured by points. The base tier, everyone's starting point, never expires: nobody is pushed out of the club through inactivity. ## When it is worth it Too short a period can make a member lose their tier over a normal pause between purchases. It is better to start with a generous window and tune it against your members' real purchase frequency. # Design your tiers (https://docs.loybox.com.ar/en/niveles/armar-tus-niveles) Designing your tiers means defining your club's ladder: how many there are, what it takes to move up and what each one offers. There is no single formula, but there are good practices. This is the guide. ## The steps ### Define the base tier It is the entry step, with no requirements: everyone starts there. It carries no threshold and no expiration. ### Add your VIP tiers Create the steps above it. For most brands, three to four tiers in total is the sweet spot: enough to give a sense of progress, without getting confusing. ### Choose how each one is measured Decide whether the threshold is accumulated points or amount spent, and the value to reach. Remember: each higher tier has to ask for more than the one below. ### Load in the benefits For each tier, define the points multiplier, the reward on arrival and the exclusive rewards. Every step should feel better than the last. ### Give it a name and an icon The name communicates status (Silver, Gold, Platinum… or something of your own) and the icon makes it visible in the app. ## Rules worth keeping in mind ## Your own tiers, or Loybox's You can use a tier ladder of your own, designed to fit your brand, or start from Loybox's default configuration to get going quickly. When you define your own tiers, your brand uses that full ladder instead of the default one. A descriptive name reads better than a generic one: "Gold" says more than "Tier 3". Pick a progression that is clear and easy to remember. ## One piece of advice to start You do not need to launch with the perfect ladder. Start with two or three clear tiers, with genuinely desirable benefits, and adjust over time based on how your real members move between steps. Follow the step-by-step guide: [Create a tier](https://docs.loybox.com.ar/niveles/crear-un-nivel). # Create a tier (https://docs.loybox.com.ar/en/niveles/crear-un-nivel) Tiers are built like a ladder: the base tier first, then the tiers above it. In this guide we create one end to end from the dashboard. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. The New tier modal in the Loybox dashboard ## Step by step ### Go to **Niveles** (Tiers) In the sidebar, under **Fidelización** (Loyalty), tap **Niveles**. ### Tap **Nuevo nivel** (New tier) A window opens to configure the tier. If you do not have any yet, start with the base tier (for example, *Bronce*, "Bronze"): it is every member's starting point. ### Set the **Nombre** (name) The name the member sees, for example *Oro* ("Gold"). ### Pick an **Ícono** (icon) Search for and select an icon for the tier. It is the visual badge shown in the app. ### Choose the **Métrica** (metric) How progress toward the tier is measured: * **Puntos** (points): by accumulated points. * **Monto ($)** (amount): by amount spent. ### Define the **Umbral** (threshold) How much the member needs to accumulate to reach the tier (in points or in money, depending on the metric). The base tier has no threshold and no expiration: it is the entry step, so these fields do not appear when configuring it. ### Adjust the **Expiración (días)** (expiration in days) *(optional)* If you want the tier to be held through activity, enter in how many days it expires. Leave it empty for a tier that never expires. ### Load in the tier's **Premios** (rewards) You can combine as many as you want: * **Multiplicador (%)** (multiplier): the extra percentage of points per purchase (0 = no bonus, 10 = +10%, 100 = double). * **Puntos de regalo** (gift points): points awarded once, on reaching the tier for the first time. * **Premios del catálogo** (catalog rewards): existing rewards handed over on reaching the tier. ### Tap **Crear nivel** (Create tier) The tier is saved and appears in your tier ladder. ## Ordering the tiers In the list, drag the tiers to reorder them. The first one is always the base tier, and from there up the thresholds have to go from lower to higher. ## Three things worth knowing Points or amount is a choice for the whole ladder, not for a single tier. If you change the metric, it applies to every tier and the thresholds reset to zero: review them before saving. A tier's exclusive rewards (on arrival, or by event, such as a birthday) are loaded once the tier is saved. Create the tier first, then edit it to add them. You do not need to launch with the full ladder. The base tier plus two or three above it is enough to get going; you can always add more and reorder. # Fundamentals (https://docs.loybox.com.ar/en/referidos) Referrals are how your own members invite new people into your club. When an invitee makes their first purchase, both the referrer and the invitee earn points. It is an acquisition channel where your members make the recommendation for you, and the reward is only paid out once that recommendation turns into a real purchase. ## How it works ### You turn the program on You define how many points are awarded per successful referral. ### Each member shares their link From their app, every member has their own invitation link to share with whoever they want. ### A new member joins The invited person opens the link and joins your club. ### Both earn points When that invitee makes their first purchase, the points are credited to both: the referrer and the invitee. ## The referral points You configure a single value: the same points go to the referrer and to the invitee. They are credited once, on the invitee's first purchase (not on sign-up), so the reward always comes with a real sale. ## The rules For a referral to count, Loybox checks a few conditions: # Turn on referrals (https://docs.loybox.com.ar/en/referidos/activar-referidos) Turning on referrals takes less than a minute. It is configured from the **Premios** (Rewards) page, alongside the rest of the automatic rewards. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. The invite-a-friend reward settings in the Loybox dashboard ## Step by step ### Go to **Premios** (Rewards) In the sidebar, under **Fidelización** (Loyalty), tap **Premios**. ### Scroll to **Premios especiales** (Special rewards) Below the catalog you will find the **Premios especiales** section, with the automatic rewards. ### On **Invitar amigos** (Invite friends), tap **Configurar** (Configure) It is the box that reads *"Cuando un amigo invitado compra por primera vez, ambos ganan puntos"* ("When an invited friend buys for the first time, both earn points"). If you have not configured it yet, it shows as **Sin configurar** ("Not configured"). ### Define the **Puntos para cada uno** (points for each) Enter how many points each referral earns. That same value goes to the referrer and to the invitee, when the invitee makes their first purchase. ### Tap **Guardar** (Save) That is it: the program is live and your members start earning points for inviting. ## Editing or turning it off The value you enter is the same for both sides: the referrer's points and the invitee's points are not configured separately. # Fundamentals (https://docs.loybox.com.ar/en/resenas) Reviews are how Loybox asks your members, automatically and over WhatsApp, to leave a review after buying. The point is to collect social proof: Google reviews of your business and reviews of your products. Reviews lean on your online store's orders: the request fires when a purchase is delivered. That is why the tool requires your store to be connected. ## The types of review ## How the request works ### The member receives their purchase The review request is tied to the delivery of an order from your store. ### Loybox waits the delay you defined You configure how many hours to wait from delivery (for example, 24 = one day after receiving the order). ### The request goes out over WhatsApp The member gets the message to review your business and/or the products they bought. ### The member replies They leave their review: on Google, in your own system, or by answering the WhatsApp with stars and a comment (native reviews). ## The native review When you use Loybox's native reviews, the member rates 1 to 5 stars and can leave an optional comment, all inside the WhatsApp conversation. Loybox stores those reviews and marks them as verified, because they come from a real purchase. ## No spam: the repeat window So your members do not get worn out, Loybox does not ask for the same review over and over: # Configure reviews (https://docs.loybox.com.ar/en/resenas/configurar-resenas) Configuring reviews is a matter of turning on what you want to use. Changes save themselves as you make them. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. The **Reseñas** (Reviews) section requires your online store to be connected, because review requests fire on the delivery of each purchase. The Reviews section in the Loybox dashboard ## Business reviews (Google) ### Go to **Reseñas** (Reviews) In the sidebar, tap **Reseñas**. ### Turn on **Pedir reseña en Google** (Ask for a Google review) With the toggle on, after each purchase the member is invited to leave a Google review of your business. ### Connect your Google listing Search for and select your business. Until you pick it, Loybox cannot send the review request. ### Adjust the **Demora del envío (horas)** (send delay in hours) How many hours to wait from delivery before asking for the review (for example, `24` = one day later). ## Product reviews ### Turn on **Pedir reseña de productos** (Ask for product reviews) With this on, the member is asked to review the products they bought. ### Choose the **Tipo de reseña** (review type) ### Adjust the **Demora del envío (horas)** (send delay in hours) Same as with Google: how long to wait from delivery before asking. ### If you picked **External**, load the links In the **Links de reseña por producto** (per-product review links) section, look up each product and paste its review link. That is what Loybox will send the member. There is no save button: every change (toggles, review type, delay) applies instantly. You can preview how the WhatsApp reaches the member under **Así le llega al cliente** ("How the member sees it"). # Fundamentals (https://docs.loybox.com.ar/en/recomendaciones) Recommendations are how Loybox suggests relevant products to each member in your online store, using AI. Instead of building rules product by product, the system learns from your catalog and from purchase behavior to show the right product at the right moment. Recommendations run on your connected online store: they show up on its pages (cart, product page, checkout) and go out over WhatsApp. ## The types of recommendation ## Where they appear You choose which points of the store show them: ## Recommendations over WhatsApp Beyond the store, recommendations can arrive over WhatsApp at two moments: ## How the impact is measured Loybox attributes the sales that come from a recommendation: if the member buys within the attribution window after seeing a suggestion, that sale counts as generated by recommendations. That is how you see the tool's real return. ## What you need to configure Very little: the AI does the work of choosing what to show. You decide whether it is on, where it appears and which notifications go out. # Configure recommendations (https://docs.loybox.com.ar/en/recomendaciones/configurar-recomendaciones) The settings are organized in three tabs: **General**, **Ubicaciones** (Placements) and **Notificaciones** (Notifications). Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. The **Recomendaciones** (Recommendations) section requires your online store to be connected. ## General ### Go to **Recomendaciones** (Recommendations) In the sidebar, tap **Recomendaciones**. ### Turn on **Recomendaciones activas** (Recommendations active) This enables the recommendation system across the store. ### Adjust **Upsell: % máximo más caro** (upsell: max % pricier) When an upgrade is suggested, how much pricier than the base product it may be. For example, `50%` suggests products up to 50% more expensive. ## Placements In the **Ubicaciones** tab you choose which points of the store show recommendations: ## Notifications In the **Notificaciones** tab you configure the WhatsApp sends: ### Post-purchase recommendation Turn it on so that, after a purchase, the member gets products that go with what they bought. Set the **Demora post-compra (horas)** (post-purchase delay in hours) so it is not intrusive. ### Win-back for inactive members Turn it on to send recommendations to members who stopped buying. Set the **Días para considerar inactivo** (days before counting as inactive) from which it applies. ### Attribution window (hours) If the member buys within this window after seeing a recommendation, that sale is attributed to the tool. This is what lets you measure the impact. ## Saving When you are done, tap **Guardar configuración** (Save settings). The changes apply to your store. # Fundamentals (https://docs.loybox.com.ar/en/carrito) The cart tools work on the moment of purchase in your online store, with two goals: recovering the purchases that were left halfway, and pushing the order value with amount-based rewards. Both tools require your online store to be connected. ## Two tools ## When to use each one # Recover abandoned carts (https://docs.loybox.com.ar/en/carrito/recuperar-carritos) When a member leaves products in the cart and does not buy, Loybox can send them WhatsApp reminders to recover that sale. Here is how to set it up. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. ## Step by step ### Go to **Carrito** (Cart) In the sidebar, tap **Carrito**. At the top you will see **Carrito abandonado** (Abandoned cart). ### Turn on the **Recordatorios** (reminders) Switch on **Recordatorios activos** (reminders active). With this, if a member abandons their cart, a reminder reaches them over WhatsApp. ### Define the send times In **Recordatorios (horas desde el abandono)** (reminders, hours since abandonment) you enter how many hours after abandoning the cart each reminder goes out. You can set several: for example, `1, 24, 72` = after an hour, after a day and after 3 days. ### Add a coupon *(optional)* If you want to give an extra incentive, add a discount coupon (a percentage of the total or a fixed amount) and set its validity in hours. ### Save The changes apply and the reminders start going out. Reminders travel over WhatsApp, so you need WhatsApp Business connected under Integrations. Two or three is enough. The first one, early (after an hour or after a day), is usually the most effective; the ones after it serve to re-engage whoever did not answer, without becoming annoying. # Cart rewards (https://docs.loybox.com.ar/en/carrito/recompensas-en-carrito) Cart rewards are rules that unlock a gift when the purchase passes an amount. They exist to push the order value: "you are close to your gift". Here is how to create a rule. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. ## Step by step ### Go to **Carrito** (Cart) In the sidebar, tap **Carrito**. Scroll down to the rewards section. ### Tap **Nueva regla** (New rule) A window opens to configure the rule. ### Set a **Nombre** (name) So you can identify it in your dashboard. For example, *Gift from 20,000 up*. ### Define the **Monto mínimo del carrito** (minimum cart amount) The subtotal from which the reward unlocks. ### Choose the **Tipo de recompensa** (reward type) Depending on the type, you fill in the product or the discount value. ### Write the **Mensaje al cliente** (message to the member) This is what they see in the store when the reward unlocks (for example, "Your gift is unlocked!"). Optionally you can define the discount's text at checkout. ### Leave it **Activa** (active) and tap **Crear regla** (Create rule) Only active rules apply in the store. You can have several. Set the minimum a little above your average order value: high enough for the member to add one more product, but reachable enough to be worth trying. # Fundamentals (https://docs.loybox.com.ar/en/segmentacion) Segmentation automatically groups your members by their purchase patterns, so you know who is who in your base and can act differently with each group. Loybox builds the segments for you: there are no rules to define by hand. Segmentation is calculated over the orders of your connected online store. ## How it is built: the RFM model Every member is classified by three signals of their purchase behavior: Combining these three signals, Loybox places each member in a segment with a persona and an insight that explain who they are and what to do about it. ## The segments The segments follow the RFM standard. Some of the most common ones: | Segment | Who they are | | -------------------------------------------- | ------------------------------------------------------------- | | **Champions** | Your best members: they buy often, recently, and spend a lot. | | **Leales** (Loyal) | Regular, consistent members. | | **Leales en potencia** (Potential loyalists) | Recent buyers with good pace, on their way to loyal. | | **Necesitan atención** (Need attention) | Good members who started spacing out their purchases. | | **En riesgo** (At risk) | They used to buy and are drifting away. | | **Hibernando** (Hibernating) | They have not bought in a while. | | **Perdidos** (Lost) | They stopped buying a long time ago. | The segment names are the ones the dashboard and the API return, in Spanish. The English in parentheses is here so you can read the table, not a name you will see on screen. Each segment shows its RFM rule, how many members it groups, its weight in your base and in your sales, and averages for recency, frequency and order value. ## Plus: your business's health The dashboard also summarizes the overall state of your base with key metrics: # Using your segments (https://docs.loybox.com.ar/en/segmentacion/usar-tus-segmentos) Segmentation is not just a diagnosis: it exists so you can act differently with each group of members. Here is how to use the dashboard. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. ## Step by step ### Go to **Segmentación** (Segmentation) In the sidebar, tap **Segmentación**. ### Review your business's health At the top you will see the overall diagnosis and the KPIs (active members, orders, average order value, repeat rate and the top 20% concentration). ### Explore each segment Each segment is shown as a card with its persona, its insight, how many members it groups, its averages (recency, frequency, order value) and the RFM rule that defines it. ### Look at a segment's members Open a segment to see the list of members in it. You can sort it by higher or lower amount spent, more or fewer purchases, and by purchase date (oldest or most recent). ### Act with a campaign From a segment you can launch a WhatsApp campaign aimed at that group, so you speak differently to each type of member. To create WhatsApp campaigns you need WhatsApp Business connected under Integrations. ## How to think about each segment The point is to treat each group according to what it needs: Segmentation is recalculated on a regular basis, so the groups stay up to date as your members' habits change. # Fundamentals (https://docs.loybox.com.ar/en/campanas) Campaigns let you send a message to a group of members over WhatsApp or email. They lean on [segmentation](https://docs.loybox.com.ar/segmentacion): instead of writing to your whole base, you speak differently to each group based on its behavior. A campaign's starting point is a segment: they are launched from a segment's detail view under **Segmentación** (Segmentation). That way the audience is defined by purchase behavior. ## How it works ### You choose the audience A segment (for example, *En riesgo*, at risk) or an individual member. ### You choose the channel WhatsApp or email, depending on how you want to reach them. ### You write the message With personalization variables such as `{{first_name}}`, so each member receives it with their own name. ### You schedule or send You pick a date and time, or send it right away. ### You follow the results Every campaign shows its state and its metrics. ## A campaign's states | State | What it means | | -------------------------- | ---------------------------------- | | **Borrador** (Draft) | In preparation, not sent yet. | | **Programada** (Scheduled) | With a send date and time set. | | **Enviando** (Sending) | Currently going out. | | **Enviada** (Sent) | Already delivered to the audience. | | **Cancelada** (Cancelled) | Stopped before being sent. | | **Falló** (Failed) | Something went wrong on send. | ## Personalization Messages accept variables that are filled in with each member's data (for example `{{first_name}}`), so a single message arrives personalized to every person. To send over WhatsApp you need WhatsApp Business connected under Integrations. # Create a campaign (https://docs.loybox.com.ar/en/campanas/crear-una-campana) Campaigns are created from a segment, so they start in the **Segmentación** (Segmentation) section. Here is how to do it end to end. Loybox's admin dashboard is not translated yet, so menu and button names are quoted **exactly as they appear on screen**, with the English meaning right after. ## Step by step ### Open a segment under **Segmentación** (Segmentation) Go to **Segmentación** and open the segment you want to talk to (for example, *En riesgo*, at risk, or *Champions*). ### Create the campaign for that group From the segment's detail view, start a campaign. The audience is defined by that segment. ### Choose the channel WhatsApp or email. To use WhatsApp you need [WhatsApp Business connected](https://docs.loybox.com.ar/integraciones/whatsapp) under Integrations. ### Write the **Mensaje** (message) Draft the text. Use variables such as `{{first_name}}` to personalize it with each member's name. ### Preview Check how the message will arrive before sending it. ### Schedule the send Under **Fecha y hora** (date and time), pick when it goes out (it has to be in the future) and tap **Programar envío** (Schedule send). You can also save it as a draft. ### Follow the results Under **Campañas** (Campaigns) you will see all your campaigns with their state (Borrador, Programada, Enviando, Enviada…) and their metrics. The advantage of starting from a segment is being able to adjust the tone: thank and reward the *Champions*; give the *En riesgo* a concrete reason to come back. The same effort goes further when the message fits who receives it. # Integrations (https://docs.loybox.com.ar/en/integraciones) Loybox connects to the tools you already use so your loyalty program runs without friction: your online store, WhatsApp and your email marketing. Every integration is managed from the **Integraciones** (Integrations) section of the dashboard. ## Available Many Loybox tools, such as reviews and recommendations, lean on your connected online store. Connecting Tiendanube is the first step to using them. Tiendanube is the leading ecommerce platform in Latin America, and Perfit is an email marketing tool widely used in the region. Both are the local equivalents of what a Shopify or a Mailchimp is elsewhere. # Tiendanube (https://docs.loybox.com.ar/en/integraciones/tiendanube) The Tiendanube integration connects your online store to Loybox. It is the foundation of most of the tools: your store's orders, products and customers sync automatically. Tiendanube is the leading ecommerce platform in Latin America, the region Loybox operates in. ## What it enables ## How to connect it ### Go to **Integraciones** (Integrations) In the dashboard's sidebar, open **Integraciones**. ### On **Tiendanube**, tap **Conectar** (Connect) It redirects you to Tiendanube to authorize the connection with your store. ### Authorize the access Confirm the permission in Tiendanube. On your way back, the store is connected and the sync starts. Connecting Tiendanube is the first step to using automatic points, redemption at checkout, reviews and recommendations. # WhatsApp Business (https://docs.loybox.com.ar/en/integraciones/whatsapp) The WhatsApp Business integration lets Loybox send messages to your members over WhatsApp: point notifications, review requests, recommendations and campaigns. ## What it enables ## How to connect it ### Go to **Integraciones** (Integrations) In the dashboard, open the **Integraciones** section. ### On **WhatsApp Business**, tap **Conectar** (Connect) Meta's flow opens to link your WhatsApp Business account. ### Complete the connection with Meta Follow Meta's steps to authorize. When you are done, WhatsApp Business is connected. The connection goes through Meta (Facebook), the official provider of the WhatsApp Business API. # Perfit (https://docs.loybox.com.ar/en/integraciones/perfit) The Perfit integration syncs your club's contacts with your Perfit account, so you can add email marketing to your loyalty strategy. Perfit is an email marketing platform widely used in Latin America. ## What it enables ## How to connect it ### Go to **Integraciones** (Integrations) In the dashboard, open the **Integraciones** section. ### On **Perfit**, tap **Conectar** (Connect) Link your Perfit account by following the on-screen steps. ### Done Once connected, Loybox starts syncing your contacts to Perfit. # Technical reference (https://docs.loybox.com.ar/en/referencia-tecnica) This page sums up, in one place, how Loybox works at a technical level: the entities, the formulas and the rules that govern each mechanism. Every section links to the matching guide if you need the full detail. ## Entities The whole model rests on five pieces ([Concepts](https://docs.loybox.com.ar/conceptos)): | Entity | What it represents | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | | **Brand** | The company inside Loybox. It sets the currency, the point rules, the reward catalog and the app's identity. It can have one location or many. | | **Member** | The person who joined the club. They have a relationship with the brand, with their own point balance and history. | | **Consumption** | The record of a purchase, in the store or in the online store. It is what triggers the point calculation. | | **Point** | The unit of loyalty. It is earned through consumptions and other actions, and spent redeeming rewards. | | **Reward** | What the member gets in exchange for points. | In the API the member of a club is the `client` resource (`/v1/clients`), and the dashboard says *Cliente*. This page uses "member", which is the product's term for the people in the club; "client" is the brand that signs up. Where a field or an endpoint is named, the API's own name is used. ## Point calculation The main rule is money per point ([Earning points](https://docs.loybox.com.ar/puntos-y-premios/ganar-puntos)): ``` points = floor( purchase amount ÷ money per point ) ``` Rounding is always down. With `100 = 1 point`, a purchase of `1,750` earns `17` points. ### Default per-currency conversion If the brand does not define a money-per-point rule, a per-currency conversion applies: | Currency | Default rule | | ------------------ | -------------------------------------------------------------------------- | | Euro (EUR) | 50 points per € | | Mexican peso (MXN) | 1 point per 50 MXN | | Everything else | Converted to dollars (MEP rate, refreshed regularly) and 50 points per USD | As soon as the brand defines its own rule, this conversion stops applying. ### The order of the multipliers Order matters, because the adjustments cascade: ### Base point Following the money-per-point rule, or the per-currency conversion. ### Double points If the promotion is running, it doubles the previous result. ### The tier's percentage bonus Applied last, according to the tier the member holds at the time of the purchase ([Tier benefits](https://docs.loybox.com.ar/niveles/beneficios-de-nivel)). ### Other sources of points Beyond consumptions, points are awarded by referrals (once the invitee's first purchase goes through), birthdays, joining the club and reaching a tier for the first time. ## Balance A member's balance is always `live earned points − redeemed points`. There is no persisted counter to reconcile, so the number is consistent with the real history by construction. Expired points are not deleted from the history: they stop counting when the available balance is calculated. ## Point expiration There are three modes ([Point expiration](https://docs.loybox.com.ar/puntos-y-premios/expiracion)): | Mode | Behavior | | ------------------- | --------------------------------------------------------------------------------------- | | **No expiration** | Points never expire. This is the default mode. | | **Rolling** | The whole balance shares a single expiration date, renewed with every new purchase. | | **Per transaction** | The points of each consumption expire at their own pace, regardless of later purchases. | Expiration only applies if the mode is `rolling` or `per transaction` and the period in days is greater than zero. With the period at zero, points do not expire even if the mode is active. ## Tiers A member's tier is resolved by thresholds ([How members move up](https://docs.loybox.com.ar/niveles/como-suben-de-nivel)): * Each tier is measured by accumulated points or by amount spent, and each tier can use its own criterion within the same ladder. * Progress is calculated over the full history of the relationship, not over the current balance. That is why redeeming never demotes anyone: the balance drops, the tier does not. * After each purchase, the member sits in the highest tier whose threshold they already reached. * Thresholds always increase: a higher tier cannot demand less than a lower one. The base tier is the entry step: it has no threshold and no expiration, and it never expires ([Expiration and demotion](https://docs.loybox.com.ar/niveles/vencimiento-de-niveles)). Tier expiration only applies to VIP tiers measured by points. ## Rewards A reward is defined by type and value, cost in points, redemption cap, expiration and an optional image ([Rewards](https://docs.loybox.com.ar/puntos-y-premios/premios)). The text the member sees is generated from the type and the value. Types: free product, money voucher (`$`), percentage discount (`%`), 2-for-1, free shipping and free-form (your own text). Possible states, derived from the configuration: | State | Condition | | ------------ | ------------------------------------ | | **Active** | Available to redeem. | | **Inactive** | Paused manually. | | **Expired** | Its expiration date has passed. | | **Sold out** | It reached its total redemption cap. | Only active rewards show up as available to the member. A redemption cap of zero means unlimited. ## Redemption The flow checks the balance before deducting ([Redemption](https://docs.loybox.com.ar/puntos-y-premios/canje)): ### Balance check The redemption goes through only if the member covers the reward's cost in points. ### Deduction and issuance The redemption is recorded, the cost is subtracted from the balance and the reward ends up in the member's name with a short, unique validation code. ### Code validation The code is bound to the brand and to that specific redemption. Once marked as used it cannot be validated again, which prevents double use. A redeemed reward keeps the original reward's validity date. ## Segmentation Members are grouped automatically with the RFM model ([Segmentation](https://docs.loybox.com.ar/segmentacion)), over three signals: recency (how long ago they bought), frequency (how many times) and monetary value (how much they spent in total). The segments follow the RFM standard: `Champions`, `Leales`, `Leales en potencia`, `Necesitan atención`, `En riesgo`, `Hibernando` and `Perdidos` (the names come back from the product in Spanish: loyal, potential loyalists, need attention, at risk, hibernating and lost). Each one exposes its RFM rule, its member count, its weight in the base and in sales, and averages for recency, frequency and order value. Segmentation is calculated over the orders of the connected online store. ## Channels and integrations One brand can run the club in brick-and-mortar stores (a PWA app with its own branding) and in its online store (wired into the checkout). The point rules and the reward catalog are shared across channels. Available integrations ([Integrations](https://docs.loybox.com.ar/integraciones)): Tiendanube (orders, products and customers), WhatsApp Business (notifications and messages) and Perfit (contact sync for email). Reviews and recommendations depend on having the online store connected. # About the API (https://docs.loybox.com.ar/en/api-reference) The Loybox API does the same things the dashboard does, but from your code: recording purchases that earn points, showing the reward catalog, redeeming codes and looking up a member's state. It is a **REST API over HTTPS**. Everything goes back and forth as JSON, field names are in `snake_case` and dates are ISO 8601 with a time zone (`2026-03-14T18:30:00Z`). ## Base URL Every route in this reference hangs off: ``` https://loybox-public-api-752998171300.southamerica-west1.run.app ``` The version goes in the first path segment (`/v1/...`). When an endpoint changes in a non-compatible way, a new version appears alongside the old one, and the old one keeps working: that is the case with [looking up a code](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo) and its [version 2](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo-v2). ## The examples Every endpoint page carries the whole call in `curl`, ready to paste into a terminal. Three things are variables and apply to every example: | In the example | What to put | | ------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `$LOYBOX_API_KEY` | Your [API key](https://docs.loybox.com.ar/api-reference/credenciales#api-key-del-comercio). Export it in the environment; do not paste it into the command. | | `$ACCESS_TOKEN` | The [end-user token](https://docs.loybox.com.ar/api-reference/credenciales#token-del-usuario-final) that the login returned. | | `X-Commerce-Id: 87` | **Your** commerce id. | ## Machine format The API is also published as a specification, so you can generate a client instead of writing one: ``` https://docs.loybox.com.ar/openapi.json ``` It is OpenAPI 3.1 and covers all 25 endpoints, the response schemas and the two credentials. If you are integrating with the help of an agent, hand it that URL. There is one `openapi.json` for all three languages, and its field descriptions are in Spanish. Field names, endpoint paths and schemas are language-neutral, so a generated client is identical either way. ## The two ways to integrate This is the most important decision, and it is worth making before writing code, because it changes the credential, the available endpoints and where your code runs. Every section of this reference uses one of the two, and every endpoint page says which at the top: | Section | Credential | What for | | ---------------------------------------------- | -------------- | ---------------------------------------- | | [Consumptions](https://docs.loybox.com.ar/api-reference/consumos) | API key | Recording purchases that earn points | | [Clients](https://docs.loybox.com.ar/api-reference/clientes) | API key | Looking up members and their benefits | | [Benefits](https://docs.loybox.com.ar/api-reference/beneficios) | API key | Catalog, code lookup and redemption | | [Authentication](https://docs.loybox.com.ar/api-reference/autenticacion) | — | End-user sign-in by email | | [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) | End-user token | The user's points, purchases and history | | [Public](https://docs.loybox.com.ar/api-reference/publico) | — | Brand and catalog, without signing in | The commerce API key grants access to the data of **all** your members. It lives on your server only. What can live in the browser is the end user's access token, which only sees their own data. ## What responses look like Responses have no envelope: the object comes at the root, and lists come back as a plain array. ```json // GET /v1/clients/12345 { "code": 12345, "username": "Ana Pérez", "email": "ana@example.com", "points": 340 } ``` Optional fields are present and set to `null`, not absent. You can read them without checking whether they exist, but you do have to check whether they are `null`. ## Pagination There are two schemes, and each one lives in a single endpoint: ### Limit and offset [Listing clients](https://docs.loybox.com.ar/api-reference/clientes/listar) uses `limit` and `offset`, and returns the total so you can build page numbers. ```json // GET /v1/clients/list?limit=20&offset=40 { "items": [], "total": 1875, "limit": 20, "offset": 40 } ``` `limit` goes from 1 to 100 and defaults to 20. `offset` starts at 0. ### Cursor [My history](https://docs.loybox.com.ar/api-reference/mi-cuenta/historial) uses a cursor, because it is a list that grows at the top and page numbers would shift under you. You request the next page by passing the previous response's `next_cursor` in `?cursor=`. ```json // GET /v1/me/activity { "results": [], "next_cursor": "eyJkIjoiMjAyNi0wMy0xNCJ9", "previous_cursor": null } ``` When `next_cursor` comes back `null`, there are no more pages. ## Where to start # Getting started (https://docs.loybox.com.ar/en/api-reference/primeros-pasos) This page is the complete integration, end to end. If you are here to implement and want to read a single page before writing code, this is the one. There are **two paths** and they are not exclusive: almost every integration starts with the first and adds the second when they want the member to see their own points. | Path | What it solves | Credential | | ------------------------------------------------------------ | -------------------------------------------------------------------- | --------------------------------------------------------------------- | | [From your server](#camino-1-sumar-puntos-desde-tu-servidor) | Making purchases earn points and codes get redeemed at the sale | [API key](https://docs.loybox.com.ar/api-reference/credenciales#api-key-del-comercio) | | [From your frontend](#camino-2-el-club-en-tu-frontend) | Letting the member see their points, buy rewards and show their code | [End-user token](https://docs.loybox.com.ar/api-reference/credenciales#token-del-usuario-final) | ## Before you start You need two things, and we give you both: write to us at [hola@loybox.com.ar](mailto:hola@loybox.com.ar). The commerce API key. It goes on your server only. Your commerce id. This is what travels in the `X-Commerce-Id` header and it can live in the frontend. From here on, the examples use the [reference's conventions](https://docs.loybox.com.ar/api-reference#los-ejemplos): `$LOYBOX_API_KEY` for the API key, `$ACCESS_TOKEN` for the end-user token and `87` as the `commerce_id`. ## Path 1: earning points from your server This is the minimum integration of a loyalty program: a single call, at the point where your system confirms a sale. ### Record the purchase At an online checkout you already have the email, so [by email](https://docs.loybox.com.ar/api-reference/consumos/crear-por-email) is the short path: it works even if the member does not have a Loybox account yet. ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/consumptions/email \ -H "Authorization: Bearer $LOYBOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "client_email": "ana@example.com", "amount": 1750 }' ``` At a physical point of sale, where the member gives their number, it is the same call [by code](https://docs.loybox.com.ar/api-reference/consumos/crear-por-codigo) with `client_code`. `amount` is whole units of the commerce's currency. A purchase of `1,750.50` is sent as `1750`. How many points it earns is not decided by your call: it is decided by the commerce's configuration. You send the amount and Loybox applies the money-per-point rule, double points if they are running, and the tier bonus, in that order ([the formula](https://docs.loybox.com.ar/referencia-tecnica#cálculo-de-puntos)). ### Show them the balance The consumption's response does not say how many points it added. The balance is [looked up separately](https://docs.loybox.com.ar/api-reference/clientes/obtener): ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/clients/12345 \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` With this you already have a working program: purchases earn and the member has a balance. ### Look up the code the member brings When a member shows up with a redemption code (their `client_benefit_code`), the first thing is to see what it is. Use [v2](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo-v2), which brings the discount's value at the root: ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v2/benefits/preview/887766 \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` With the response's `type` and `value` you apply the discount in your sale: | `type` | What to do | | --------------------- | -------------------------------- | | `percentage_discount` | Apply the percentage in `value`. | | `absolute_discount` | Subtract the amount in `value`. | | `free_product` | Add the product in `product`. | A `400` here means the code was already used: do not apply anything. ### Redeem it once the sale closed [Redemption](https://docs.loybox.com.ar/api-reference/beneficios/canjear) burns the code and there is no going back: ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/benefits/redeem \ -H "Authorization: Bearer $LOYBOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "client_benefit_code": 887766 }' ``` Looking up is harmless and can be repeated; redeeming is final. If you redeem before closing the sale and the sale falls through, the member lost the reward and there is no way to give it back over the API. ## Path 2: the club in your frontend Here Loybox works as the loyalty engine under your product: the user signs in with a code emailed to them and from there sees their points, buys benefits and shows their codes. All of this can run in the browser. No call on this path carries the API key: it grants access to the data of all your members. What travels is the end-user token, which only sees their own data, plus the `X-Commerce-Id`, which is not a secret. ### Ask for the code ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/auth/otp/request \ -H "X-Commerce-Id: 87" \ -H "Content-Type: application/json" \ -d '{ "email": "ana@example.com" }' ``` It always answers `200`, even if that email has no account. In the UI you always show the same message ("we sent a code to your email"), because you cannot know whether the account existed. ### Verify it and store the session ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/auth/otp/verify \ -H "X-Commerce-Id: 87" \ -H "Content-Type: application/json" \ -d '{ "email": "ana@example.com", "otp": "418302" }' ``` It returns `access` and `refresh`. Store both: the `access` expires in `expires_in` seconds and the `refresh` is what [renews it](https://docs.loybox.com.ar/api-reference/autenticacion/renovar-token) without asking the user for another code. If the email had no account, one is created, and either way the user ends up subscribed to your program. ### Paint the screen with a single call [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener) brings the points, the commerce's branding and the points about to expire, all at once: ```js const res = await fetch( 'https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me', { headers: { Authorization: `Bearer ${accessToken}`, 'X-Commerce-Id': '87', }, }, ); const me = await res.json(); // me.points -> the big balance on the screen // me.commerce -> logo, name and color for the program's branding // me.subscribed -> if it comes back false, show the call to join ``` A `401` here means the `access` expired: [renew it](https://docs.loybox.com.ar/api-reference/autenticacion/renovar-token) and retry the call. ### Show the catalog and buy [The catalog](https://docs.loybox.com.ar/api-reference/mi-cuenta/beneficios-disponibles) comes back unfiltered by balance: you compare each benefit's `cost` with the user's `points` and decide what to show as reachable and what as "you need N more points". ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/benefits/exchange \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" \ -H "Idempotency-Key: 8f14e45f-ea0f-4d1c-9a1b-2c3d4e5f6a7b" \ -H "Content-Type: application/json" \ -d '{ "benefit_id": "b_9f2a" }' ``` Buying trades points for a benefit, and the user does it from your frontend. Redeeming uses that benefit in the sale, and your server does it with the API key ([step 4 of path 1](#camino-1-sumar-puntos-desde-tu-servidor)). ### Show them the code The purchase returns a `client_benefit_code`. That number is both the redemption code and the coupon code: in an online store it is what the user pastes at checkout, and in a physical store it is what they show at the counter. Show it large, with a copy button and the `due_date` next to it. The full list of the ones they hold is in [my benefits](https://docs.loybox.com.ar/api-reference/mi-cuenta/mis-beneficios). ## The full circuit The two paths close like this, and it is the mental model worth having before writing code: ``` purchase ─▶ POST /v1/consumptions/email (your server, API key) │ ▼ points to the member │ ▼ POST /v1/me/benefits/exchange (your frontend, end-user token) │ ▼ client_benefit_code │ ▼ GET /v2/benefits/preview/{code} (your server, API key) │ ▼ POST /v1/benefits/redeem (your server, API key) ``` ## Before going to production * The **API key lives on your server only**. If it leaked, write to us and we rotate it. * **Never retry a `400`** blindly: it is the already-used benefit, the expired one or points that fall short. Read the `message` and stop. * **Buying a benefit carries an `Idempotency-Key`**. It is what prevents charging the points twice when the network drops. * A **`401`** in My account is the signal to renew the token, not to sign the user out. * The **`404` from [my tier](https://docs.loybox.com.ar/api-reference/mi-cuenta/nivel)** is the normal case for a new member: hide the tiers section, do not show an error. * **`points_expiration` does not come back `null`** when points do not expire: it comes with `mode: "none"`. Check the `mode` before showing the notice. ## If you are implementing with an agent The API is published in machine format: * [`/openapi.json`](https://docs.loybox.com.ar/openapi.json): the complete OpenAPI 3.1 specification, with all 25 endpoints, the schemas and the two credentials. Good for generating a typed client. Its descriptions are in Spanish; the names and schemas are not. * [`/llms.txt`](https://docs.loybox.com.ar/llms.txt) and [`/llms-full.txt`](https://docs.loybox.com.ar/llms-full.txt): the whole docs as text, meant to be handed over as context. These two are per language, so the links above are the English ones. * Any page of the docs as raw Markdown by appending `.md` to the URL, for example [`/api-reference/credenciales.md`](https://docs.loybox.com.ar/api-reference/credenciales.md). # Credentials (https://docs.loybox.com.ar/en/api-reference/credenciales) The API has **two distinct credentials**, and they are not interchangeable. Which one you use depends on where your code runs and what data it needs to see. ## Commerce API key This is the classic integration: your backend operates across every member of the commerce. The API key goes in the `Authorization` header: ``` Authorization: Bearer {api-key} ``` This credential works with [Consumptions](https://docs.loybox.com.ar/api-reference/consumos), [Benefits](https://docs.loybox.com.ar/api-reference/beneficios) and [Clients](https://docs.loybox.com.ar/api-reference/clientes). No other header is needed: the key already identifies the commerce. The API key grants access to the data of **all** your members. Never put it in the frontend, in a mobile app, or in a repository. If it leaked, write to us at [hola@loybox.com.ar](mailto:hola@loybox.com.ar) so we can rotate it. ## End-user token Meant for wiring Loybox straight into your frontend and using it as a loyalty engine: the user signs in with a code emailed to them and from there looks up their points, buys benefits and sees their history. Two headers travel: ``` Authorization: Bearer {user-access-token} X-Commerce-Id: {your-commerce-id} ``` This credential works with [Authentication](https://docs.loybox.com.ar/api-reference/autenticacion), [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) and [Public](https://docs.loybox.com.ar/api-reference/publico). This token **can** live in the browser: it only sees that user's data in your commerce. ## The X-Commerce-Id header Id of the commerce integrating the API. Every response is scoped to this commerce. It is required on **every** Authentication, My account and Public endpoint, even the ones that carry no token. It is the header that scopes the response to your program: the same user can be in several Loybox programs, and with this header they only see yours. It is not a secret: it goes in the frontend without a problem. What it does is scope, not authorize. ## The sign-in flow ### Request the code [`POST /v1/auth/otp/request`](https://docs.loybox.com.ar/api-reference/autenticacion/pedir-codigo) with the user's email. They receive a 6-digit code. ### Verify it [`POST /v1/auth/otp/verify`](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo) with the email and the code. It returns an access token (`access`) and a refresh token (`refresh`). If the email had no Loybox account, one is created, and either way the user ends up subscribed to your commerce's program. ### Use the session From there on, calls to [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) go with `Authorization: Bearer {access}`. ### Renew it When the `access` expires, [`POST /v1/auth/refresh`](https://docs.loybox.com.ar/api-reference/autenticacion/renovar-token) returns a new one from the `refresh`, without asking the user for another code. The code expires in **10 minutes** and allows **5 attempts**. Requesting a new code invalidates the previous one. ## Summary | | Commerce API key | End-user token | | ------------------ | --------------------------------- | -------------------------------------------------- | | **Header** | `Authorization: Bearer {api-key}` | `Authorization: Bearer {access}` + `X-Commerce-Id` | | **Where it lives** | On your server only | Can live in the browser | | **What it sees** | Every member of the commerce | Only that user, only in your commerce | | **Expires** | No | Yes, renewed with the `refresh` | | **Sections** | Consumptions, Benefits, Clients | Authentication, My account, Public | # Objects (https://docs.loybox.com.ar/en/api-reference/objetos) This page is the API's dictionary: every object that shows up in a response, with all of its fields. Endpoint pages link here instead of repeating the lists. ## The three codes First of all, this: the API handles three similar-looking identifiers, and mixing them up is the most common mistake when integrating. | Code | What it identifies | Where it is used | | --------------------- | --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | `client_code` | A **member**. It is the number every person registered in Loybox has. | [Recording a consumption](https://docs.loybox.com.ar/api-reference/consumos/crear-por-codigo), [looking up a client](https://docs.loybox.com.ar/api-reference/clientes/obtener) | | `benefit_id` | A **catalog benefit**, the one the commerce created. | [Looking up a benefit](https://docs.loybox.com.ar/api-reference/beneficios/obtener), [buying it](https://docs.loybox.com.ar/api-reference/mi-cuenta/comprar-beneficio) | | `client_benefit_code` | A benefit **already bought** by a specific member. | [Looking up the code](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo), [redeeming it](https://docs.loybox.com.ar/api-reference/beneficios/canjear) | The commerce creates **benefits**, and each one has a `benefit_id`. When a member buys one with their points they receive a **redeemable benefit** with its own `client_benefit_code`. The `benefit_id` is only good for looking up information. The `client_benefit_code` is good for looking up **and for redeeming**: it is the code the member presents in the store, or pastes at the online store's checkout. ## Client Appears in [listing clients](https://docs.loybox.com.ar/api-reference/clientes/listar) and [looking up a client](https://docs.loybox.com.ar/api-reference/clientes/obtener). The member's code. The member's name. The member's email. Points they hold at the commerce. ## Benefit The catalog benefit. Appears in almost every response of [Benefits](https://docs.loybox.com.ar/api-reference/beneficios), [Clients](https://docs.loybox.com.ar/api-reference/clientes), [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) and [Public](https://docs.loybox.com.ar/api-reference/publico). The `benefit_id`. What kind of reward it is: `percentage_discount`, `absolute_discount` or `free_product`. Description of the benefit. How many points it costs to buy. How long it stays valid. `null` if it does not expire. `normal` for catalog ones; `welcome`, `birthday`, `monthly_top` or `level` for the automatic rewards. Defaults to `normal`. The commerce's brand color, in hexadecimal. Total number of redemptions allowed for this benefit. `0` means no limit. The reward's detail. See [Prize](#premio). The coupon, if the benefit applies in a Tiendanube store. See [Tiendanube coupon](#cupón-de-tiendanube). ### Benefit (v2) [`GET /v2/benefits/preview/{client_benefit_code}`](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo-v2) returns a version with three extra fields, which save you from digging into `prize` for the basics: The benefit's title. In v1 it only lived inside `prize`. The discount's value: the percentage if it is `percentage_discount`, the amount if it is `absolute_discount`. The product, if it is `free_product`. See [Product](#producto). Every other field is the same as in [Benefit](#beneficio). ## Redeemable benefit A benefit a member already bought. Appears in [purchased benefits](https://docs.loybox.com.ar/api-reference/clientes/beneficios-comprados), [my benefits](https://docs.loybox.com.ar/api-reference/mi-cuenta/mis-beneficios) and as the response of [buying a benefit](https://docs.loybox.com.ar/api-reference/mi-cuenta/comprar-beneficio). The redemption code. It is what the member presents at the commerce, and also the coupon code in an online store. When they bought it. How long they have to redeem it. `null` if it does not expire. Whether it was already redeemed. Defaults to `false`. The benefit bought. See [Benefit](#beneficio). ## Prize The detail of what the member wins. It lives inside `prize`. `percentage_discount`, `absolute_discount` or `free_product`. The reward's title. The reward's description. The discount's percentage or amount, depending on the `type`. The gift product. See [Product](#producto). The reward's expiration. URL of the reward's image. ## Product The product's id in Loybox. The product's name. The product's id in the commerce's own system. ## Commerce The program's branding data. Appears in [commerce data](https://docs.loybox.com.ar/api-reference/publico/comercio) and inside [my account](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener). The `commerce_id`, the same one that goes in the `X-Commerce-Id` header. The commerce's name. URL of the logo. Brand color in hexadecimal, for the program's UI. The commerce's category, for example `Tienda de comics`. The commerce's currency. ## My account The response of [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener). The user's name. The user's email. The user's phone. The user's points at this commerce. Defaults to `0`. Whether the user is subscribed to this commerce's program. Defaults to `false`. The commerce's data, to paint the program's branding. See [Commerce](#comercio). Points about to expire. See [Points expiration](#vencimiento-de-puntos). ## Points expiration Points about to expire. Defaults to `0`. When they expire. Days remaining. Months remaining. How points expire at this commerce: `none`, `rolling` or `accumulated`. `none` means they do not expire. If the commerce does not expire points, the object comes back with `mode: "none"` and `points: 0`, not as `null`. See [Point expiration](https://docs.loybox.com.ar/puntos-y-premios/expiracion) for the detail of the modes. ## Tier The response of [`GET /v1/me/level`](https://docs.loybox.com.ar/api-reference/mi-cuenta/nivel). The endpoint and its fields say `level`; this documentation says "tier", which is the product's term in English. It is the same thing. The tier's name. The tier's position in the ladder. The points multiplier the tier grants. URL of the tier's icon. When they reached the tier. When the tier expires. Whether the tier already expired. The next tier and what is missing to reach it. See [Next tier](#próximo-nivel). Points earned in total, the lifetime accumulated figure. Amount spent in total. Number of consumptions recorded. ### Next tier The next tier's name. The next tier's position. What the threshold is measured in: accumulated points or amount spent. The threshold value to reach. ## Activity item Each item of [my history](https://docs.loybox.com.ar/api-reference/mi-cuenta/historial). What happened: `consumption` (a purchase that earned points), `benefit_exchange` (they bought a benefit with points), `benefit_usage` (they redeemed a benefit) or `points_special_reward` (an automatic reward gave them points). When it happened. Points the item added or subtracted. The benefit involved, on benefit items. See [Benefit](#beneficio). The purchase amount, on `consumption` items. The event that triggered the reward, on `points_special_reward` items. Additional note on the item. ## Automatic reward Each item of [program rewards](https://docs.loybox.com.ar/api-reference/mi-cuenta/recompensas). The event that triggers it: `welcome`, `birthday` or `monthly_top`. `benefit` if it delivers a benefit, `points` if it delivers points. The benefit it delivers, when `reward_type` is `benefit`. See [Benefit](#beneficio). The points it delivers, when `reward_type` is `points`. ## Session The response of [verifying the code](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo). Access token. Sent as `Authorization: Bearer {access}` on the My account endpoints. Refresh token, to get a new `access` without asking for another code. Seconds the access token stays valid. The user's id. The user's name. The user's email. The user's phone. ## Tiendanube coupon Lives inside `tiendanube_coupon` when the benefit applies in a [Tiendanube](https://docs.loybox.com.ar/integraciones/tiendanube) store. `percentage`, `absolute` or `shipping`. The coupon's value. Id of the Tiendanube category the coupon applies to. That category's name. How long the coupon is valid for. The product the coupon applies to, if it applies to a single one. See [Tiendanube product](#producto-de-tiendanube). ### Tiendanube product The product's id in Tiendanube. The product's name. URL of the product in the store. Whether it is in stock. Whether it is published in the store. The product's brand. The product's categories, each with `id` and `name`. Empty by default. # Errors (https://docs.loybox.com.ar/en/api-reference/errores) When something goes wrong, the API responds with an HTTP status code and a body with a single field: ```json { "message": "Client not found" } ``` The `message` is text for the developer, not for showing to the user: it can change without notice. What your code should look at is **the status code**. ## Status codes | Code | What it means | What to do | | ----- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | `200` | It worked. | — | | `201` | The resource was created. Both [Consumptions](https://docs.loybox.com.ar/api-reference/consumos) endpoints return this. | — | | `400` | The request could not be processed: the benefit was already used, it is not valid, or the user's points fall short. | Read the `message` to know which case it is. Do not retry as is. | | `401` | The credential is missing, expired, or does not work for this endpoint. | With an API key, check it is the right one. With an end-user token, [renew it](https://docs.loybox.com.ar/api-reference/autenticacion/renovar-token). | | `403` | The client exists but cannot have consumptions. | Do not retry. | | `404` | The resource does not exist: client, benefit or commerce. | Check the code or the id you sent. | | `422` | The body or the headers failed validation. | See [Validation errors](#errores-de-validación). | ## Validation errors The `422` is different from the rest: it does not carry a `message` but a `detail` with the list of everything that is wrong, one item per field. ```json { "detail": [ { "loc": ["body", "amount"], "msg": "Input should be a valid integer", "type": "int_parsing" } ] } ``` Where the problem is. The first element says which part of the request (`body`, `query`, `header`, `path`) and the rest is the path to the field. What is wrong with it. The kind of validation error. The most frequent cause of a `422` is not the body: it is **the missing `X-Commerce-Id` header**. It is required on every endpoint of [Authentication](https://docs.loybox.com.ar/api-reference/autenticacion), [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) and [Public](https://docs.loybox.com.ar/api-reference/publico). ## Two cases that are not errors [`POST /v1/auth/otp/request`](https://docs.loybox.com.ar/api-reference/autenticacion/pedir-codigo) answers `200` even if the email has no Loybox account. That is deliberate: if it answered differently, anyone could use the endpoint to find out which emails are registered. Do not use it to check whether a user exists. [`GET /v1/me/level`](https://docs.loybox.com.ar/api-reference/mi-cuenta/nivel) returns `404` when the user does not have a tier yet, or when the commerce does not use tiers. It is the normal case for a new member, not a failure: in the UI the right move is to hide the tiers section, not to show an error. ## Retries Buying a benefit moves points, so a blind retry can charge them twice. That is what [`POST /v1/me/benefits/exchange`](https://docs.loybox.com.ar/api-reference/mi-cuenta/comprar-beneficio) accepts the `Idempotency-Key` header for: if you send the same value again, the purchase does not repeat. ``` Idempotency-Key: 8f14e45f-ea0f-4d1c-9a1b-2c3d4e5f6a7b ``` Use a different value for each purchase the user starts (a UUID is enough) and the same one across every retry of that purchase. # Consumptions (https://docs.loybox.com.ar/en/api-reference/consumos) A **consumption** is the record of a purchase. It is what triggers the point calculation: every time a member buys, your system tells Loybox and Loybox adds the points that apply. It is the minimum integration of a loyalty program. If you are only going to call one endpoint in this whole API, it is one of these two. ## The two endpoints They do the same thing and differ only in how they identify the member: | | By code | By email | | -------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | | **Identifies the member with** | Their `client_code` | Their email | | **If the member does not exist** | Returns `404` | Records the consumption anyway and invites them by email | | **When to use it** | A point of sale or app where the member gives their code | An online checkout, where you already have the email | ## How many points it earns The call does not decide that: the commerce's configuration does. You send the purchase **amount** and Loybox applies the money-per-point rule, double points if they are running, and the member's tier bonus, in that order. The formula and the order of the multipliers are in [Technical reference](https://docs.loybox.com.ar/referencia-tecnica#cálculo-de-puntos). The `amount` field is an `integer`: whole units of the commerce's currency, no decimals. A purchase of `1,750.50` is sent as `1750`. ## Credential Both endpoints go from your server, with the [commerce API key](https://docs.loybox.com.ar/api-reference/credenciales#api-key-del-comercio): ``` Authorization: Bearer {api-key} ``` # Create consumption by code (https://docs.loybox.com.ar/en/api-reference/consumos/crear-por-codigo) Records a new consumption using the member's code. This is the call that earns the points of a purchase. The member has to exist: if the code does not match any client, the call returns `404` and nothing is recorded. If you would rather the consumption be recorded anyway, use [create consumption by email](https://docs.loybox.com.ar/api-reference/consumos/crear-por-email). ## Body The code of the member who made the purchase. The purchase amount, in whole units of the commerce's currency. Id of the register where the purchase was made. Id of the location where the purchase was made. ## Example ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/consumptions/client-code \ -H "Authorization: Bearer $LOYBOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "client_code": 12345, "amount": 1750, "counter_id": 2, "id_suc": 1 }' ``` ```json // 201 Created { "message": "Consumption created successfully" } ``` The response does not say how many points it earned. To see that, look the member up with [`GET /v1/clients/{client_code}`](https://docs.loybox.com.ar/api-reference/clientes/obtener). ## Errors | Code | When | | ----- | --------------------------------------------------------------------------------------------------------------------- | | `400` | The consumption could not be created. | | `403` | The client exists but is not eligible to have consumptions. | | `404` | The client does not exist. | | `422` | A body field is missing or has the wrong type. See [Validation errors](https://docs.loybox.com.ar/api-reference/errores#errores-de-validación). | # Create consumption by email (https://docs.loybox.com.ar/en/api-reference/consumos/crear-por-email) Records a new consumption using the member's email. This is the one to use at an online checkout, where you already have the email and asking the member for a code would be redundant. If the email does not match any Loybox account, the consumption **is created anyway** and an email automatically goes out inviting them to register. When they register, the points from that purchase are already waiting for them. It is how the program starts accruing value before the member joins. ## Body Email of the member who made the purchase. The purchase amount, in whole units of the commerce's currency. ## Example ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/consumptions/email \ -H "Authorization: Bearer $LOYBOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "client_email": "ana@example.com", "amount": 1750 }' ``` ```json // 201 Created { "message": "Consumption created successfully" } ``` ## Errors | Code | When | | ----- | ----------------------------------------------------------------------------------------------------------------------------------- | | `400` | The consumption could not be created. | | `403` | The client exists but is not eligible to have consumptions. | | `404` | The client does not exist. | | `422` | A body field is missing, or the email is not a valid format. See [Validation errors](https://docs.loybox.com.ar/api-reference/errores#errores-de-validación). | # Clients (https://docs.loybox.com.ar/en/api-reference/clientes) A **client** is a person who joined the commerce's club. They have their own `client_code`, point balance and history. The API resource is `client`, and that is the name used for fields and paths. In prose this documentation says "member", which is the product's term for the people in the club. This section is read-only: it exists to show a member's state inside your system, on the point-of-sale screen, in the online store's profile page, in a CRM. Points move by recording [consumptions](https://docs.loybox.com.ar/api-reference/consumos) and [redeeming benefits](https://docs.loybox.com.ar/api-reference/beneficios/canjear), not from here. ## The two benefit lists There are two per-member benefit endpoints, and it is worth not mixing them up: | Endpoint | What it returns | | ----------------------------------------------------------------------- | ------------------------------------------------------------------------- | | [`/available-benefits`](https://docs.loybox.com.ar/api-reference/clientes/beneficios-disponibles) | The ones the member **can buy** with the points they hold | | [`/benefits`](https://docs.loybox.com.ar/api-reference/clientes/beneficios-comprados) | The ones they **already bought** and can still redeem, each with its code | ## Credential The whole section goes from your server, with the [commerce API key](https://docs.loybox.com.ar/api-reference/credenciales#api-key-del-comercio): ``` Authorization: Bearer {api-key} ``` These endpoints expose the name, email and points of the people in the club. Do not call them from the frontend: if you need the user themselves to see their own data, that is what [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) is for, and it only shows their own. # List clients (https://docs.loybox.com.ar/en/api-reference/clientes/listar) Returns the commerce's client list, paginated with limit and offset. ## Parameters How many clients to return per page. From `1` to `100`. Defaults to `20`. Which position to start from. Defaults to `0`. ## Response The clients on this page. See [Client](https://docs.loybox.com.ar/api-reference/objetos#cliente). Total number of clients at the commerce, unpaginated. The limit applied. The offset applied. ## Example ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/clients/list?limit=2&offset=0 \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK { "items": [ { "code": 12345, "username": "Ana Pérez", "email": "ana@example.com", "points": 340 }, { "code": 12346, "username": "Bruno Díaz", "email": "bruno@example.com", "points": 0 } ], "total": 1875, "limit": 2, "offset": 0 } ``` To walk the whole list, keep adding `limit` to `offset` until the sum reaches `total`. ## Errors | Code | When | | ----- | --------------------------------------------------------------- | | `401` | The API key is invalid: it has no commerce attached. | | `422` | `limit` is outside the 1 to 100 range, or `offset` is negative. | # Get a client (https://docs.loybox.com.ar/en/api-reference/clientes/obtener) Looks a client up by their code. The `client_code` is the number every person registered in Loybox has: the one the member gives at the register and the one used to [record a consumption](https://docs.loybox.com.ar/api-reference/consumos/crear-por-codigo). ## Parameters The client's code. ## Response A [Client](https://docs.loybox.com.ar/api-reference/objetos#cliente) object. ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/clients/12345 \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK { "code": 12345, "username": "Ana Pérez", "email": "ana@example.com", "points": 340 } ``` The `points` field is the available balance: live earned points minus redeemed points. Expired points do not count. See [Balance](https://docs.loybox.com.ar/referencia-tecnica#saldo). ## Errors | Code | When | | ----- | ------------------------------- | | `404` | The client does not exist. | | `422` | The code is not a valid format. | # Benefits they can buy (https://docs.loybox.com.ar/en/api-reference/clientes/beneficios-disponibles) Looks up the benefits available to a client: the ones shown on their benefits screen, that is, the ones they **can buy** with their points. It is the flip side of [purchased benefits](https://docs.loybox.com.ar/api-reference/clientes/beneficios-comprados), which returns the ones they already traded points for. ## Parameters The client's code. ## Response An array of [Benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio). ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/clients/12345/available-benefits \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK [ { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": { "type": "percentage_discount", "title": "20% off", "description": "Válido en toda la tienda", "value": 20, "product": null, "expiration": "2026-12-31T23:59:59Z", "image": null }, "tiendanube_coupon": null } ] ``` The example's text values come back in the language the commerce wrote them in. They are data, not interface: Loybox does not translate what the brand typed. Each benefit's `cost` is what it costs in points. To know which ones they can afford, compare it with the `points` from [getting a client](https://docs.loybox.com.ar/api-reference/clientes/obtener). ## Errors | Code | When | | ----- | ------------------------------- | | `404` | The client does not exist. | | `422` | The code is not a valid format. | # Purchased benefits (https://docs.loybox.com.ar/en/api-reference/clientes/beneficios-comprados) Returns the benefits the client **already bought** with their points and can still redeem at the commerce. It is the flip side of [benefits they can buy](https://docs.loybox.com.ar/api-reference/clientes/beneficios-disponibles): that one returns what their points cover, this one what is already theirs. Each item's `client_benefit_code` is the code used to [look the benefit up](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo) and to [redeem it](https://docs.loybox.com.ar/api-reference/beneficios/canjear). It is the number the member presents in the store or pastes at checkout. ## Parameters The client's code. Left unspecified it returns **only the redeemable ones**: unused and unexpired. `true` returns the already-redeemed ones and `false` the unredeemed ones, in both cases without filtering by expiration. The default behavior is the one you need to operate: showing the member what they can use today. The `used` parameter is for querying the history. ## Response An array of [Redeemable benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio-canjeable). ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/clients/12345/benefits \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK [ { "client_benefit_code": 887766, "issue_date": "2026-03-01T14:22:00Z", "due_date": "2026-04-01T14:22:00Z", "used": false, "benefit": { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": null, "tiendanube_coupon": null } } ] ``` ## Errors | Code | When | | ----- | ----------------------------------------------------------- | | `401` | The API key is invalid: it has no commerce attached. | | `404` | The client does not exist. | | `422` | The code is not a valid format, or `used` is not a boolean. | # Benefits (https://docs.loybox.com.ar/en/api-reference/beneficios) This section holds the two halves of a reward's life: **the catalog** the commerce built, and **the redemption** of a code a member brings in to use. The commerce creates **benefits**, and each one has a `benefit_id`. When a member buys one with their points they receive a **redeemable benefit** with its own `client_benefit_code`. The `benefit_id` is only good for looking up information. The `client_benefit_code` is good for looking up **and for redeeming**. ## The redemption flow This is what it looks like on your system's side when a member shows up with a code: ### The member gives their code They have it in their Loybox app. It is the `client_benefit_code`. ### You look up what it is [`GET /v1/benefits/preview/{client_benefit_code}`](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo) tells you which reward it is and, where it applies, what discount to give. It does not redeem anything yet. ### You apply the discount At your register, your ecommerce or wherever the sale runs, using the previous step's data. ### You mark it as used [`POST /v1/benefits/redeem`](https://docs.loybox.com.ar/api-reference/beneficios/canjear). From here on the code is burned and cannot be used again. Looking up is harmless and can be repeated; redeeming is final. If you redeem before closing the sale and the sale falls through, the member lost the reward. ## The endpoints ## Credential The whole section goes from your server, with the [commerce API key](https://docs.loybox.com.ar/api-reference/credenciales#api-key-del-comercio): ``` Authorization: Bearer {api-key} ``` # List benefits (https://docs.loybox.com.ar/en/api-reference/beneficios/listar) Returns a list of every benefit created by the commerce. It is the full catalog, unfiltered by validity and unfiltered by member. It takes no parameters and no pagination. ## Response An array of [Benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio). ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/benefits/list \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK [ { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": null, "tiendanube_coupon": null }, { "id": "b_4c81", "type": "free_product", "description": "Café de regalo", "cost": 100, "expiration": null, "benefit_type": "welcome", "color": "#f1a10d", "buy_limit": 1, "prize": null, "tiendanube_coupon": null } ] ``` The `benefit_type` field separates catalog benefits (`normal`) from the rewards the commerce hands out on its own: `welcome`, `birthday`, `monthly_top` and `level`. If you want to show only what the member can buy with points, filter by `normal`, or use [benefits they can buy](https://docs.loybox.com.ar/api-reference/clientes/beneficios-disponibles), which comes pre-filtered. ## Errors This endpoint declares no errors of its own beyond the [general ones](https://docs.loybox.com.ar/api-reference/errores). # Get a benefit (https://docs.loybox.com.ar/en/api-reference/beneficios/obtener) Returns information about a catalog benefit using its id. The `benefit_id` identifies a **catalog** benefit, not one belonging to a specific member. To look up the benefit a member brings in to use, the identifier is the `client_benefit_code` and the endpoint is [look up a code](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo). ## Parameters The benefit's id. ## Response A [Benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio) object. ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/benefits/b_9f2a \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": { "type": "percentage_discount", "title": "20% off", "description": "Válido en toda la tienda", "value": 20, "product": null, "expiration": "2026-12-31T23:59:59Z", "image": null }, "tiendanube_coupon": null } ``` ## Errors | Code | When | | ----- | ---------------------------------------------------- | | `401` | The API key is invalid: it has no commerce attached. | | `404` | The benefit does not exist. | | `422` | The id is not a valid format. | # Look up a code (https://docs.loybox.com.ar/en/api-reference/beneficios/consultar-codigo) Returns information about a benefit using the code the member holds to redeem it. It is what tells you **which actions to take** before redeeming: what kind of reward it is, how much discount to apply, whether it is a gift product. With that, your system can apply the benefit in the sale and only then [mark it as used](https://docs.loybox.com.ar/api-reference/beneficios/canjear). Looking up does not redeem: you can call it as many times as you need. [v2](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo-v2) returns the same plus the `title`, the discount's `value` and the `product` at the top level, without having to dig into `prize`. For a new integration, that is the one to use. ## Parameters The redemption code the member holds. ## Response A [Benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio) object. ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/benefits/preview/887766 \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": { "type": "percentage_discount", "title": "20% off", "description": "Válido en toda la tienda", "value": 20, "product": null, "expiration": "2026-12-31T23:59:59Z", "image": null }, "tiendanube_coupon": null } ``` What to read depending on the `type`: | `type` | What to do | | --------------------- | -------------------------------------- | | `percentage_discount` | Apply the percentage in `prize.value`. | | `absolute_discount` | Subtract the amount in `prize.value`. | | `free_product` | Add the product in `prize.product`. | ## Errors | Code | When | | ----- | ---------------------------------------------------- | | `400` | The benefit was already used. | | `401` | The API key is invalid: it has no commerce attached. | | `404` | The benefit does not exist. | | `422` | The code is not a valid format. | A `400` here already tells you to stop: the code is burned and no discount should be applied. # Look up a code (v2) (https://docs.loybox.com.ar/en/api-reference/beneficios/consultar-codigo-v2) It does the same as [version 1](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo), returning information about the benefit from the code the member holds to redeem it, but it returns three extra fields at the root of the object. For a new integration, use this one. ## What changes | Field | In v1 | In v2 | | --------- | ------------------- | ------------------------------- | | `title` | Only inside `prize` | At the root, and always present | | `value` | Only inside `prize` | At the root | | `product` | Only inside `prize` | At the root | In practice: to apply the discount you no longer need to dig into `prize` or check that it exists. Every other field is the same. ## Parameters The redemption code the member holds. ## Response A [Benefit (v2)](https://docs.loybox.com.ar/api-reference/objetos#beneficio-v2) object. ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v2/benefits/preview/887766 \ -H "Authorization: Bearer $LOYBOX_API_KEY" ``` ```json // 200 OK { "id": "b_9f2a", "type": "percentage_discount", "value": 20, "title": "20% off", "description": "Válido en toda la tienda", "product": null, "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": null, "tiendanube_coupon": null } ``` What to read depending on the `type`: | `type` | What to do | | --------------------- | -------------------------------- | | `percentage_discount` | Apply the percentage in `value`. | | `absolute_discount` | Subtract the amount in `value`. | | `free_product` | Add the product in `product`. | ## How it is redeemed The same as in v1: with [`POST /v1/benefits/redeem`](https://docs.loybox.com.ar/api-reference/beneficios/canjear). Redemption has no version 2: the same code works for both. ## Errors | Code | When | | ----- | ---------------------------------------------------- | | `400` | The benefit was already used. | | `401` | The API key is invalid: it has no commerce attached. | | `404` | The benefit does not exist. | | `422` | The code is not a valid format. | # Redeem a benefit (https://docs.loybox.com.ar/en/api-reference/beneficios/canjear) Redeems the benefit using the code the member holds. It is the last step of the flow: from here on the code is burned and cannot be used again. Call this endpoint only once the sale is closed and the discount applied. If you call it earlier and the sale falls through, the member loses the reward and there is no way to give it back over the API. To see which reward it is without burning it, use [look up a code](https://docs.loybox.com.ar/api-reference/beneficios/consultar-codigo). ## Body The redemption code the member holds. ## Example ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/benefits/redeem \ -H "Authorization: Bearer $LOYBOX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "client_benefit_code": 887766 }' ``` ```json // 200 OK { "message": "Benefit redeemed successfully" } ``` ## Errors | Code | When | | ----- | ---------------------------------------------- | | `400` | The benefit was already used. | | `404` | The benefit does not exist. | | `422` | The field is missing, or it is not an integer. | It is what happens when someone tries to use the same code twice. It is not a bug in your integration: it is worth showing whoever is at the counter a clear "this code was already used" message instead of a generic error. # Authentication (https://docs.loybox.com.ar/en/api-reference/autenticacion) Sign-in for the **end user** with a one-time code sent by email. This is the section that lets you wire Loybox directly into your website's frontend, without going through your server. There are no passwords: the user enters their email, receives a 6-digit code, and that is it. ## The flow ### Request the code [`POST /v1/auth/otp/request`](https://docs.loybox.com.ar/api-reference/autenticacion/pedir-codigo) with the user's email. They receive a 6-digit code. The endpoint always answers `200`, even if that email has no account. ### Verify it [`POST /v1/auth/otp/verify`](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo) with the email and the code. It returns an access token (`access`) and a refresh token (`refresh`). If the email had no Loybox account, one is created; either way the user ends up subscribed to your commerce's program. ### Use the session From there on, calls to [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) go with the `Authorization: Bearer {access}` header. ### Renew it When the `access` expires, [`POST /v1/auth/refresh`](https://docs.loybox.com.ar/api-reference/autenticacion/renovar-token) returns a new one from the `refresh`, without asking the user for another code. ## Rules of the code * It expires in **10 minutes**. * It allows **5 attempts**. * Requesting a new code **invalidates the previous one**. ## The X-Commerce-Id header Every endpoint in this section and in [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) requires the `X-Commerce-Id` header with your commerce id: ``` X-Commerce-Id: {your-commerce-id} ``` That header is what scopes the response to your program: the user never sees data from other commerces. The commerce **API key** is a secret and goes on your server only. The **user's access token** is the one that can live in the browser. Never send the API key from the frontend. See [Credentials](https://docs.loybox.com.ar/api-reference/credenciales). ## The endpoints # Request a code (https://docs.loybox.com.ar/en/api-reference/autenticacion/pedir-codigo) Emails a 6-digit code so the end user can sign in. If the email has no Loybox account, the account is created when [verifying the code](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo), not here. It answers `200` even if the email does not exist. That is **deliberate**: if it answered differently, anyone could use this endpoint to find out which emails are registered. In your UI this means that after requesting the code you always show the same message ("we sent a code to your email"), with no way to know whether the account existed. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. It carries no `Authorization`: this is the endpoint the session starts with. ## Body The user's email. It has to be a valid email format. ## Example ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/auth/otp/request \ -H "X-Commerce-Id: 87" \ -H "Content-Type: application/json" \ -d '{ "email": "ana@example.com" }' ``` ```json // 200 OK { "message": "Código enviado" } ``` The `message` comes back from the API in Spanish. It is text for the developer, not for showing to the user (see [Errors](https://docs.loybox.com.ar/api-reference/errores)). ## Rules of the code * It expires in **10 minutes**. * It allows **5 attempts**. * Requesting a new code **invalidates the previous one**. ## Errors | Code | When | | ----- | --------------------------------------------------------------- | | `422` | The `X-Commerce-Id` header is missing, or the email is invalid. | # Verify the code (https://docs.loybox.com.ar/en/api-reference/autenticacion/verificar-codigo) Validates the code sent by email and returns the end user's session tokens. If the email had no account, **it creates one**. Either way it leaves the user subscribed to the program of the commerce named in `X-Commerce-Id`. The `access` it returns is the one used as `Authorization: Bearer {access}` on every [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) endpoint. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Body The same email the [code was requested with](https://docs.loybox.com.ar/api-reference/autenticacion/pedir-codigo). The 6-digit code received by email. Exactly 6 characters. ## Response A [Session](https://docs.loybox.com.ar/api-reference/objetos#sesión) object. ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/auth/otp/verify \ -H "X-Commerce-Id: 87" \ -H "Content-Type: application/json" \ -d '{ "email": "ana@example.com", "otp": "418302" }' ``` ```json // 200 OK { "access": "eyJhbGciOiJIUzI1NiIs...", "refresh": "eyJhbGciOiJIUzI1NiIs...", "expires_in": 3600, "user_id": 4821, "username": "Ana Pérez", "email": "ana@example.com", "phone": null } ``` Store both tokens. The `access` expires in `expires_in` seconds; the `refresh` is what later [renews it](https://docs.loybox.com.ar/api-reference/autenticacion/renovar-token) without asking the user for another code. There is no need to call [join the program](https://docs.loybox.com.ar/api-reference/mi-cuenta/adherirme) after this: the user is already subscribed. That endpoint is for re-joining after opting out. ## Errors | Code | When | | ----- | -------------------------------------------------------------- | | `400` | The code is invalid or expired. | | `422` | The `X-Commerce-Id` header is missing, or the body is invalid. | After 5 failed attempts the code stops working and you have to [request a new one](https://docs.loybox.com.ar/api-reference/autenticacion/pedir-codigo). # Renew the token (https://docs.loybox.com.ar/en/api-reference/autenticacion/renovar-token) Returns a new access token from the refresh token obtained when [verifying the code](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo), without needing to ask the user for a new code. It is what makes the session feel continuous: when a call to [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) returns `401`, you renew and retry. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Body The refresh token returned by [verifying the code](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo). ## Response The new access token. Seconds the new token stays valid. ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/auth/refresh \ -H "X-Commerce-Id: 87" \ -H "Content-Type: application/json" \ -d '{ "refresh": "eyJhbGciOiJIUzI1NiIs..." }' ``` ```json // 200 OK { "access": "eyJhbGciOiJIUzI1NiIs...", "expires_in": 3600 } ``` The response carries only the `access`. The `refresh` you already had is still the valid one: keep it and keep using it. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------- | | `401` | The refresh token is invalid or expired. | | `422` | The `X-Commerce-Id` header is missing, or the `refresh` field is missing. | A `401` here means the session really ended: you have to [request a code](https://docs.loybox.com.ar/api-reference/autenticacion/pedir-codigo) again. # My account (https://docs.loybox.com.ar/en/api-reference/mi-cuenta) Endpoints for the **end user**, authenticated with the access token returned by [verifying the code](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo): ``` Authorization: Bearer {access} X-Commerce-Id: {your-commerce-id} ``` Everything they return is scoped to the commerce in the `X-Commerce-Id` header: points, benefits, history and tier belong to that program and nothing else. The same user can be in several Loybox programs, and each one only sees its own. ## The typical circuit This is how a loyalty website is built with these endpoints: ### The first render [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener) brings the points, the commerce's branding and the points about to expire, all at once. With a single call you paint the header and the balance. ### The catalog [`GET /v1/me/benefits/available`](https://docs.loybox.com.ar/api-reference/mi-cuenta/beneficios-disponibles) to show what they can redeem. ### The purchase [`POST /v1/me/benefits/exchange`](https://docs.loybox.com.ar/api-reference/mi-cuenta/comprar-beneficio) trades points for a benefit. ### The codes [`GET /v1/me/benefits`](https://docs.loybox.com.ar/api-reference/mi-cuenta/mis-beneficios) to show them the codes they hold to present at the commerce. ## When building the UI Three things that save round trips: * Each of the user's benefit `client_benefit_code` is **also the coupon code**: in an online store it is what the user pastes at checkout. * Benefits carry `benefit_type`, which separates catalog ones (`normal`) from the special rewards (`welcome`, `birthday`, `monthly_top`, `level`), and `color`, the commerce's brand color. * **How much the user is short** for a benefit is the benefit's `cost` minus the `points` from [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener). ## Buying and redeeming are not the same | | Buying | Redeeming | | ---------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------- | | **What it does** | Trades points for a benefit | Uses the benefit at the commerce | | **Who calls it** | The user, from your website | Your server, at the sale | | **Endpoint** | [`POST /v1/me/benefits/exchange`](https://docs.loybox.com.ar/api-reference/mi-cuenta/comprar-beneficio) | [`POST /v1/benefits/redeem`](https://docs.loybox.com.ar/api-reference/beneficios/canjear) | | **Credential** | End-user token | Commerce API key | ## The endpoints ## The 401 across the whole section All of these endpoints return `401` when the access token is missing, expired, or does not belong to an end user. It is the normal case once time has passed: [renew it](https://docs.loybox.com.ar/api-reference/autenticacion/renovar-token) and retry the call. # My account (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/obtener) Everything the frontend needs on the first render: the user's data, their points and subscription in the program of the commerce named in `X-Commerce-Id`, the commerce's branding data (name, logo, color, category) and the points about to expire. It is the call the app starts with. There is no need to fetch the commerce's data separately: it comes inside. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Response A [My account](https://docs.loybox.com.ar/api-reference/objetos#mi-cuenta) object. ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK { "username": "Ana Pérez", "email": "ana@example.com", "phone": null, "points": 340, "subscribed": true, "commerce": { "id": 87, "name": "Tienda Central", "logo": "https://cdn.loybox.com.ar/logos/87.png", "color": "#f1a10d", "category_name": "Tienda de comics", "currency": "ARS" }, "points_expiration": { "points": 120, "expiration_date": "2026-09-30T23:59:59Z", "days_left": 37, "months_left": 1, "mode": "accumulated" } } ``` What to do with each piece: | Field | What for | | ------------------- | ------------------------------------------------------------------------------------------------------------- | | `points` | The big balance on the screen. It is what each benefit's `cost` is compared against. | | `subscribed` | If it comes back `false`, show the call to [join](https://docs.loybox.com.ar/api-reference/mi-cuenta/adherirme) instead of the catalog. | | `commerce` | Logo, name and color to paint the program's branding. | | `points_expiration` | The "X points expire in Y days" notice. | `points_expiration` does not come back `null`: it comes with `mode: "none"` and `points: 0`. Check the `mode` before showing the expiration notice. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------ | | `401` | The access token is missing, expired, or does not belong to an end user. | | `422` | The `X-Commerce-Id` header is missing. | # Benefits I can buy (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/beneficios-disponibles) The commerce's catalog of live benefits, which the user can buy with their points. To know which ones they can afford, compare each benefit's `cost` with the `points` from [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener). The API does not filter by balance: it returns the catalog and the UI decides what to show as reachable and what as "you need N more points". ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Response An array of [Benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio). ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/benefits/available \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK [ { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": { "type": "percentage_discount", "title": "20% off", "description": "Válido en toda la tienda", "value": 20, "product": null, "expiration": "2026-12-31T23:59:59Z", "image": null }, "tiendanube_coupon": null } ] ``` Each item's `id` is what you send as `benefit_id` to [buy a benefit](https://docs.loybox.com.ar/api-reference/mi-cuenta/comprar-beneficio). To show the catalog to a visitor who has not signed in yet there is [`GET /v1/public/benefits`](https://docs.loybox.com.ar/api-reference/publico/beneficios), which needs no token. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------ | | `401` | The access token is missing, expired, or does not belong to an end user. | | `422` | The `X-Commerce-Id` header is missing. | # Buy a benefit (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/comprar-beneficio) Trades the user's points for a catalog benefit. It returns the purchased benefit with its `client_benefit_code`, which is the code later redeemed at the commerce. It is the only [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) call that moves points. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. A key so a retry does not charge the points twice. If the network drops after the server processed the purchase, your retry can charge the points again. With the `Idempotency-Key`, sending the same key again does not repeat the purchase. Generate one value per purchase the user starts (a UUID is enough) and use the same one across every retry of that purchase. ## Body Id of the benefit to buy, exactly as [benefits I can buy](https://docs.loybox.com.ar/api-reference/mi-cuenta/beneficios-disponibles) returns it. ## Response A [Redeemable benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio-canjeable) object. ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/benefits/exchange \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" \ -H "Idempotency-Key: 8f14e45f-ea0f-4d1c-9a1b-2c3d4e5f6a7b" \ -H "Content-Type: application/json" \ -d '{ "benefit_id": "b_9f2a" }' ``` ```json // 200 OK { "client_benefit_code": 887766, "issue_date": "2026-08-24T13:05:00Z", "due_date": "2026-09-23T13:05:00Z", "used": false, "benefit": { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": null, "tiendanube_coupon": null } } ``` The `client_benefit_code` is what to show the user: it is their redemption code and also the coupon code in an online store. After buying, it is worth refreshing the `points` with [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener). ## Errors | Code | When | | ----- | -------------------------------------------------------------------------- | | `400` | The benefit does not exist, is not valid, or the user's points fall short. | | `401` | The access token is missing, expired, or does not belong to an end user. | | `422` | The `X-Commerce-Id` header is missing, or the `benefit_id` is missing. | The `400` bundles all three cases, so it is worth preventing them in the UI: do not offer to buy a benefit whose `cost` exceeds the user's points. # My benefits (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/mis-beneficios) Benefits the user already bought with their points at this commerce and can still redeem. Each item's `client_benefit_code` is the code the user presents at the commerce to redeem it. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Response An array of [Redeemable benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio-canjeable). ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/benefits \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK [ { "client_benefit_code": 887766, "issue_date": "2026-08-24T13:05:00Z", "due_date": "2026-09-23T13:05:00Z", "used": false, "benefit": { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": null, "tiendanube_coupon": null } } ] ``` In an online store, the `client_benefit_code` is what the user pastes at checkout. It is worth showing it large and with a copy button, and the `due_date` next to it so they know how long they have to use it. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------ | | `401` | The access token is missing, expired, or does not belong to an end user. | | `422` | The `X-Commerce-Id` header is missing. | # My history (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/historial) The user's activity in the commerce's program: consumptions that earned points, benefit purchases, redemptions and special rewards. Cursor paginated: to fetch the next page you pass the previous response's `next_cursor` in `?cursor=`. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Parameters Cursor of the page to fetch. It comes from the previous response's `next_cursor`. Left unspecified, it returns the first page. ## Response This page's items. See [Activity item](https://docs.loybox.com.ar/api-reference/objetos#movimiento). Passed as `?cursor=` to fetch the next page. `null` when there are no more. The previous page's cursor. ## Example ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/activity \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK { "results": [ { "type": "consumption", "date": "2026-08-20T18:42:00Z", "points": 17, "benefit": null, "amount": 1750, "event": null, "additional_note": null }, { "type": "benefit_exchange", "date": "2026-08-24T13:05:00Z", "points": -250, "benefit": { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": null, "tiendanube_coupon": null }, "amount": null, "event": null, "additional_note": null } ], "next_cursor": "eyJkIjoiMjAyNi0wOC0yMCJ9", "previous_cursor": null } ``` ## The four activity types | `type` | What happened | Fields it carries | | ----------------------- | --------------------------------------- | ------------------------------ | | `consumption` | A purchase that earned points | `amount`, `points` | | `benefit_exchange` | They bought a benefit with points | `benefit`, `points` (negative) | | `benefit_usage` | They redeemed a benefit at the commerce | `benefit` | | `points_special_reward` | An automatic reward gave them points | `event`, `points` | Since which fields come filled in depends on the `type`, it is worth building the history row with a `switch` on `type` instead of always reading every field. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------ | | `401` | The access token is missing, expired, or does not belong to an end user. | | `422` | The `X-Commerce-Id` header is missing. | # My tier (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/nivel) The user's current tier at this commerce, with their points multiplier, their accumulated progress and which tier comes next. The endpoint and its fields say `level`; this documentation says "tier", which is the product's term in English. It is the same thing. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Response A [Tier](https://docs.loybox.com.ar/api-reference/objetos#nivel) object. ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/level \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK { "name": "Plata", "rank": 2, "points_multiplier": 1.25, "icon_url": "https://cdn.loybox.com.ar/levels/plata.png", "reached_at": "2026-05-11T10:00:00Z", "expiration_date": "2027-05-11T10:00:00Z", "is_expired": false, "next_level": { "name": "Oro", "rank": 3, "threshold_type": "points", "threshold": 5000 }, "total_earned_points": 3120, "total_spent_amount": 312000, "total_consumptions_count": 48 } ``` The tier names in the example (`Plata`, `Oro`) are the ones the commerce typed. They are data, not interface: Loybox does not translate them. ## How to build the progress bar Progress is calculated against the lifetime accumulated figure, not against the balance. Depending on the next tier's `threshold_type`: | `threshold_type` | Compare it with | | ---------------- | --------------------- | | By points | `total_earned_points` | | By amount spent | `total_spent_amount` | The tier is measured over the full history of the relationship, so spending points lowers the balance but never the tier. See [How members move up](https://docs.loybox.com.ar/niveles/como-suben-de-nivel). ## Errors | Code | When | | ----- | --------------------------------------------------------------------------------------- | | `401` | The access token is missing, expired, or does not belong to an end user. | | `404` | The user has no tier assigned at this commerce yet, or the commerce does not use tiers. | | `422` | The `X-Commerce-Id` header is missing. | Do not treat it as a failure. When the user has no tier yet, or the commerce does not use tiers, the right move is to **hide the tiers section** in the UI, not to show an error. # Program rewards (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/recompensas) Rewards the commerce hands out on its own when something happens: the welcome one on joining, the birthday one, the member-of-the-month one. Each one says whether it gives a benefit or points. It exists to show the user what they get **beyond** redeeming points. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Response An array of [Automatic reward](https://docs.loybox.com.ar/api-reference/objetos#recompensa-automática). ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/rewards \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK [ { "event": "welcome", "reward_type": "benefit", "benefit": { "id": "b_4c81", "type": "free_product", "description": "Café de regalo", "cost": 0, "expiration": null, "benefit_type": "welcome", "color": "#f1a10d", "buy_limit": 1, "prize": null, "tiendanube_coupon": null }, "points": null }, { "event": "birthday", "reward_type": "points", "benefit": null, "points": 200 } ] ``` ## The three events | `event` | When it is handed out | | ------------- | ---------------------------------------------- | | `welcome` | On joining the program | | `birthday` | On the member's birthday | | `monthly_top` | To the member who bought the most in the month | The `reward_type` says where to look: if it is `benefit`, the reward is in `benefit`; if it is `points`, it is in `points`. The other field comes back `null`. It returns the rewards the commerce **configured**, not the ones the user already received. For that there is [my history](https://docs.loybox.com.ar/api-reference/mi-cuenta/historial), where point rewards show up as `points_special_reward` items. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------ | | `401` | The access token is missing, expired, or does not belong to an end user. | | `404` | The commerce does not exist. | | `422` | The `X-Commerce-Id` header is missing. | # Join the program (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/adherirme) Subscribes the user to the commerce's loyalty program. If the commerce configured a welcome reward, it comes back in `welcome_benefit` or `welcome_points`. [Verifying a code](https://docs.loybox.com.ar/api-reference/autenticacion/verificar-codigo) already leaves the user subscribed, so this endpoint is **mostly for re-joining after opting out**. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. It carries no body. ## Response The operation's result. The welcome benefit, if the commerce configured one and the user just joined. See [Benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio). Welcome points, if the commerce configured points instead of a benefit. ```bash curl -X POST https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/subscription \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK { "message": "Subscribed successfully", "welcome_benefit": { "id": "b_4c81", "type": "free_product", "description": "Café de regalo", "cost": 0, "expiration": null, "benefit_type": "welcome", "color": "#f1a10d", "buy_limit": 1, "prize": null, "tiendanube_coupon": null }, "welcome_points": null } ``` The two welcome fields are mutually exclusive: one or the other comes back, depending on what the commerce configured. If it configured nothing, both come back `null`. This is a good moment to show a welcome screen: if `welcome_benefit` came, the reward; if `welcome_points` came, the points they just earned. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------ | | `401` | The access token is missing, expired, or does not belong to an end user. | | `404` | The commerce does not exist. | | `422` | The `X-Commerce-Id` header is missing. | # Opt out (https://docs.loybox.com.ar/en/api-reference/mi-cuenta/darme-de-baja) Unsubscribes the user from the commerce's program. The accumulated points stay where they are: if the user [joins again](https://docs.loybox.com.ar/api-reference/mi-cuenta/adherirme), they are still there. It is worth saying so on the confirmation screen: it is the difference between opting out and being deleted, and knowing it makes opting out less frightening. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. It carries no body. ## Response `200 OK`. The response has no defined shape: looking at the status code is enough. ```bash curl -X DELETE https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/me/subscription \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "X-Commerce-Id: 87" ``` After opting out, [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener) returns `subscribed: false`. ## Errors | Code | When | | ----- | ------------------------------------------------------------------------ | | `401` | The access token is missing, expired, or does not belong to an end user. | | `404` | The commerce does not exist, or the user was not subscribed. | | `422` | The `X-Commerce-Id` header is missing. | The `404` also covers a repeated opt-out: if the user was no longer subscribed, there is nothing to unsubscribe. # Public (https://docs.loybox.com.ar/en/api-reference/publico) Endpoints that **require no token at all**, only the `X-Commerce-Id` header. They exist to show your loyalty program to a visitor who has not signed in yet: the branding in the header and the reward catalog, so they can see what they get by joining. ``` X-Commerce-Id: {your-commerce-id} ``` ## The endpoints ## After sign-in there is no need to ask again Once the user signs in, the same data comes back through the [My account](https://docs.loybox.com.ar/api-reference/mi-cuenta) endpoints: | Signed out | Signed in | | -------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | [`GET /v1/public/commerce`](https://docs.loybox.com.ar/api-reference/publico/comercio) | Comes inside [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener) | | [`GET /v1/public/benefits`](https://docs.loybox.com.ar/api-reference/publico/beneficios) | [`GET /v1/me/benefits/available`](https://docs.loybox.com.ar/api-reference/mi-cuenta/beneficios-disponibles) | In practice: use the public ones for the welcome screen, and switch to the My account ones as soon as there is a session. It goes in the frontend without a problem. What it does is scope the response to your commerce, not authorize access. # Commerce data (https://docs.loybox.com.ar/en/api-reference/publico/comercio) The commerce's name, logo, brand color and category, **with no token needed**. It exists to paint the program's header before the user signs in. ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Response A [Commerce](https://docs.loybox.com.ar/api-reference/objetos#comercio) object. ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/public/commerce \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK { "id": 87, "name": "Tienda Central", "logo": "https://cdn.loybox.com.ar/logos/87.png", "color": "#f1a10d", "category_name": "Tienda de comics", "currency": "ARS" } ``` Once signed in, the same data comes inside [`GET /v1/me`](https://docs.loybox.com.ar/api-reference/mi-cuenta/obtener) in the `commerce` field, so there is no need to ask for it again. ## Errors | Code | When | | ----- | -------------------------------------- | | `400` | The commerce could not be fetched. | | `422` | The `X-Commerce-Id` header is missing. | # Benefit catalog (https://docs.loybox.com.ar/en/api-reference/publico/beneficios) The commerce's live benefits, **with no token needed**. It exists to show the loyalty program to a visitor who has not signed in yet: the shop window of rewards that answers "what do I get if I join?". ## Headers Id of the commerce integrating the API. Every response is scoped to this commerce. ## Response An array of [Benefit](https://docs.loybox.com.ar/api-reference/objetos#beneficio). ```bash curl https://loybox-public-api-752998171300.southamerica-west1.run.app/v1/public/benefits \ -H "X-Commerce-Id: 87" ``` ```json // 200 OK [ { "id": "b_9f2a", "type": "percentage_discount", "description": "20% de descuento en toda la tienda", "cost": 250, "expiration": "2026-12-31T23:59:59Z", "benefit_type": "normal", "color": "#f1a10d", "buy_limit": 0, "prize": { "type": "percentage_discount", "title": "20% off", "description": "Válido en toda la tienda", "value": 20, "product": null, "expiration": "2026-12-31T23:59:59Z", "image": null }, "tiendanube_coupon": null } ] ``` Once signed in it is better to use [`GET /v1/me/benefits/available`](https://docs.loybox.com.ar/api-reference/mi-cuenta/beneficios-disponibles), which is the same catalog but already filtered by what the commerce enabled for that user. ## Errors | Code | When | | ----- | --------------------------------------------- | | `400` | The commerce's benefits could not be fetched. | | `422` | The `X-Commerce-Id` header is missing. |