> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.brevo.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.brevo.com/_mcp/server.

# Best practices

## Integration best practices

**Always enroll before crediting**

Attempting to create a transaction for a contact who is not subscribed to the program returns a `422`. Enroll the contact first, then credit points.

**Use `loyaltySubscriptionId` as your bridge**

Set `loyaltySubscriptionId` to your own customer ID at enrollment time. This lets you reference the member by your internal ID throughout the integration and pass it in eCommerce order `identifiers` — without maintaining a separate ID mapping table.

**Use `autoComplete: false` for purchase flows, `autoComplete: true` for instant rewards**

Purchase points should only be confirmed after the order is validated. Bonus credits (sign-up, birthday, referral) have no approval step and can be auto-completed.

**Store transaction IDs**

Always persist the `id` returned by Create transaction or Create balance order. You need it to call `/complete` or `/cancel`. If you lose it, you will need to query the transaction list to retrieve it.

**Use `meta` to store your business context**

Pass `orderId`, `campaignId`, or any relevant reference in the `meta` field. This makes debugging and auditing easier and keeps your transaction history self-documenting.

**Never call Complete on an already-completed transaction**

This returns a `422`. Check the transaction status before completing: if it is not `pending`, skip the call.

---

## Performance considerations

**Parallelize read calls**

The balance, tier, and voucher read endpoints are independent. Use concurrent requests to build your loyalty widget — do not chain them sequentially. See [Read member data](/docs/loyalty-member-data) for an example.

**Cache member data for display purposes**

Balance and tier data do not change in real time on your frontend. Cache responses for 30–60 seconds to reduce API calls on high-traffic account pages.

**Use webhooks instead of polling**

Never poll the transaction endpoint to detect completion. Use the `balance_value_updated` webhook to trigger downstream actions. See [Loyalty webhooks](/docs/loyalty-webhooks).

**Set appropriate `ttl` on pending transactions**

If your order confirmation flow takes up to 24 hours, set `ttl: 1440` (minutes). This prevents orphaned `pending` transactions from accumulating if your system fails to call `/complete` or `/cancel`.

---

## Security best practices

**Keep API keys server-side**

Never expose your `api-key` in browser JavaScript, mobile app binaries, or public repositories. All Loyalty API calls must originate from your backend.

**Validate webhook signatures**

Configure [secure webhook calls](/docs/secured-webhooks) with username and password authentication to verify that incoming webhooks originate from Brevo.

**Scope API keys by environment**

Use separate API keys for staging and production. Rotate keys immediately if you suspect exposure.

**Audit `meta` fields**

Treat `meta` as an internal field — never expose it raw to end users, as it may contain internal order references or pricing data.

---

## Use cases

#### Points on purchase (eCommerce)

A fashion retailer credits 1 point per €1 spent on confirmed orders.

```
1. Customer places order → POST /loyalty/.../create-order (amount = order total, status: pending)
2. Order is confirmed   → POST .../transactions/{tid}/complete (balance updated, tier re-evaluated)
3. Customer cancels     → POST .../transactions/{tid}/cancel (no balance change)
4. Customer returns     → POST .../transactions (negative amount) → /complete
5. Webhook balance_value_updated → trigger "You earned 89 points" email
6. Webhook tier_association_updated → trigger "Welcome to Gold" email + voucher
```

#### Referral program

A beauty brand gives 200 points to a member who refers a friend who completes their first purchase.

```
1. Friend signs up and makes first purchase → your backend detects referral
2. POST .../transactions (amount: 200, autoComplete: true, meta: { referredContactId: 99999 })
3. Webhook balance_value_updated → trigger "You earned 200 referral points" push notification
```

#### Birthday reward

A loyalty program sends a 50-point bonus 7 days before a member's birthday.

```
1. Configure a rule in Brevo: "7 days before birthday → attribute reward"
   (Brevo Loyalty UI or via the Rules API)
2. Webhook balance_value_updated fires on the birthday event
3. Trigger a personalized birthday email with voucher code from GET .../vouchers
```

#### Loyalty widget on account page

A retailer displays a loyalty status block on the customer account page.

```javascript
// Node.js — parallel API calls
const [balances, tier, vouchers] = await Promise.all([
  fetch(`${BASE}/subscriptions/${contactId}/balances`, { headers }),
  fetch(`${BASE}/subscriptions/${contactId}/tier`,     { headers }),
  fetch(`${BASE}/subscriptions/${contactId}/vouchers`, { headers }),
]);

// Render: "340 pts · Silver · 160 pts to Gold · 1 reward available"
```

#### Points expiry re-engagement

A program where points expire after 12 months. Trigger a winback campaign 30 days before expiry.

```
1. Configure expiry reminder on balance definition (30 days before expiry)
2. Webhook balance_expiration_reminder fires
3. Trigger automation: "Your 340 points expire in 30 days — shop now"
4. If member doesn't act: webhook balance_value_expired fires
5. Trigger winback: "Your points expired — here's 50 bonus points to come back"
   → POST .../transactions (amount: 50, autoComplete: true)
```

---

## Additional resources

| Resource                                     | Link                                                                      |
| -------------------------------------------- | ------------------------------------------------------------------------- |
| Loyalty API Reference — Program              | [API reference](/reference/get-lp-list)                                   |
| Loyalty API Reference — Balance              | [API reference](/reference/get-balance-definition-list)                   |
| Loyalty API Reference — Tier                 | [API reference](/reference/get-loyalty-program-tier)                      |
| Loyalty webhooks                             | [Guide](/docs/loyalty-webhooks)                                           |
| eCommerce orders guide                       | [Guide](/docs/import-your-orders)                                         |
| Contacts API guide                           | [Guide](/docs/synchronise-contact-lists)                                  |
| Authentication                               | [Guide](/docs/authentication-schemes)                                     |
| Rate limits                                  | [Guide](/docs/api-limits)                                                 |
| Webhooks getting started                     | [Guide](/docs/how-to-use-webhooks)                                        |
| Brevo Help Center — Set up a loyalty program | [help.brevo.com](https://help.brevo.com/hc/en-us/articles/28562151712146) |