Redeem customer points

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…

This is the v2 API for redeeming points. If you are on the older API, see Redeem Points (v1.1) for POST /v1.1/points/redeem.

Redeem points for a customer. By default, points are deducted from the customer's individual wallet. If the customer is an active member of a UserGroup2 group and the org has ENABLE_CROSS_MEMBER_REDEMPTION enabled, points are instead drawn from the combined group balance in FEFO (First Expiry, First Out) order — the earliest-expiring batch across all group members is consumed first.

What this API supports

  • Redeem points from an individual customer's wallet.
  • Redeem from the combined balance of all active group members in a single transaction. This requires the ENABLE_CROSS_MEMBER_REDEMPTION org-level configuration to be enabled. To enable this, raise a JIRA ticket to the Capillary support team.
  • FEFO (First Expiry, First Out) ordering across all group members — the earliest-expiring batch is drawn first. When two batches share the same expiry date, the batch with the earlier award date takes priority; if both match, the lower customer ID breaks the tie.
  • Per-source-member breakdown in the response (crossMemberRedemptionBreakup[]) showing exactly whose points were drawn and from which expiry batch.
  • Backward compatible: callers not enrolled in a UserGroup2 group, or orgs without ENABLE_CROSS_MEMBER_REDEMPTION enabled, take the standard individual redemption path unchanged. The groupRedemption field does not control routing — cross-member activation is determined by org configuration and group membership.

Example request

curl -X POST 'https://{host}/v2/customers/1003/redemptions' \
  -u USERNAME:{password} \
  -H 'Content-Type: application/json' \
  -d '{
    "redemptionType": "POINTS",
    "points": 350,
    "transactionNumber": "TXN-882291",
    "validationCode": "VC-1234",
    "source": "INSTORE",
    "commit": true,
    "externalReferenceNumber": "TXN-882291"
  }'

API Quick Reference

POST /v2/customers/{id}/redemptions

Request
   └─ root (object)
       ├─ redemptionType (string)
       ├─ points (number)
       ├─ transactionNumber (string)
       ├─ validationCode (string)
       ├─ source (string)
       ├─ commit (boolean)
       ├─ skipValidation (boolean)
       ├─ groupRedemption (boolean)
       ├─ externalReferenceNumber (string)
       └─ notes (string)

Response
   └─ entity (object)
       ├─ redemptionId (string)
       ├─ userId (number)
       ├─ points (number)
       ├─ remainingPoints (number)
       ├─ redeemed (boolean)
       ├─ isGroupRedemption (boolean)
       └─ crossMemberRedemptionBreakup [] (present only on group redemptions)
           ├─ memberId (number)
           ├─ pointsRedeemed (number)
           └─ expiryDate (string — ISO-8601)

Prerequisites

  • Basic authentication. Credentials must be authorised for the org that owns the customer.
  • For group redemptions, the org must have ENABLE_CROSS_MEMBER_REDEMPTION enabled. To enable this, raise a JIRA ticket to the Capillary support team.
  • For group redemptions, the transacting customer ({id}) must be an active member of a UserGroup2 group with the allow_points_redemption permission. Use the Update permissions API to grant this permission.

Path parameters

FieldTypeRequiredDescription
idLongYesCustomer ID of the member initiating the redemption.

Body parameters

FieldTypeRequiredDescription
redemptionTypeStringYesType of redemption. Supported values: POINTS.
pointsNumberYesNumber of points to redeem. For group redemptions, points are drawn from the combined group balance in FEFO order.
transactionNumberStringYesUnique identifier for the transaction.
validationCodeStringConditionalAuthorization code issued to the customer to confirm the redemption. The code is verified against a valid code on record for this org. Required when validation enforcement is enabled at the org level.
sourceStringYesSource of the redemption request. Supported values: INSTORE.
commitBooleanYesSet to true to finalize and commit the redemption. When false, the call performs a validation dry run without deducting points.
skipValidationBooleanOptionalWhen true, bypasses the validation code check. Only effective when the org has the validation override config enabled. Defaults to false.
groupRedemptionBooleanOptionalSet to true to redeem group points.
externalReferenceNumberStringOptionalA plain string reference identifier for the points redemption attempt. Each externalReferenceNumber must be unique for a redemption. This is used for an idempotency check. There is no character limit for this parameter.
notesStringOptionalNotes or additional information about the redemption.

