BETA: Please note that the current endpoints are considered beta. It is possible there may be changes before these endpoints are finalised.

Customers

Get a Customer

Get a customer

get /organizations/{organizationId}/customers/{customerId}

Parameters

NameTypeInDescription
organizationIdstringpathOrganization ID
customerIdstringpathCustomer ID

Responses

200: OK response.Customer
{
  "createdAt": "2021-10-20T14:51:16Z",
  "dob": "2021-10-20",
  "email": "john@example.com",
  "firstName": "John",
  "gender": "MALE",
  "hasAgreedToMarketing": true,
  "id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
  "lastName": "Smith",
  "phoneNumber": "+61411222333",
  "statistics": {
    "lastPointsEarnedAt": "2021-08-23T02:06:24.000Z",
    "lastPointsRedeemedAt": "2021-03-17T04:27:06.000Z",
    "lastSpentAt": "2021-08-23T02:06:23.000Z",
    "pointsBalance": 3125,
    "totalPointsEarned": 4523,
    "totalPointsRedeemed": 1398,
    "totalSpend": 3687
  },
  "updatedAt": "2021-10-21T18:34:45Z"
}
404: not_found: Not Found response.

List Customers

List all customers for an organization. The result list is paged by 1000 results. Use X-Next-Page to retrieve the next page of results

get /organizations/{organizationId}/customers

Parameters

NameTypeInDescription
organizationIdstringpathOrganization ID
afterstringqueryThe cursor to use for pagination. Do not use this field manually it will be automatically provided in the response headers (see Paging guide).
sortstringqueryHow to sort the returned customer list.
"created", "updated"
emailstringqueryGive a valid email address to search all customers - this will find and return a list of customers with the exact email address given.
phoneNumberstringqueryGive a valid phone number to search all customers. Note that we cannot guarantee unique key on phone numbers.

Responses

200: OK response.Customer[]
[
  {
    "createdAt": "2021-10-20T14:51:16Z",
    "dob": "2021-10-20",
    "email": "john@example.com",
    "firstName": "John",
    "gender": "MALE",
    "hasAgreedToMarketing": true,
    "id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
    "lastName": "Smith",
    "phoneNumber": "+61411222333",
    "statistics": {
      "lastPointsEarnedAt": "2021-08-23T02:06:24.000Z",
      "lastPointsRedeemedAt": "2021-03-17T04:27:06.000Z",
      "lastSpentAt": "2021-08-23T02:06:23.000Z",
      "pointsBalance": 3125,
      "totalPointsEarned": 4523,
      "totalPointsRedeemed": 1398,
      "totalSpend": 3687
    },
    "updatedAt": "2021-10-21T18:34:45Z"
  },
  {
    "createdAt": "2021-10-20T14:51:16Z",
    "dob": "2021-10-20",
    "email": "john@example.com",
    "firstName": "John",
    "gender": "MALE",
    "hasAgreedToMarketing": true,
    "id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
    "lastName": "Smith",
    "phoneNumber": "+61411222333",
    "statistics": {
      "lastPointsEarnedAt": "2021-08-23T02:06:24.000Z",
      "lastPointsRedeemedAt": "2021-03-17T04:27:06.000Z",
      "lastSpentAt": "2021-08-23T02:06:23.000Z",
      "pointsBalance": 3125,
      "totalPointsEarned": 4523,
      "totalPointsRedeemed": 1398,
      "totalSpend": 3687
    },
    "updatedAt": "2021-10-21T18:34:45Z"
  },
  {
    "createdAt": "2021-10-20T14:51:16Z",
    "dob": "2021-10-20",
    "email": "john@example.com",
    "firstName": "John",
    "gender": "MALE",
    "hasAgreedToMarketing": true,
    "id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
    "lastName": "Smith",
    "phoneNumber": "+61411222333",
    "statistics": {
      "lastPointsEarnedAt": "2021-08-23T02:06:24.000Z",
      "lastPointsRedeemedAt": "2021-03-17T04:27:06.000Z",
      "lastSpentAt": "2021-08-23T02:06:23.000Z",
      "pointsBalance": 3125,
      "totalPointsEarned": 4523,
      "totalPointsRedeemed": 1398,
      "totalSpend": 3687
    },
    "updatedAt": "2021-10-21T18:34:45Z"
  }
]

