#Loyalty activity
GET /loyalty-activity
List loyalty activity, newest first. Every entry is part of the append-only ledger: points earns, spends, manual adjustments, revocations and expiries. Supports search, filtering and cursor pagination.
Requires the loyalty:read permission.
Query parameters
limitnumberThe number of records to return.
cursorstringA pagination cursor. Fetch the next page by passing the nextCursor value from the previous response.
sortcreatedAt | -createdAt | amount | -amountThe sort order. Prefix a field with - to sort descending. Defaults to -createdAt.
searchstringA free-text search term. Every word has to match, from the start of a word, in any order and ignoring case and accents, against the record's most identifying fields. Combined with filter using AND.
filterstringA JSON-encoded filter document, for example {"createdAt":{"$gte":"2025-01-01T00:00:00Z"}}. Filterable fields: id, type, loyaltyMembershipId, amount, revokeTransactionId, createdAt, customer.id, customer.email, customer.firstName, customer.lastName, customer.metadata, customer.emailOptOut, customer.emailOptOutSource, customer.createdAt, rule.id, rule.name. See Filtering for the syntax.
includestringA comma-separated list of extra fields to compute and return. Each one costs an additional query, so ask only for what you need. Available: customer, rule, membership.
curl \
"https://your-store.meisei.app/api/loyalty-activity" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@meisei/api/admin/client"
import { getLoyaltyActivity } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getLoyaltyActivity()require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
page = meisei.loyalty_activity.listfrom meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
page = meisei.loyalty_activity.list(){
"data": [
{
"id": "A4Ws1igz",
"type": "points",
"loyaltyMembershipId": "A4Ws1igz",
"loyaltyRuleId": "A4Ws1igz",
"amount": 0,
"balanceAfter": 0,
"details": "...",
"revokeTransactionId": "A4Ws1igz",
"eventKey": "string",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"customer": {
"id": "...",
"email": "...",
"phone": "...",
"firstName": "...",
"lastName": "...",
"country": "...",
"metadata": "...",
"notes": "...",
"emailOptOut": "...",
"emailOptOutAt": "...",
"emailOptOutSource": "...",
"createdAt": "...",
"updatedAt": "..."
},
"rule": {
"id": "...",
"name": "...",
"section": "..."
},
"membership": {
"id": "...",
"customerId": "...",
"loyaltyProgramId": "...",
"loyaltyTierId": "...",
"tierAssignedManually": "...",
"tierAttainedAt": "...",
"leftAt": "...",
"createdAt": "...",
"updatedAt": "..."
}
}
],
"nextCursor": "string"
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the activity entry.",
"idCodec": "sqid"
},
"type": {
"type": "string",
"enum": ["points", "reward", "join", "tierChange"],
"description": "What kind of loyalty activity the entry records."
},
"loyaltyMembershipId": {
"type": "string",
"description": "The loyalty membership the activity belongs to.",
"idCodec": "sqid"
},
"loyaltyRuleId": {
"anyOf": [
{
"type": "string",
"description": "The loyalty rule that produced the entry, or null when none did.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"amount": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The points change, positive for earns and negative for spends. Null for non-points activity."
},
"balanceAfter": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The membership's points balance right after this entry. Null for non-points activity."
},
"details": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Context for the entry, such as a manual adjustment's reason."
},
"revokeTransactionId": {
"anyOf": [
{
"type": "string",
"description": "When the entry is a revocation, the transaction it reverses.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "When the entry is a revocation, the transaction it reverses."
},
"eventKey": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The idempotency key the entry was appended with, if any."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the activity happened."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the entry was last changed."
},
"customer": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the customer.",
"idCodec": "sqid"
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"description": "The customer's email address, unique within the organization."
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's phone number in E.164 format."
},
"firstName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's first name."
},
"lastName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's last name."
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's country, as an ISO 3166-1 code."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"description": "A metadata value: a string, a number, true or false, or a list of strings. A key with a metadata definition holds the type its definition names."
},
"description": "Key/value pairs for your own data. Keys you define with `/metadata-definitions` are typed and validated; any other key is free-form. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Internal notes about the customer. Never shown to them."
},
"emailOptOut": {
"type": "boolean",
"description": "Whether the customer has opted out of marketing email. They still receive mail they asked for, such as a wishlist they shared themselves."
},
"emailOptOutAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the opt-out was recorded. Null while the customer is still subscribed."
},
"emailOptOutSource": {
"anyOf": [
{
"type": "string",
"enum": ["customer", "merchant", "import", "shopify"],
"description": "Where the opt-out came from."
},
{
"type": "null"
}
],
"description": "Where the opt-out came from: `customer` (they opted out themselves, through an unsubscribe link or your integration), `merchant`, `import` or `shopify`. Null while the customer is still subscribed."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was first created in Meisei."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was last changed."
}
},
"required": [
"id",
"email",
"phone",
"firstName",
"lastName",
"country",
"metadata",
"notes",
"emailOptOut",
"emailOptOutAt",
"emailOptOutSource",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The customer the activity belongs to, through the membership."
},
"rule": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the rule.",
"idCodec": "sqid"
},
"name": {
"type": "string",
"description": "The rule's display name."
},
"section": {
"type": "string",
"enum": ["rules", "rewards", "offers"],
"description": "The widget section the rule sits in."
}
},
"required": ["id", "name", "section"],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"membership": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the membership.",
"idCodec": "sqid"
},
"customerId": {
"type": "string",
"description": "The customer the membership belongs to.",
"idCodec": "sqid"
},
"loyaltyProgramId": {
"type": "string",
"description": "The loyalty program the membership is in.",
"idCodec": "sqid"
},
"loyaltyTierId": {
"anyOf": [
{
"type": "string",
"description": "The tier the member currently sits in, if the program uses tiers.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The tier the member currently sits in, if the program uses tiers."
},
"tierAssignedManually": {
"type": "boolean",
"description": "True when an admin pinned the tier. The loyalty tiers automation leaves a pinned tier alone until the pin is removed."
},
"tierAttainedAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the member reached their current tier, or null without a tier."
},
"leftAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the customer left the program, or null while they are an active member. A member who left keeps their row so rejoining can restore their balances."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer joined the program."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the membership was last changed."
}
},
"required": [
"id",
"customerId",
"loyaltyProgramId",
"loyaltyTierId",
"tierAssignedManually",
"tierAttainedAt",
"leftAt",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The loyalty membership the activity belongs to."
}
},
"required": [
"id",
"type",
"loyaltyMembershipId",
"loyaltyRuleId",
"amount",
"balanceAfter",
"details",
"revokeTransactionId",
"eventKey",
"createdAt",
"updatedAt"
],
"additionalProperties": false
},
"description": "The page of records, in the requested sort order."
},
"nextCursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Pass this back as `cursor` to fetch the next page. Null once the last page has been returned."
}
},
"required": ["data", "nextCursor"],
"additionalProperties": false
}POST /loyalty-activity/adjustments
Manually adjust a member's points balance, up or down, with a required reason stored on the entry. A deduction may push the balance below zero, for example when correcting fraud. Triggers the loyaltyTransaction.created webhook.
Requires the loyalty:write permission.
Body parameters
loyaltyMembershipIdstringrequiredThe loyalty membership to adjust.
amountintegerrequiredThe points to add (positive) or deduct (negative).
reasonstringrequiredWhy the balance was adjusted. Stored on the activity entry.
curl \
-X POST \
"https://your-store.meisei.app/api/loyalty-activity/adjustments" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"loyaltyMembershipId": "string",
"amount": 0,
"reason": "string"
}'import { client } from "@meisei/api/admin/client"
import { postLoyaltyActivityAdjustments } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await postLoyaltyActivityAdjustments({
body: {
loyaltyMembershipId: "string",
amount: 0,
reason: "string",
},
})require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.adjust(
loyalty_membership_id: "string",
amount: 0,
reason: "string",
)from meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.adjust(
loyalty_membership_id="string",
amount=0,
reason="string",
){
"id": "A4Ws1igz",
"type": "points",
"loyaltyMembershipId": "A4Ws1igz",
"loyaltyRuleId": "A4Ws1igz",
"amount": 0,
"balanceAfter": 0,
"details": "...",
"revokeTransactionId": "A4Ws1igz",
"eventKey": "string",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"customer": {
"id": "A4Ws1igz",
"email": "user@example.com",
"phone": "string",
"firstName": "string",
"lastName": "string",
"country": "string",
"metadata": "...",
"notes": "string",
"emailOptOut": true,
"emailOptOutAt": "2025-01-15T09:30:00Z",
"emailOptOutSource": "customer",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
},
"rule": {
"id": "A4Ws1igz",
"name": "string",
"section": "rules"
},
"membership": {
"id": "A4Ws1igz",
"customerId": "A4Ws1igz",
"loyaltyProgramId": "A4Ws1igz",
"loyaltyTierId": "A4Ws1igz",
"tierAssignedManually": true,
"tierAttainedAt": "2025-01-15T09:30:00Z",
"leftAt": "2025-01-15T09:30:00Z",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the activity entry.",
"idCodec": "sqid"
},
"type": {
"type": "string",
"enum": ["points", "reward", "join", "tierChange"],
"description": "What kind of loyalty activity the entry records."
},
"loyaltyMembershipId": {
"type": "string",
"description": "The loyalty membership the activity belongs to.",
"idCodec": "sqid"
},
"loyaltyRuleId": {
"anyOf": [
{
"type": "string",
"description": "The loyalty rule that produced the entry, or null when none did.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"amount": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The points change, positive for earns and negative for spends. Null for non-points activity."
},
"balanceAfter": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The membership's points balance right after this entry. Null for non-points activity."
},
"details": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Context for the entry, such as a manual adjustment's reason."
},
"revokeTransactionId": {
"anyOf": [
{
"type": "string",
"description": "When the entry is a revocation, the transaction it reverses.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "When the entry is a revocation, the transaction it reverses."
},
"eventKey": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The idempotency key the entry was appended with, if any."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the activity happened."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the entry was last changed."
},
"customer": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the customer.",
"idCodec": "sqid"
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"description": "The customer's email address, unique within the organization."
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's phone number in E.164 format."
},
"firstName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's first name."
},
"lastName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's last name."
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's country, as an ISO 3166-1 code."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"description": "A metadata value: a string, a number, true or false, or a list of strings. A key with a metadata definition holds the type its definition names."
},
"description": "Key/value pairs for your own data. Keys you define with `/metadata-definitions` are typed and validated; any other key is free-form. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Internal notes about the customer. Never shown to them."
},
"emailOptOut": {
"type": "boolean",
"description": "Whether the customer has opted out of marketing email. They still receive mail they asked for, such as a wishlist they shared themselves."
},
"emailOptOutAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the opt-out was recorded. Null while the customer is still subscribed."
},
"emailOptOutSource": {
"anyOf": [
{
"type": "string",
"enum": ["customer", "merchant", "import", "shopify"],
"description": "Where the opt-out came from."
},
{
"type": "null"
}
],
"description": "Where the opt-out came from: `customer` (they opted out themselves, through an unsubscribe link or your integration), `merchant`, `import` or `shopify`. Null while the customer is still subscribed."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was first created in Meisei."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was last changed."
}
},
"required": [
"id",
"email",
"phone",
"firstName",
"lastName",
"country",
"metadata",
"notes",
"emailOptOut",
"emailOptOutAt",
"emailOptOutSource",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The customer the activity belongs to, through the membership."
},
"rule": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the rule.",
"idCodec": "sqid"
},
"name": {
"type": "string",
"description": "The rule's display name."
},
"section": {
"type": "string",
"enum": ["rules", "rewards", "offers"],
"description": "The widget section the rule sits in."
}
},
"required": ["id", "name", "section"],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"membership": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the membership.",
"idCodec": "sqid"
},
"customerId": {
"type": "string",
"description": "The customer the membership belongs to.",
"idCodec": "sqid"
},
"loyaltyProgramId": {
"type": "string",
"description": "The loyalty program the membership is in.",
"idCodec": "sqid"
},
"loyaltyTierId": {
"anyOf": [
{
"type": "string",
"description": "The tier the member currently sits in, if the program uses tiers.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The tier the member currently sits in, if the program uses tiers."
},
"tierAssignedManually": {
"type": "boolean",
"description": "True when an admin pinned the tier. The loyalty tiers automation leaves a pinned tier alone until the pin is removed."
},
"tierAttainedAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the member reached their current tier, or null without a tier."
},
"leftAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the customer left the program, or null while they are an active member. A member who left keeps their row so rejoining can restore their balances."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer joined the program."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the membership was last changed."
}
},
"required": [
"id",
"customerId",
"loyaltyProgramId",
"loyaltyTierId",
"tierAssignedManually",
"tierAttainedAt",
"leftAt",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The loyalty membership the activity belongs to."
}
},
"required": [
"id",
"type",
"loyaltyMembershipId",
"loyaltyRuleId",
"amount",
"balanceAfter",
"details",
"revokeTransactionId",
"eventKey",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The activity entry the adjustment created."
}POST /loyalty-activity/bulk-expire
Expire outstanding points in bulk, for example everything earned in a retired currency or before a cutoff date. For each member and currency with matching earns, an offsetting expiry transaction is appended so the balance math stays intact, clamped so no balance goes below zero. Omitting the filter considers every transaction in the organization.
Requires the loyalty:write permission.
Costs 5 rate limit tokens instead of the usual one. See Rate limits.
Query parameters
filterstringA JSON-encoded filter document selecting the transactions to expire, for example points earned before a cutoff date. Omit it and every transaction in the organization is considered. See Filtering for the syntax.
curl \
-X POST \
"https://your-store.meisei.app/api/loyalty-activity/bulk-expire" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@meisei/api/admin/client"
import { postLoyaltyActivityBulkExpire } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await postLoyaltyActivityBulkExpire()require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.bulk_expirefrom meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.bulk_expire(){
"count": 0,
"amountExpired": 0
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"count": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "How many expiry transactions were written, one per member and currency."
},
"amountExpired": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "The total number of points taken off balances across the organization."
}
},
"required": ["count", "amountExpired"],
"additionalProperties": false
}POST /loyalty-activity/{id}/revoke
Reverse a points entry by appending a compensating entry of the opposite amount, linked through revokeTransactionId. Only points entries that are not themselves revocations, have not already been revoked and did not pay for a reward can be revoked; anything else returns a 409. To give back the points a reward was claimed with, revoke the reward instead. Revoking an earn the member already spent may push the balance below zero. Triggers the loyaltyTransaction.created webhook.
Requires the loyalty:write permission.
Path parameters
idstringrequiredThe ID of the points entry to revoke.
curl \
-X POST \
"https://your-store.meisei.app/api/loyalty-activity/A4Ws1igz/revoke" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@meisei/api/admin/client"
import { postLoyaltyActivityByIdRevoke } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await postLoyaltyActivityByIdRevoke({
path: { id: "A4Ws1igz" },
})require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.revoke("A4Ws1igz")from meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.revoke("A4Ws1igz"){
"id": "A4Ws1igz",
"type": "points",
"loyaltyMembershipId": "A4Ws1igz",
"loyaltyRuleId": "A4Ws1igz",
"amount": 0,
"balanceAfter": 0,
"details": "...",
"revokeTransactionId": "A4Ws1igz",
"eventKey": "string",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"customer": {
"id": "A4Ws1igz",
"email": "user@example.com",
"phone": "string",
"firstName": "string",
"lastName": "string",
"country": "string",
"metadata": "...",
"notes": "string",
"emailOptOut": true,
"emailOptOutAt": "2025-01-15T09:30:00Z",
"emailOptOutSource": "customer",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
},
"rule": {
"id": "A4Ws1igz",
"name": "string",
"section": "rules"
},
"membership": {
"id": "A4Ws1igz",
"customerId": "A4Ws1igz",
"loyaltyProgramId": "A4Ws1igz",
"loyaltyTierId": "A4Ws1igz",
"tierAssignedManually": true,
"tierAttainedAt": "2025-01-15T09:30:00Z",
"leftAt": "2025-01-15T09:30:00Z",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the activity entry.",
"idCodec": "sqid"
},
"type": {
"type": "string",
"enum": ["points", "reward", "join", "tierChange"],
"description": "What kind of loyalty activity the entry records."
},
"loyaltyMembershipId": {
"type": "string",
"description": "The loyalty membership the activity belongs to.",
"idCodec": "sqid"
},
"loyaltyRuleId": {
"anyOf": [
{
"type": "string",
"description": "The loyalty rule that produced the entry, or null when none did.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"amount": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The points change, positive for earns and negative for spends. Null for non-points activity."
},
"balanceAfter": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The membership's points balance right after this entry. Null for non-points activity."
},
"details": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Context for the entry, such as a manual adjustment's reason."
},
"revokeTransactionId": {
"anyOf": [
{
"type": "string",
"description": "When the entry is a revocation, the transaction it reverses.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "When the entry is a revocation, the transaction it reverses."
},
"eventKey": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The idempotency key the entry was appended with, if any."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the activity happened."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the entry was last changed."
},
"customer": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the customer.",
"idCodec": "sqid"
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"description": "The customer's email address, unique within the organization."
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's phone number in E.164 format."
},
"firstName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's first name."
},
"lastName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's last name."
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's country, as an ISO 3166-1 code."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"description": "A metadata value: a string, a number, true or false, or a list of strings. A key with a metadata definition holds the type its definition names."
},
"description": "Key/value pairs for your own data. Keys you define with `/metadata-definitions` are typed and validated; any other key is free-form. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Internal notes about the customer. Never shown to them."
},
"emailOptOut": {
"type": "boolean",
"description": "Whether the customer has opted out of marketing email. They still receive mail they asked for, such as a wishlist they shared themselves."
},
"emailOptOutAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the opt-out was recorded. Null while the customer is still subscribed."
},
"emailOptOutSource": {
"anyOf": [
{
"type": "string",
"enum": ["customer", "merchant", "import", "shopify"],
"description": "Where the opt-out came from."
},
{
"type": "null"
}
],
"description": "Where the opt-out came from: `customer` (they opted out themselves, through an unsubscribe link or your integration), `merchant`, `import` or `shopify`. Null while the customer is still subscribed."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was first created in Meisei."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was last changed."
}
},
"required": [
"id",
"email",
"phone",
"firstName",
"lastName",
"country",
"metadata",
"notes",
"emailOptOut",
"emailOptOutAt",
"emailOptOutSource",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The customer the activity belongs to, through the membership."
},
"rule": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the rule.",
"idCodec": "sqid"
},
"name": {
"type": "string",
"description": "The rule's display name."
},
"section": {
"type": "string",
"enum": ["rules", "rewards", "offers"],
"description": "The widget section the rule sits in."
}
},
"required": ["id", "name", "section"],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"membership": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the membership.",
"idCodec": "sqid"
},
"customerId": {
"type": "string",
"description": "The customer the membership belongs to.",
"idCodec": "sqid"
},
"loyaltyProgramId": {
"type": "string",
"description": "The loyalty program the membership is in.",
"idCodec": "sqid"
},
"loyaltyTierId": {
"anyOf": [
{
"type": "string",
"description": "The tier the member currently sits in, if the program uses tiers.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The tier the member currently sits in, if the program uses tiers."
},
"tierAssignedManually": {
"type": "boolean",
"description": "True when an admin pinned the tier. The loyalty tiers automation leaves a pinned tier alone until the pin is removed."
},
"tierAttainedAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the member reached their current tier, or null without a tier."
},
"leftAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the customer left the program, or null while they are an active member. A member who left keeps their row so rejoining can restore their balances."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer joined the program."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the membership was last changed."
}
},
"required": [
"id",
"customerId",
"loyaltyProgramId",
"loyaltyTierId",
"tierAssignedManually",
"tierAttainedAt",
"leftAt",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The loyalty membership the activity belongs to."
}
},
"required": [
"id",
"type",
"loyaltyMembershipId",
"loyaltyRuleId",
"amount",
"balanceAfter",
"details",
"revokeTransactionId",
"eventKey",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The compensating entry the revocation created."
}GET /loyalty-activity/{id}
Get a single loyalty activity entry by ID.
Requires the loyalty:read permission.
Path parameters
idstringrequiredThe ID of the activity entry.
Query parameters
includestringA comma-separated list of extra fields to compute and return. Each one costs an additional query, so ask only for what you need. Available: customer, rule, membership.
curl \
"https://your-store.meisei.app/api/loyalty-activity/A4Ws1igz" \
-H "Authorization: Bearer sk_YOUR_SECRET_KEY"import { client } from "@meisei/api/admin/client"
import { getLoyaltyActivityById } from "@meisei/api/admin"
client.setConfig({
baseUrl: "https://your-store.meisei.app/api",
headers: { Authorization: "Bearer sk_YOUR_SECRET_KEY" },
})
const { data, error } = await getLoyaltyActivityById({
path: { id: "A4Ws1igz" },
})require "meisei"
meisei = Meisei::Client.new(
secret_key: "sk_YOUR_SECRET_KEY",
base_url: "https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.retrieve("A4Ws1igz")from meisei import Client
meisei = Client(
secret_key="sk_YOUR_SECRET_KEY",
base_url="https://your-store.meisei.app/api",
)
result = meisei.loyalty_activity.retrieve("A4Ws1igz"){
"id": "A4Ws1igz",
"type": "points",
"loyaltyMembershipId": "A4Ws1igz",
"loyaltyRuleId": "A4Ws1igz",
"amount": 0,
"balanceAfter": 0,
"details": "...",
"revokeTransactionId": "A4Ws1igz",
"eventKey": "string",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z",
"customer": {
"id": "A4Ws1igz",
"email": "user@example.com",
"phone": "string",
"firstName": "string",
"lastName": "string",
"country": "string",
"metadata": "...",
"notes": "string",
"emailOptOut": true,
"emailOptOutAt": "2025-01-15T09:30:00Z",
"emailOptOutSource": "customer",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
},
"rule": {
"id": "A4Ws1igz",
"name": "string",
"section": "rules"
},
"membership": {
"id": "A4Ws1igz",
"customerId": "A4Ws1igz",
"loyaltyProgramId": "A4Ws1igz",
"loyaltyTierId": "A4Ws1igz",
"tierAssignedManually": true,
"tierAttainedAt": "2025-01-15T09:30:00Z",
"leftAt": "2025-01-15T09:30:00Z",
"createdAt": "2025-01-15T09:30:00Z",
"updatedAt": "2025-01-15T09:30:00Z"
}
}{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the activity entry.",
"idCodec": "sqid"
},
"type": {
"type": "string",
"enum": ["points", "reward", "join", "tierChange"],
"description": "What kind of loyalty activity the entry records."
},
"loyaltyMembershipId": {
"type": "string",
"description": "The loyalty membership the activity belongs to.",
"idCodec": "sqid"
},
"loyaltyRuleId": {
"anyOf": [
{
"type": "string",
"description": "The loyalty rule that produced the entry, or null when none did.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"amount": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The points change, positive for earns and negative for spends. Null for non-points activity."
},
"balanceAfter": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "The membership's points balance right after this entry. Null for non-points activity."
},
"details": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {},
"description": "Context for the entry, such as a manual adjustment's reason."
},
"revokeTransactionId": {
"anyOf": [
{
"type": "string",
"description": "When the entry is a revocation, the transaction it reverses.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "When the entry is a revocation, the transaction it reverses."
},
"eventKey": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The idempotency key the entry was appended with, if any."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the activity happened."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the entry was last changed."
},
"customer": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the customer.",
"idCodec": "sqid"
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"description": "The customer's email address, unique within the organization."
},
"phone": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's phone number in E.164 format."
},
"firstName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's first name."
},
"lastName": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's last name."
},
"country": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "The customer's country, as an ISO 3166-1 code."
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "number"
},
{
"type": "boolean"
},
{
"type": "array",
"items": {
"type": "string"
}
}
],
"description": "A metadata value: a string, a number, true or false, or a list of strings. A key with a metadata definition holds the type its definition names."
},
"description": "Key/value pairs for your own data. Keys you define with `/metadata-definitions` are typed and validated; any other key is free-form. Individual keys are filterable with a dot path, for example `metadata.category`."
},
"notes": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Internal notes about the customer. Never shown to them."
},
"emailOptOut": {
"type": "boolean",
"description": "Whether the customer has opted out of marketing email. They still receive mail they asked for, such as a wishlist they shared themselves."
},
"emailOptOutAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the opt-out was recorded. Null while the customer is still subscribed."
},
"emailOptOutSource": {
"anyOf": [
{
"type": "string",
"enum": ["customer", "merchant", "import", "shopify"],
"description": "Where the opt-out came from."
},
{
"type": "null"
}
],
"description": "Where the opt-out came from: `customer` (they opted out themselves, through an unsubscribe link or your integration), `merchant`, `import` or `shopify`. Null while the customer is still subscribed."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was first created in Meisei."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer was last changed."
}
},
"required": [
"id",
"email",
"phone",
"firstName",
"lastName",
"country",
"metadata",
"notes",
"emailOptOut",
"emailOptOutAt",
"emailOptOutSource",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The customer the activity belongs to, through the membership."
},
"rule": {
"anyOf": [
{
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the rule.",
"idCodec": "sqid"
},
"name": {
"type": "string",
"description": "The rule's display name."
},
"section": {
"type": "string",
"enum": ["rules", "rewards", "offers"],
"description": "The widget section the rule sits in."
}
},
"required": ["id", "name", "section"],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "The loyalty rule that produced the entry, or null when none did."
},
"membership": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "Unique identifier for the membership.",
"idCodec": "sqid"
},
"customerId": {
"type": "string",
"description": "The customer the membership belongs to.",
"idCodec": "sqid"
},
"loyaltyProgramId": {
"type": "string",
"description": "The loyalty program the membership is in.",
"idCodec": "sqid"
},
"loyaltyTierId": {
"anyOf": [
{
"type": "string",
"description": "The tier the member currently sits in, if the program uses tiers.",
"idCodec": "sqid"
},
{
"type": "null"
}
],
"description": "The tier the member currently sits in, if the program uses tiers."
},
"tierAssignedManually": {
"type": "boolean",
"description": "True when an admin pinned the tier. The loyalty tiers automation leaves a pinned tier alone until the pin is removed."
},
"tierAttainedAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the member reached their current tier, or null without a tier."
},
"leftAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
],
"description": "When the customer left the program, or null while they are an active member. A member who left keeps their row so rejoining can restore their balances."
},
"createdAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the customer joined the program."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
"description": "When the membership was last changed."
}
},
"required": [
"id",
"customerId",
"loyaltyProgramId",
"loyaltyTierId",
"tierAssignedManually",
"tierAttainedAt",
"leftAt",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The loyalty membership the activity belongs to."
}
},
"required": [
"id",
"type",
"loyaltyMembershipId",
"loyaltyRuleId",
"amount",
"balanceAfter",
"details",
"revokeTransactionId",
"eventKey",
"createdAt",
"updatedAt"
],
"additionalProperties": false,
"description": "The requested activity entry."
}