✦ Loyalty+

Documentation

Contents

Integration API

A REST API for connecting your own systems — a POS, a booking app, a back-office script — to your loyalty account. Every request is scoped to your tenant automatically; you can only ever see or change your own data.

Authentication

Send your API key (Settings → API key) as an x-api-key header on every request. Generate or rotate it in Settings. Rotating immediately invalidates the old key.

curl https://loyaltyplus.app/v1/api/account \
  -H 'x-api-key: loy_your_key_here'

Base URL: https://loyaltyplus.app/v1/api  ·  All request/response bodies are JSON. A missing or invalid key returns 401; a suspended account 403; an account without an active subscription 402.

Account

GET/v1/api/account

Your account summary, including country and whether reward SMS is currently deliverable (point 1 — check pool/BYO coverage programmatically).

GET /v1/api/account

{
  "tenantId": "clx...",
  "name": "My Cafe",
  "plan": "PRO",
  "subscriptionStatus": "active",
  "countryCode": "IE",
  "sms": { "deliverable": true, "method": "pool", "poolAvailable": true }
}

Customers

GET/v1/api/customers

List customers. Query params: search, status (ACTIVE|INACTIVE), page, limit (max 100). Each row includes the live points balance (summed from the ledger).

curl "https://loyaltyplus.app/v1/api/customers?search=jane&limit=20" \
  -H 'x-api-key: loy_your_key_here'

POST/v1/api/customers

Create a customer. Only name is required. initialPoints writes an opening ledger entry.

curl -X POST https://loyaltyplus.app/v1/api/customers \
  -H 'x-api-key: loy_your_key_here' \
  -H 'Content-Type: application/json' \
  -d '{ "name": "Jane Doe", "phone": "+15551234567", "notes": "VIP", "initialPoints": 10 }'

GET/v1/api/customers/lookup

Find one customer by phone number and get their points balance and reward status in a single call. The phone can be in any common format (087 123 4567, +353871234567, …) — it is normalized server-side.

curl "https://loyaltyplus.app/v1/api/customers/lookup?phone=%2B353871234567" \
  -H 'x-api-key: loy_your_key_here'

{
  "customer": { "id": "…", "name": "Jane Doe", "phone": "+353871234567", "status": "ACTIVE" },
  "totalPoints": 40,
  "rewardAvailable": false,
  "rewardThreshold": 100,
  "rewardTitle": "Free Reward"
}

GET/v1/api/customers/{id}

One customer with visit history, points ledger, and recent redemptions.

PATCH/v1/api/customers/{id}

Update a customer. Send only the fields you want to change: name, phone, notes, status.

curl -X PATCH https://loyaltyplus.app/v1/api/customers/clx123 \
  -H 'x-api-key: loy_your_key_here' \
  -H 'Content-Type: application/json' \
  -d '{ "status": "INACTIVE" }'

DELETE/v1/api/customers/{id}

Irreversible. Permanently deletes the customer and their identities/ledger. There is no undo.

Adjust points

POST/v1/api/customers/{id}/points

Add or remove points. points may be negative to deduct. Balances are never stored directly — this writes one ledger entry, so history stays auditable. reason is a free-text label; storeId is optional (defaults to your first store).

curl -X POST https://loyaltyplus.app/v1/api/customers/clx123/points \
  -H 'x-api-key: loy_your_key_here' \
  -H 'Content-Type: application/json' \
  -d '{ "points": 50, "reason": "In-store purchase" }'

Reward rules

GET/v1/api/reward-rules

List reward rules. A rule sets how points are earned (per visit / per unit / per spend) and the reward threshold. Store-specific rules override the tenant default.

POST/v1/api/reward-rules

Create a rule. Example: earn 1 point per visit, reward at 10 visits.

curl -X POST https://loyaltyplus.app/v1/api/reward-rules \
  -H 'x-api-key: loy_your_key_here' \
  -H 'Content-Type: application/json' \
  -d '{
    "earningMode": "PER_VISIT",
    "pointsPerVisit": 1,
    "visitRewardThreshold": 10,
    "rewardTitle": "Free coffee",
    "cooldownMinutesPerCheckin": 60
  }'