Examples

Syncing customers on a schedule

To sync the full database on a schedule (rather than using webhook events) without needing to refetch all customers can use the sort=updated query parameter. This will fetch customers starting with those updated most recently. Continue to fetch next pages until you pass the updated timestamp from the last scheduled run.

The following example demonstrates the approach using fetch in Typescript (note: limited error handling for brevity).

async function getUpdatedCustomers(organizationId: string, updatedAt: Date | null) {
  let customers = [];
  let path: string | null = `/organizations/${organizationId}/customers?sort=updated`;

  do {
    const url = new URL(path, "https://api.loke.global");
    const response = await fetch(url, {
      headers: { Authorization: "Bearer my_access_token" },
    });
    if (!response.ok) throw new Error("Network response was not OK");
    path = response.headers.get("X-Next-Page");

    customers.push(await response.json());

    const lastCustomer =  customers[customers.length - 1];
    if (!lastCustomer || (updatedAt && new Date(lastCustomer.updatedAt) < updatedAt)) {
      // don't continue, even if more pages
      path = null;
    }
  } while (path);

  return { customers, updatedAt: customers[0]?.updatedAt ?? updatedAt };
}

async function doScheduledJob() {
  // load the job params, in particular last known updatedAt
  const job = await getMyJob();
  
  const {customers, updatedAt} = await getUpdatedCustomers(
    job.organizationId,
    job.updatedAt // will be null on first run
  );

  // do something with customers
  await updateCustomersInMySystem(customers);

  // remember the new updatedAt value for next run
  await updateMyJob(job.id, { updatedAt });
}

List memberships

List all customer-lists that a customer is a member of. The result list is paged by 10 results. Use X-Next-Page to retrieve the next page of results

get /organizations/{organizationId}/customers/{customerId}/memberships

Parameters

NameTypeInDescription
organizationIdstringpathOrganization ID
afterstringqueryThe cursor to use for pagination. Do not use this field manually it will be automatically provided in the response headers (see Paging guide).
customerIdstringpathCustomer ID

Responses

200: OK response.CustomerListTiny[]
[
  {
    "id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
    "name": "Loyal Customers"
  },
  {
    "id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
    "name": "Loyal Customers"
  },
  {
    "id": "01FCCGYZA9JPQ97HBSTKW0KT7P",
    "name": "Loyal Customers"
  }
]

Models

Customer

NameTypeDescription
idstringUnique ID of the Customer
createdAtstring(optional) The date and time that the Customer was created
updatedAtstring(optional) The date and time that the Customer was last updated
dobstring(optional) The Customers date of birth in YYYY-MM-DD format
emailstring(optional) The Customers email address
firstNamestringCustomer first name or given name
genderstring(optional) The Customers gender
hasAgreedToMarketingboolean(optional) If the Customer has agreed to marketing
lastNamestringCustomer last name or surname
phoneNumberstring(optional) The Customers mobile phone number
statisticsCustomerStatistics(optional)

CustomerStatistics

NameTypeDescription
lastPointsEarnedAtstring(optional) Date and time of last points earned by the Customer
lastPointsRedeemedAtstring(optional) Date and time of last redeemed points by the Customer
lastSpentAtstring(optional) The date of the Customers last spend
pointsBalanceinteger(optional) The Customers current points balance
totalPointsEarnedinteger(optional) The total points earned over the Customers lifetime
totalPointsRedeemedinteger(optional) Total points earned over lifetime of the Customer
totalSpendinteger(optional) The total spend amount of the Customer, in the lowest common denominator e.g. cents

CustomerTiny

NameTypeDescription
idstringUnique ID of the Customer
emailstring(optional) The Customers email address
firstNamestringCustomer first name or given name
lastNamestringCustomer last name or surname
phoneNumberstring(optional) The Customers mobile phone number

CustomerListTiny

A customer list

NameTypeDescription
idstring(optional) Unique ID of the customer list
namestring(optional) The name of the customer list

In this article