Loyalty rewards

GET /loyalty-rewards

List the rewards members hold, newest first by default. Every reward a rule issued, a stamp card produced, a member claimed with points, or you issued by hand lands here. Supports search, filtering and cursor pagination.

Requires the loyalty:read permission.

Query Parameters

limitnumber

The number of records to return.

cursorstring

A pagination cursor. Fetch the next page by passing the nextCursor value from the previous response.

sortcreatedAt | -createdAt | redeemedAt | -redeemedAt | expiresAt | -expiresAt

The sort order. Prefix a field with - to sort descending. Defaults to -createdAt.

searchstring

A free-text search term, matched case-insensitively against the record's most identifying fields. Combined with filter using AND.

filterstring

A JSON-encoded filter document, for example {"createdAt":{"$gte":"2025-01-01T00:00:00Z"}}. Filterable fields: id, loyaltyMembershipId, loyaltyRuleId, stampCardId, status, code, redeemedAt, expiresAt, revokedAt, 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.

includestring

A 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, membership, rule.

Request
curl \
  "https://api.cascade.dev/loyalty-rewards" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
      "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
      "stampCardId": "550e8400-e29b-41d4-a716-446655440000",
      "loyaltyTransactionId": "550e8400-e29b-41d4-a716-446655440000",
      "reward": {
        "type": "...",
        "amount": "..."
      },
      "status": "pending",
      "code": "string",
      "redeemedAt": "2025-01-15T09:30:00Z",
      "expiresAt": "2025-01-15T09:30:00Z",
      "revokedAt": "2025-01-15T09:30:00Z",
      "metadata": "...",
      "fulfillment": {
        "mode": "...",
        "status": "...",
        "shopifyDiscountId": "...",
        "shopifyDiscountGid": "...",
        "shop": "...",
        "note": "..."
      },
      "ruleSnapshot": "...",
      "createdAt": "2025-01-15T09:30:00Z",
      "updatedAt": "2025-01-15T09:30:00Z",
      "customer": {
        "id": "...",
        "email": "...",
        "phone": "...",
        "firstName": "...",
        "lastName": "...",
        "country": "...",
        "birthday": "...",
        "metadata": "...",
        "notes": "...",
        "emailOptOut": "...",
        "emailOptOutAt": "...",
        "emailOptOutSource": "...",
        "createdAt": "...",
        "updatedAt": "..."
      },
      "membership": {
        "id": "...",
        "customerId": "...",
        "loyaltyProgramId": "...",
        "loyaltyTierId": "...",
        "tierAssignedManually": "...",
        "tierAttainedAt": "...",
        "tierReviewAt": "...",
        "leftAt": "...",
        "referralCode": "...",
        "createdAt": "...",
        "updatedAt": "..."
      },
      "rule": {
        "id": "...",
        "name": "...",
        "section": "..."
      }
    }
  ],
  "nextCursor": "string"
}

POST /loyalty-rewards

Issue a reward to one member outside any rule, for example as an apology or a prize. The reward comes out pending with a fresh code and shows up on the member's activity feed. Points are added through a balance adjustment instead. Triggers the loyaltyReward.issued webhook.

Requires the loyalty:write permission.

Body Parameters

dataobjectrequired

The reward to issue.

Request
curl \
  -X POST \
  "https://api.cascade.dev/loyalty-rewards" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
    "reward": {
      "type": "points",
      "amount": 0
    },
    "expiresAt": "2025-01-15T09:30:00Z",
    "reason": "string"
  }
}'
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
  "stampCardId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyTransactionId": "550e8400-e29b-41d4-a716-446655440000",
  "reward": {
    "type": "points",
    "amount": 0
  },
  "status": "pending",
  "code": "string",
  "redeemedAt": "2025-01-15T09:30:00Z",
  "expiresAt": "2025-01-15T09:30:00Z",
  "revokedAt": "2025-01-15T09:30:00Z",
  "metadata": "...",
  "fulfillment": {
    "mode": "shopify",
    "status": "pending",
    "shopifyDiscountId": "string",
    "shopifyDiscountGid": "string",
    "shop": "string",
    "note": "string"
  },
  "ruleSnapshot": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z",
  "customer": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]",
    "phone": "string",
    "firstName": "string",
    "lastName": "string",
    "country": "string",
    "birthday": "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"
  },
  "membership": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "customerId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyProgramId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyTierId": "550e8400-e29b-41d4-a716-446655440000",
    "tierAssignedManually": true,
    "tierAttainedAt": "2025-01-15T09:30:00Z",
    "tierReviewAt": "2025-01-15T09:30:00Z",
    "leftAt": "2025-01-15T09:30:00Z",
    "referralCode": "string",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z"
  },
  "rule": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "string",
    "section": "rules"
  }
}

GET /loyalty-rewards/lookup