Example response

{
  "status": {
    "success": true,
    "code": 201,
    "message": "SUCCESS"
  },
  "entity": {
    "redemptionId": "RDM-5002",
    "userId": 1003,
    "points": 100,
    "remainingPoints": 400,
    "redeemed": true,
    "isGroupRedemption": false
  }
}
{
  "status": {
    "success": true,
    "code": 201,
    "message": "SUCCESS"
  },
  "entity": {
    "redemptionId": "RDM-5001",
    "userId": 1003,
    "points": 350,
    "remainingPoints": 160,
    "redeemed": true,
    "isGroupRedemption": true,
    "crossMemberRedemptionBreakup": [
      { "memberId": 1004, "pointsRedeemed": 10,  "expiryDate": "2026-04-02T00:00:00Z" },
      { "memberId": 1001, "pointsRedeemed": 100, "expiryDate": "2026-04-05T00:00:00Z" },
      { "memberId": 1002, "pointsRedeemed": 240, "expiryDate": "2026-04-10T00:00:00Z" }
    ]
  }
}

Response parameters

FieldTypeDescription
redemptionIdStringUnique identifier for this redemption transaction.
userIdLongCustomer ID of the transacting member.
pointsNumberTotal points redeemed in this transaction.
remainingPointsNumberRemaining redeemable balance for the transacting member after the redemption.
redeemedBooleantrue when the redemption succeeded.
isGroupRedemptionBooleantrue when group redemption was applied.
crossMemberRedemptionBreakupArrayPer-source-member breakdown. Present only when isGroupRedemption is true. null for individual redemptions.
.memberIdLongCustomer ID of the group member whose points were drawn.
.pointsRedeemedNumberPoints drawn from this member's wallet. Entries are ordered by FEFO (earliest expiry first).
.expiryDateString (ISO-8601)Expiry timestamp of the points batch consumed from this member's wallet.

How group redemption works

When a group member redeems points, the API draws from the earliest-expiring batches across all active group members first — this is called FEFO (First Expiry, First Out) ordering. Points expiring soonest are consumed before those with later expiry dates.

Example

A group of four members has a combined balance of 1,410 points. Two members each hold a 100-point batch expiring in 2 days — earlier than any other batch in the group. The caller requests 200 points.

The API draws 100 points from each of the two earliest-expiring batches, leaving all other members' points untouched.

"crossMemberRedemptionBreakup": [
  { "memberId": 1002, "pointsRedeemed": 100, "expiryDate": "2026-05-20T00:00:00Z" },
  { "memberId": 1003, "pointsRedeemed": 100, "expiryDate": "2026-05-20T00:00:00Z" }
]

Individual redemption

If the customer is not part of a group, or if group redemption is not enabled for the org, points are deducted only from that customer's own wallet.


Error codes

CodeTypeDescription
802ErrorInvalid customer ID — the {id} in the path does not correspond to an active customer.
813ErrorInsufficient balance — the available redeemable balance (individual wallet, or the group's combined balance for group redemptions) is less than the requested points value.
744ErrorDuplicate externalReferenceNumber — a prior redemption with this value already exists on this org.
400ErrorRequired field missing or invalid value (e.g., source absent).
700ErrorInvalid redemption type. Returned when redemptionType is set to an unrecognized value (for example, lowercase "points" instead of "POINTS"). The HTTP status is 201 and success is true, but entity.redemptionStatus.success is false.
403ErrorOne or more group members carry an active fraud flag (CONFIRMED, RECONFIRMED, or INTERNAL). The entire redemption is blocked.
404ErrorFor group redemptions: the transacting member is not an active member of a cross-member-eligible group, or the group does not exist for this org.
500ErrorInternal server error. Retry the request after a short delay.
Path Params
integer
required
Body Params
string
required
number
required
string
required
string
string
required
boolean
required
boolean
boolean
string
string
Headers
string
string
Responses

401

Unauthorized — invalid or missing credentials

500

Internal server error

Language
Credentials
Basic
base64
:
URL
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json