# 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.
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.
## 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.
## 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.
## 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.
## 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.
## 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. |