Look a reward up by the code printed on it, so a point of sale or storefront can check it before honoring it. The code is matched whatever case it is typed in. Check status and expiresAt on the result: only a pending reward that has not expired can be used.

Requires the loyalty:read permission.

Query Parameters

codestringrequired

The code printed on the reward.

includestring

A 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, membership, rule.

Request
curl \
  "https://api.cascade.dev/loyalty-rewards/lookup" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
  "stampCardId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyTransactionId": "550e8400-e29b-41d4-a716-446655440000",
  "reward": {
    "type": "points",
    "amount": 0
  },
  "status": "pending",
  "code": "string",
  "redeemedAt": "2025-01-15T09:30:00Z",
  "expiresAt": "2025-01-15T09:30:00Z",
  "revokedAt": "2025-01-15T09:30:00Z",
  "metadata": "...",
  "fulfillment": {
    "mode": "shopify",
    "status": "pending",
    "shopifyDiscountId": "string",
    "shopifyDiscountGid": "string",
    "shop": "string",
    "note": "string"
  },
  "ruleSnapshot": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z",
  "customer": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]",
    "phone": "string",
    "firstName": "string",
    "lastName": "string",
    "country": "string",
    "birthday": "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"
  },
  "membership": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "customerId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyProgramId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyTierId": "550e8400-e29b-41d4-a716-446655440000",
    "tierAssignedManually": true,
    "tierAttainedAt": "2025-01-15T09:30:00Z",
    "tierReviewAt": "2025-01-15T09:30:00Z",
    "leftAt": "2025-01-15T09:30:00Z",
    "referralCode": "string",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z"
  },
  "rule": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "string",
    "section": "rules"
  }
}

POST /loyalty-rewards/claims

Spend a member's points on a reward. The balance check, the debit and the reward all happen together, so a claim the member cannot afford leaves nothing behind and returns a 409. Rules with a variable amount take pointsToSpend and scale the reward with it. Claiming is not redeeming: the reward comes out pending and is marked redeemed when its code is used. Triggers the loyaltyReward.issued and loyaltyTransaction.created webhooks.

Requires the loyalty:write permission.

Body Parameters

dataobjectrequired

The claim to make.

Request
curl \
  -X POST \
  "https://api.cascade.dev/loyalty-rewards/claims" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
    "pointsToSpend": 0
  }
}'
Response
{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
    "stampCardId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyTransactionId": "550e8400-e29b-41d4-a716-446655440000",
    "reward": {
      "type": "points",
      "amount": 0
    },
    "status": "pending",
    "code": "string",
    "redeemedAt": "2025-01-15T09:30:00Z",
    "expiresAt": "2025-01-15T09:30:00Z",
    "revokedAt": "2025-01-15T09:30:00Z",
    "metadata": "...",
    "fulfillment": {
      "mode": "shopify",
      "status": "pending",
      "shopifyDiscountId": "string",
      "shopifyDiscountGid": "string",
      "shop": "string",
      "note": "string"
    },
    "ruleSnapshot": "...",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z",
    "customer": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "email": "[email protected]",
      "phone": "string",
      "firstName": "string",
      "lastName": "string",
      "country": "string",
      "birthday": "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"
    },
    "membership": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "customerId": "550e8400-e29b-41d4-a716-446655440000",
      "loyaltyProgramId": "550e8400-e29b-41d4-a716-446655440000",
      "loyaltyTierId": "550e8400-e29b-41d4-a716-446655440000",
      "tierAssignedManually": true,
      "tierAttainedAt": "2025-01-15T09:30:00Z",
      "tierReviewAt": "2025-01-15T09:30:00Z",
      "leftAt": "2025-01-15T09:30:00Z",
      "referralCode": "string",
      "createdAt": "2025-01-15T09:30:00Z",
      "updatedAt": "2025-01-15T09:30:00Z"
    },
    "rule": {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "string",
      "section": "rules"
    }
  },
  "pointsSpent": 0
}

POST /loyalty-rewards/{id}/redeem

Mark a reward's code as used at checkout. Only a pending reward that has not expired can be redeemed, and only once: anything else returns a 409. Triggers the loyaltyReward.redeemed webhook.

Requires the loyalty:write permission.

Path Parameters

idstring (uuid)required

The ID of the reward being used.

