Developers · Customers & loyalty

Your customer database — with the API you wish it had.

Read every customer profile. Pull the full order history. Query loyalty progress. Target a marketing segment by cohort. Issue, redeem and expire vouchers. Everything the dashboard does, your code can do too.

One customer record. Every channel they’ve ever ordered from, every penny they’ve ever spent, every point they’ve ever earned.

Customer, contact preferences, loyalty, vouchers.

A customer carries name, email, phone, addresses, contact preferences, external identifiers and computed totals (orders, spend, last order date). Loyalty tracks points balance, current tier and progress to the next. Vouchers are issued against customers or against generic codes; redemption is recorded on the order.

Reads — Queries API

  • GET /organizations/{orgId}/customers
  • GET /organizations/{orgId}/customers/{id}
  • GET /organizations/{orgId}/customers/source/{source}
  • GET /organizations/{orgId}/customers/{id}/orders
  • GET /organizations/{orgId}/customers/{id}/loyalty-tier-progress
  • GET /organizations/{orgId}/customers/marketing
  • GET /organizations/{orgId}/vouchers
  • GET /organizations/{orgId}/loyalty-schemes

Writes — Commands API

  • POST /organizations/{orgId}/customers
  • PUT /organizations/{orgId}/customers/{id}
  • PUT /organizations/{orgId}/customers/{id}/contact-preferences
  • POST /organizations/{orgId}/customers/{id}/loyalty/adjust
  • POST /organizations/{orgId}/vouchers
  • POST /organizations/{orgId}/vouchers/{id}/issue

Six things every CRM integration needs.

1. Find a customer by email

Paginated search across the customer base. Full-text search matches name, email or phone. Use locationId to scope to a single store.

GET
Request
GET /organizations/{organizationId}/customers?search=sam.patel%40example.com&page=1&pageSize=10
Authorization: Bearer <access_token>
Response — 200 OK
{
  "page": 1,
  "pageSize": 10,
  "totalCount": 1,
  "values": [
    {
      "id": "b3a9c1d4-7e2f-4a1c-9a82-6e41c0a8f33d",
      "firstName": "Sam",
      "lastName": "Patel",
      "emailAddress": "sam.patel@example.com",
      "totalOrders": 42,
      "totalSpend": { "currency": "GBP", "amount": 864.20 },
      "lastOrderDate": "2026-04-14T19:22:00Z",
      "loyaltyPoints": 864
    }
  ]
}

2. Create a customer from an external system

Import from your own CRM, your mailing list tool or a signup kiosk. Include external identifiers so you can round-trip later via /customers/source/{source}. Contact preferences default to OperationalOnly — marketing consent is explicit.

POST
Request
POST /organizations/{organizationId}/customers
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "firstName": "Priya",
  "lastName": "Shah",
  "emailAddress": "priya.shah@example.com",
  "phoneNumber": "+447700900123",
  "contactPreferences": "FirstPartyMarketing",
  "identifiers": [
    { "scheme": "Mailchimp", "value": "mc_5f2ab9…" }
  ]
}
Response — 201 Created
{
  "id": "e4f1d2a9-8c7b-4a1e-92ab-d41c5fa80e39",
  "version": 1,
  "createdTimeUtc": "2026-04-19T15:04:12Z"
}

3. Pull a customer’s order history

Paginated order summaries sorted newest-first. Cross-channel — includes web, app, kiosk, phone and every aggregator the customer has ordered from. Use /recent-orders for the convenience version that returns the last ten.

GET
Request
GET /organizations/{organizationId}/customers/{id}/orders?page=1&pageSize=20
Authorization: Bearer <access_token>
Response — 200 OK
{
  "values": [
    { "id": "…", "reference": "#5482", "occasion": "Delivery", "channel": "Web",  "status": "Delivered", "total": 28.40, "createdTimeUtc": "2026-04-14T19:22:00Z" },
    { "id": "…", "reference": "#5410", "occasion": "Delivery", "channel": "App",  "status": "Delivered", "total": 19.10, "createdTimeUtc": "2026-04-05T20:13:00Z" },
    { "id": "…", "reference": "#5347", "occasion": "Collection", "channel": "UberEats", "status": "Delivered", "total": 22.90, "createdTimeUtc": "2026-03-27T18:55:00Z" }
  ]
}

4. Check a customer’s loyalty tier progress

Returns the current points balance, the active tier, the next tier and how many more points (or pounds spent, depending on the scheme) are required to cross the threshold. Perfect for a “X more to Gold” banner in your app.

GET
Request
GET /organizations/{organizationId}/customers/{id}/loyalty-tier-progress
Authorization: Bearer <access_token>
Response — 200 OK
{
  "customerId": "b3a9c1d4-…",
  "schemeName": "Classic",
  "currentPoints": 864,
  "currentTier":  { "name": "Silver", "threshold": 500 },
  "nextTier":    { "name": "Gold",   "threshold": 1000 },
  "pointsToNextTier": 136,
  "progressToNextTier": 0.728
}

5. Pull a marketing segment

Server-side segmentation. Choose a segment (All, New, Lazy, Lapsed) and Andromeda returns only customers who meet that definition at query time. Filter by location or location group. Marketing consent is enforced — customers without FirstPartyMarketing are never returned.

GET
AllOrdered within PeriodMonths
NewFirst ordered in last 30 days
LazyLast ordered 30–60 days ago
LapsedLast ordered 60–90 days ago
Request — lapsed customers at two locations
GET /organizations/{organizationId}/customers/marketing
    ?CustomerMarketingSelection=Lapsed
    &LocationIds=7f2b6c9e-1a4d-4f12-9b23-5c8e0d1a3b42
    &LocationIds=c4d1e27b-5a01-48fe-bef1-9e1d2c0a8733
    &page=1
    &pageSize=100
Authorization: Bearer <access_token>
Response — 200 OK
{
  "totalCount": 412,
  "values": [
    { "id": "…", "firstName": "Sam",   "emailAddress": "sam@…",   "lastOrderDate": "2026-02-14T19:22:00Z" },
    { "id": "…", "firstName": "Priya", "emailAddress": "priya@…", "lastOrderDate": "2026-02-05T12:03:00Z" }
  ]
}

6. Issue a personalised voucher

Create a voucher definition, then issue one against a specific customer. The code is unique, single-use by default, optionally time-boxed. When the customer redeems it at checkout, the discount is recorded on the order and the voucher state flips to Redeemed.

POST
Request
POST /organizations/{organizationId}/vouchers/{voucherId}/issue
Authorization: Bearer <access_token>
Content-Type: application/json

{
  "customerId": "b3a9c1d4-7e2f-4a1c-9a82-6e41c0a8f33d",
  "discount": { "type": "PercentOff", "value": 20 },
  "minimumSpend": { "currency": "GBP", "amount": 15.00 },
  "validFromUtc": "2026-04-20T00:00:00Z",
  "validToUtc":   "2026-05-20T23:59:59Z",
  "singleUse": true,
  "channels": ["Web", "App"]
}
Response — 201 Created
{
  "voucherIssueId": "19c2f1ab-5d3e-4ac8-b711-3f0d4e2a1b9c",
  "code": "WELCOME-BACK-3Q4R",
  "status": "Issued"
}

Keep going.

Build something on top of Andromeda.

Test environment, sandbox tenant, sample data, real endpoints. No commitment.