GET/v1/api/reward-rules/{ruleId}

Fetch a single rule.

PATCH/v1/api/reward-rules/{ruleId}

Update a rule (send only changed fields).

DELETE/v1/api/reward-rules/{ruleId}

Irreversible. Deletes a reward rule.

GET/v1/api/reward-tiers

List reward tiers (multi-level rewards: points required + title per tier).

Reporting (read-only)

GET/v1/api/dashboard/stats

Headline metrics: active customers, points issued, redemptions, recent activity.

GET/v1/api/redemptions

List redemptions for your tenant.

GET/v1/api/redemptions/by-code/{redeemCode}

Look up a single redemption by its code — useful for validating a code a customer presents at the counter.

AI agents (MCP)

You can hand your loyalty account to an AI assistant — Claude, ChatGPT, or any agent that supports the Model Context Protocol — and ask it things like “check the points for 087 123 4567”, “list my top customers”, or “what rewards do we currently offer?”.

Give the agent two things:

  • MCP endpoint: https://loyaltyplus.app/v1/api/mcp
  • Header: x-api-key: loy_your_key_here (Settings → API key)

The agent gets tools for looking up customers by phone, listing/searching customers, reading rewards and stats, creating customers, and adjusting points. Everything is scoped to your business — the agent can never see another tenant's data, and every points change is written to the auditable ledger.

Agents that prefer plain REST can read the machine-readable docs instead: /llms.txt (guide for LLMs) and /openapi.json (OpenAPI 3.1).

A note on trust: the API key gives an agent the same power you have, including deleting customers. Only connect agents you trust, and rotate the key in Settings if in doubt.

SMS notifications

SMS is the last-resort channel: when a customer earns a reward we try the free channels first — web push, then Telegram — then WhatsApp, and only send an SMS if none of those reached the customer. A customer never gets the same notification twice, and customers without a saved phone number never get SMS at all. Enable/disable the channel in Settings → Notifications.

There are two sending engines (Settings → SMS):

  • Included pooled sending — we send from our own per-country senders (a local number or a registered name like "AlexLabs"). 100 messages/month are included in your subscription; beyond that, prepaid credit packs apply (valid 12 months). Only countries on our coverage list are available — the country picker in Settings lists exactly those. Pooled texts are domestic-only: they go to numbers in your selected country; customers with foreign numbers are skipped.
  • My own provider (BYO) — connect your own Telnyx, Twilio or DIDWW account. Works in any country, to any destination, uncapped — billed by your provider.

Use the Send a test SMS button in Settings → SMS to verify your setup end-to-end — it takes the exact path a real reward text takes (and costs one message, like a real one).

Getting Telnyx credentials: sign up at telnyx.com, buy or port a number, then generate an API key from Portal → API Keys. The "Sender ID / number" is the Telnyx number (E.164, e.g. +15551234567) you send from.

Getting Twilio credentials: your Account SID and Auth Token are on the Twilio Console dashboard. The "Messaging Service SID" comes from Console → Messaging → Services (starts with MG) — required.

Getting DIDWW credentials: in the DIDWW panel, create an SMS HTTP OUT trunk (SMS trunks → Create) and use its generated username/password — not your account API key. The sender number must be a DIDWW DID with outbound P2P SMS enabled (ask DIDWW support to activate outbound SMS on your account if the option is missing).

If neither a covered pool country nor a BYO account is configured, reward SMS is silently skipped (push still works) — no error is shown to the customer.

API key

The API key authenticates the Integration API above (/v1/api/*) — sent as the x-api-key header, no owner login needed.

Rotating in Settings immediately invalidates the previous key — update every system using the old one at the same time, or their requests start failing with 401.

Treat it like a password. Store it securely on generation.

Integrations

Each provider in Integrations has its own "Docs ↗" link to that provider's setup docs. Webhook-based providers generate a unique webhook URL after your first Save — copy it into the provider's dashboard, then paste back their signing key and Save again to activate.

Billing

Subscription status, plan, and payment method are managed through the Stripe customer portal — click "Manage billing" on the Billing page. Changes there (card updates, cancellation) sync back automatically via webhook within a few seconds.