Request
curl \
  -X POST \
  "https://api.cascade.dev/loyalty-rewards/550e8400-e29b-41d4-a716-446655440000/redeem" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
  "stampCardId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyTransactionId": "550e8400-e29b-41d4-a716-446655440000",
  "reward": {
    "type": "points",
    "amount": 0
  },
  "status": "pending",
  "code": "string",
  "redeemedAt": "2025-01-15T09:30:00Z",
  "expiresAt": "2025-01-15T09:30:00Z",
  "revokedAt": "2025-01-15T09:30:00Z",
  "metadata": "...",
  "fulfillment": {
    "mode": "shopify",
    "status": "pending",
    "shopifyDiscountId": "string",
    "shopifyDiscountGid": "string",
    "shop": "string",
    "note": "string"
  },
  "ruleSnapshot": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z",
  "customer": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]",
    "phone": "string",
    "firstName": "string",
    "lastName": "string",
    "country": "string",
    "birthday": "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"
  },
  "membership": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "customerId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyProgramId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyTierId": "550e8400-e29b-41d4-a716-446655440000",
    "tierAssignedManually": true,
    "tierAttainedAt": "2025-01-15T09:30:00Z",
    "tierReviewAt": "2025-01-15T09:30:00Z",
    "leftAt": "2025-01-15T09:30:00Z",
    "referralCode": "string",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z"
  },
  "rule": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "string",
    "section": "rules"
  }
}

POST /loyalty-rewards/{id}/revoke

Withdraw a reward with a reason, which is kept on the audit trail. Points the member spent claiming it are given back through the ledger. A reward whose code was already used cannot be withdrawn; adjust the member's balance by hand instead. Triggers the loyaltyReward.revoked webhook.

Requires the loyalty:write permission.

Path Parameters

idstring (uuid)required

The ID of the reward to withdraw.

Body Parameters

dataobjectrequired

Why the reward is being withdrawn.

Request
curl \
  -X POST \
  "https://api.cascade.dev/loyalty-rewards/550e8400-e29b-41d4-a716-446655440000/revoke" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "data": {
    "reason": "string"
  }
}'
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
  "stampCardId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyTransactionId": "550e8400-e29b-41d4-a716-446655440000",
  "reward": {
    "type": "points",
    "amount": 0
  },
  "status": "pending",
  "code": "string",
  "redeemedAt": "2025-01-15T09:30:00Z",
  "expiresAt": "2025-01-15T09:30:00Z",
  "revokedAt": "2025-01-15T09:30:00Z",
  "metadata": "...",
  "fulfillment": {
    "mode": "shopify",
    "status": "pending",
    "shopifyDiscountId": "string",
    "shopifyDiscountGid": "string",
    "shop": "string",
    "note": "string"
  },
  "ruleSnapshot": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z",
  "customer": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]",
    "phone": "string",
    "firstName": "string",
    "lastName": "string",
    "country": "string",
    "birthday": "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"
  },
  "membership": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "customerId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyProgramId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyTierId": "550e8400-e29b-41d4-a716-446655440000",
    "tierAssignedManually": true,
    "tierAttainedAt": "2025-01-15T09:30:00Z",
    "tierReviewAt": "2025-01-15T09:30:00Z",
    "leftAt": "2025-01-15T09:30:00Z",
    "referralCode": "string",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z"
  },
  "rule": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "string",
    "section": "rules"
  }
}

GET /loyalty-rewards/{id}

Get a single reward by ID.

Requires the loyalty:read permission.

Path Parameters

idstring (uuid)required

The ID of the reward.

Query Parameters

includestring

A 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, membership, rule.

Request
curl \
  "https://api.cascade.dev/loyalty-rewards/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer sk_YOUR_SECRET_KEY"
Response
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyMembershipId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyRuleId": "550e8400-e29b-41d4-a716-446655440000",
  "stampCardId": "550e8400-e29b-41d4-a716-446655440000",
  "loyaltyTransactionId": "550e8400-e29b-41d4-a716-446655440000",
  "reward": {
    "type": "points",
    "amount": 0
  },
  "status": "pending",
  "code": "string",
  "redeemedAt": "2025-01-15T09:30:00Z",
  "expiresAt": "2025-01-15T09:30:00Z",
  "revokedAt": "2025-01-15T09:30:00Z",
  "metadata": "...",
  "fulfillment": {
    "mode": "shopify",
    "status": "pending",
    "shopifyDiscountId": "string",
    "shopifyDiscountGid": "string",
    "shop": "string",
    "note": "string"
  },
  "ruleSnapshot": "...",
  "createdAt": "2025-01-15T09:30:00Z",
  "updatedAt": "2025-01-15T09:30:00Z",
  "customer": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "[email protected]",
    "phone": "string",
    "firstName": "string",
    "lastName": "string",
    "country": "string",
    "birthday": "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"
  },
  "membership": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "customerId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyProgramId": "550e8400-e29b-41d4-a716-446655440000",
    "loyaltyTierId": "550e8400-e29b-41d4-a716-446655440000",
    "tierAssignedManually": true,
    "tierAttainedAt": "2025-01-15T09:30:00Z",
    "tierReviewAt": "2025-01-15T09:30:00Z",
    "leftAt": "2025-01-15T09:30:00Z",
    "referralCode": "string",
    "createdAt": "2025-01-15T09:30:00Z",
    "updatedAt": "2025-01-15T09:30:00Z"
  },
  "rule": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "string",
    "section": "rules"
  }
}