LoyaltyPending stamps
Loyalty
Pending stamps
Read and decide self-stamp requests.
A customer who scans the shop's counter QR and taps Add my stamp leaves a pending stamp. It is not in the balance until someone confirms it, and it ends after 24 hours. Your service reads the queue and decides requests the way staff do on the scanner's Pending tab.
Paths are relative to https://app.revisit.cards/v1/developer.
Read the self-stamp queue
/pending-stampsScopeloyalty:read
Requires loyalty:read. A customer who scanned the shop's counter QR asked for a stamp; until it is decided it is a pending stamp: not in the balance, the visits or the scan count. The default is the waiting queue, oldest first (the counter's Pending tab). status reads the history instead (confirmed, rejected, expired, or all, newest first). A request past its 24 hours reads expired even before the clock wrote it down. Rows are limited to programs and branches the key may use. A customer is named by customerId, externalCustomerId (your id for them; null when you never synced them), the member code and the masked phone; the name, the whole number and the Order details a customer typed for staff are never returned.
Query
statusenum- One of
pending,confirmed,rejected,expired,all. Default"pending". programIduuidbranchIduuidlimitinteger- 1 to 100. Default
50. offsetinteger- Default
0.
Returns 200
hasMorebooleanRequireditemsobject[]Requireditems[].idstringRequireditems[].programIdstringRequireditems[].branchIdstringRequireditems[].branchNamestringRequired- The branch whose counter QR was scanned; a confirm credits the stamp here.
items[].customerIdstringRequireditems[].externalCustomerIdstring or nullRequired- Your id for the customer; null when your application never synced them.
items[].memberCodestringRequireditems[].maskedPhonestringRequired- Last four digits only (
•••• 4821); empty for an erased customer. items[].statusenumRequired- One of
pending,confirmed,rejected,expired. items[].requestedAtdate-timeRequireditems[].expiresAtdate-timeRequired- Twenty-four hours after the request.
items[].decidedAtdate-time or nullRequired- When it was decided; for an expired request, when its 24 hours ran out.
items[].decidedByenum or nullRequired- What kind of decider wrote the status, never who. One of
integration,staff,expiry. items[].transactionIdstring or nullRequired- The STAMP ledger row a confirm wrote.
limitintegerRequiredoffsetintegerRequired
curl "https://app.revisit.cards/v1/developer/pending-stamps" \
-H "Authorization: Bearer $DEVELOPER_API_KEY"{
"data": {
"hasMore": false,
"items": [
{
"branchId": "5eff65d7-d01c-4bd3-b26a-3d06b21fd005",
"branchName": "Dhanmondi",
"customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
"decidedAt": "2026-11-03T08:41:12.000Z",
"decidedBy": "integration",
"expiresAt": "2026-11-03T08:41:12.000Z",
"externalCustomerId": "user-42",
"id": "d12cc02b-02fe-4a1f-83b0-5414e70fd99c",
"maskedPhone": "•••• 4821",
"memberCode": "K7M2QX",
"programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
"requestedAt": "2026-11-03T08:41:12.000Z",
"status": "pending",
"transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
}
],
"limit": 50,
"offset": 0
},
"requestId": "69d43e88-e72c-4bc4-ae13-0f8d9362eab3",
"success": true
}Count the stamps waiting
/pending-stamps/countScopeloyalty:read
Requires loyalty:read. How many requests are waiting for a decision inside the key's limits (the number the scanner badge shows for those branches), optionally for one program or branch.
Query
programIduuidbranchIduuid
Returns 200
countintegerRequired
curl "https://app.revisit.cards/v1/developer/pending-stamps/count" \
-H "Authorization: Bearer $DEVELOPER_API_KEY"{
"data": {
"count": 12
},
"requestId": "4c508a8b-4530-47db-bb1b-1d5c2d683895",
"success": true
}Read one pending stamp and its status
/pending-stamps/{id}Scopeloyalty:read
Requires loyalty:read. Any status. An id of another business, another environment or outside the key's limits is 404.
Path
iduuidRequired
Returns 200
idstringRequiredprogramIdstringRequiredbranchIdstringRequiredbranchNamestringRequired- The branch whose counter QR was scanned; a confirm credits the stamp here.
customerIdstringRequiredexternalCustomerIdstring or nullRequired- Your id for the customer; null when your application never synced them.
memberCodestringRequiredmaskedPhonestringRequired- Last four digits only (
•••• 4821); empty for an erased customer. statusenumRequired- One of
pending,confirmed,rejected,expired. requestedAtdate-timeRequiredexpiresAtdate-timeRequired- Twenty-four hours after the request.
decidedAtdate-time or nullRequired- When it was decided; for an expired request, when its 24 hours ran out.
decidedByenum or nullRequired- What kind of decider wrote the status, never who. One of
integration,staff,expiry. transactionIdstring or nullRequired- The STAMP ledger row a confirm wrote.
curl "https://app.revisit.cards/v1/developer/pending-stamps/e01b010d-2c65-48e1-83a0-acad79f8d3b4" \
-H "Authorization: Bearer $DEVELOPER_API_KEY"{
"data": {
"branchId": "5eff65d7-d01c-4bd3-b26a-3d06b21fd005",
"branchName": "Dhanmondi",
"customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
"decidedAt": "2026-11-03T08:41:12.000Z",
"decidedBy": "integration",
"expiresAt": "2026-11-03T08:41:12.000Z",
"externalCustomerId": "user-42",
"id": "d12cc02b-02fe-4a1f-83b0-5414e70fd99c",
"maskedPhone": "•••• 4821",
"memberCode": "K7M2QX",
"programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
"requestedAt": "2026-11-03T08:41:12.000Z",
"status": "pending",
"transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
},
"requestId": "79d1a36e-b5de-46f8-aa16-68ac0c6f8c31",
"success": true
}Confirm a waiting stamp
/pending-stamps/{id}/confirmScopeloyalty:write
Requires loyalty:write and an Idempotency-Key. Runs the counter's own stamp earning for one stamp at the branch whose QR the customer scanned (row lock, plan gate, scan, visit, wallet banner, milestones); the stamp row has no user behind it and the audit row names your application and key. A request past its 24 hours is 409 PENDING_EXPIRED; one someone (staff, or any application) already decided is 409 PENDING_DECIDED and nothing changes; a card that no longer collects stamps is 409 NOT_A_STAMP_CARD; a full card is 409 REWARD_READY. Racing decisions apply one result. Retrying your own decision, under any key or after rotating the credential, answers the original with duplicate: true and writes nothing more.
Send an Idempotency-Key header. Safe to retry.
Path
iduuidRequired
Returns 200
idstringRequiredprogramIdstringRequiredbranchIdstringRequiredbranchNamestringRequired- The branch whose counter QR was scanned; a confirm credits the stamp here.
customerIdstringRequiredexternalCustomerIdstring or nullRequired- Your id for the customer; null when your application never synced them.
memberCodestringRequiredmaskedPhonestringRequired- Last four digits only (
•••• 4821); empty for an erased customer. statusenumRequired- One of
pending,confirmed,rejected,expired. requestedAtdate-timeRequiredexpiresAtdate-timeRequired- Twenty-four hours after the request.
decidedAtdate-time or nullRequired- When it was decided; for an expired request, when its 24 hours ran out.
decidedByenum or nullRequired- What kind of decider wrote the status, never who. One of
integration,staff,expiry. transactionIdstring or nullRequired- The STAMP ledger row a confirm wrote.
balanceinteger or nullRequired- The card's stamp count right after a confirm; null for a reject.
duplicatebooleanRequired- True when your application had already made this decision; nothing changed and this is the original result.
Errors
- 409
PENDING_EXPIREDthe pending self-stamp was not decided within 24 hours, so it has ended. Nothing was stamped. - 409
PENDING_DECIDEDsomeone (staff, or this or another application) already confirmed or rejected this pending self-stamp. The decision is final and nothing changed. - 409
NOT_A_STAMP_CARDthe card no longer collects stamps, so a waiting stamp cannot be added. Nothing changed. - 409
REWARD_READY
curl -X POST "https://app.revisit.cards/v1/developer/pending-stamps/e01b010d-2c65-48e1-83a0-acad79f8d3b4/confirm" \
-H "Authorization: Bearer $DEVELOPER_API_KEY" \
-H "Idempotency-Key: 5f0c2a8e-7b1d-4c3e-9a6f-0d4b8e6a9880"{
"data": {
"balance": 7,
"branchId": "5eff65d7-d01c-4bd3-b26a-3d06b21fd005",
"branchName": "Dhanmondi",
"customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
"decidedAt": "2026-11-03T08:41:12.000Z",
"decidedBy": "integration",
"duplicate": false,
"expiresAt": "2026-11-03T08:41:12.000Z",
"externalCustomerId": "user-42",
"id": "d12cc02b-02fe-4a1f-83b0-5414e70fd99c",
"maskedPhone": "•••• 4821",
"memberCode": "K7M2QX",
"programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
"requestedAt": "2026-11-03T08:41:12.000Z",
"status": "pending",
"transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
},
"requestId": "b59b45d3-0e61-433c-b6f2-5908f9ede78a",
"success": true
}Reject a waiting stamp
/pending-stamps/{id}/rejectScopeloyalty:write
Requires loyalty:write and an Idempotency-Key. Writes no stamp and no scan; the customer's one request for the day stays used. Same refusals and retries as confirm (balance is null).
Send an Idempotency-Key header. Safe to retry.
Path
iduuidRequired
Returns 200
idstringRequiredprogramIdstringRequiredbranchIdstringRequiredbranchNamestringRequired- The branch whose counter QR was scanned; a confirm credits the stamp here.
customerIdstringRequiredexternalCustomerIdstring or nullRequired- Your id for the customer; null when your application never synced them.
memberCodestringRequiredmaskedPhonestringRequired- Last four digits only (
•••• 4821); empty for an erased customer. statusenumRequired- One of
pending,confirmed,rejected,expired. requestedAtdate-timeRequiredexpiresAtdate-timeRequired- Twenty-four hours after the request.
decidedAtdate-time or nullRequired- When it was decided; for an expired request, when its 24 hours ran out.
decidedByenum or nullRequired- What kind of decider wrote the status, never who. One of
integration,staff,expiry. transactionIdstring or nullRequired- The STAMP ledger row a confirm wrote.
balanceinteger or nullRequired- The card's stamp count right after a confirm; null for a reject.
duplicatebooleanRequired- True when your application had already made this decision; nothing changed and this is the original result.
curl -X POST "https://app.revisit.cards/v1/developer/pending-stamps/e01b010d-2c65-48e1-83a0-acad79f8d3b4/reject" \
-H "Authorization: Bearer $DEVELOPER_API_KEY" \
-H "Idempotency-Key: 5f0c2a8e-7b1d-4c3e-9a6f-0d4b8e81c903"{
"data": {
"balance": 7,
"branchId": "5eff65d7-d01c-4bd3-b26a-3d06b21fd005",
"branchName": "Dhanmondi",
"customerId": "eb83b9c0-5619-432d-b857-cef7fcf84edb",
"decidedAt": "2026-11-03T08:41:12.000Z",
"decidedBy": "integration",
"duplicate": false,
"expiresAt": "2026-11-03T08:41:12.000Z",
"externalCustomerId": "user-42",
"id": "d12cc02b-02fe-4a1f-83b0-5414e70fd99c",
"maskedPhone": "•••• 4821",
"memberCode": "K7M2QX",
"programId": "d7595bbd-4342-41b4-9037-2e61a9f8403f",
"requestedAt": "2026-11-03T08:41:12.000Z",
"status": "pending",
"transactionId": "add73925-4de9-412c-8cc2-582b074074ca"
},
"requestId": "38d21bb3-51ea-45c2-9fdd-b5eeae305205",
"success": true
}