> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/api-reference/pass-management/stamp-card.md).

# Stamp Card

## Get a stamp board

> A card never stamped reads as an empty board; any other pass kind is a 404.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"StampCard"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.pass:read"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"StampCardResponse":{"type":"object","properties":{"count":{"type":"integer","description":"Stamps currently collected, the sum of every movement.","format":"int32"},"target":{"type":"integer","description":"Stamps needed to reach the goal, from the pass template's stamp configuration.","format":"int32"},"behaviour":{"description":"What the card does once the goal is reached, from the pass template:\n`stayAtGoal` (the board stays full and refuses further stamps), `resetImmediately` (the board\nclears in the same write that reaches the goal) or `resetOnNextStamp` (the board stays full until the\nnext stamp clears it and starts a new round).","$ref":"#/components/schemas/StampGoalBehaviour"},"state":{"type":"string","description":"`goalReached` when `count` is at or above `target`, otherwise `collecting`."},"movements":{"type":"array","items":{"description":"One movement in a card's history.","$ref":"#/components/schemas/StampMovementResponse"},"description":"Full history, oldest first, including the movements that cleared the board."},"rewardBenefitTemplateId":{"type":["null","string"],"description":"Benefit template granted on reaching the goal, or null when the pass template grants none.\nWhat the next goal will grant, not a record of what past goals did."}},"additionalProperties":false,"description":"The state of a stamp board."},"StampGoalBehaviour":{"enum":["resetOnNextStamp","resetImmediately","stayAtGoal"],"type":"string","description":"What happens to a stamp card once its goal is reached."},"StampMovementResponse":{"type":"object","properties":{"movementId":{"type":"string","description":"Server-assigned identifier (GUID) of the movement."},"date":{"oneOf":[{"type":"string","format":"date-time"},{"type":"integer","format":"int64"}],"description":"When it was applied, in UTC. Accepts ISO 8601 date-time string or Unix epoch seconds in request inputs. Responses are serialized as ISO 8601 date-time strings."},"value":{"type":"integer","description":"Signed change in stamps. The board clearing itself after a goal shows as a negative movement of the full count.","format":"int32"},"source":{"type":["null","string"],"description":"Identity of the caller (user or API key) that applied it; a clearing movement carries the source of the stamp that triggered it."},"remarks":{"type":["null","string"],"description":"Note sent with the movement; clearing movements carry a system note."}},"additionalProperties":false,"description":"One movement in a card's history."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/{passId}/stamps":{"get":{"tags":["StampCard"],"summary":"Get a stamp board","description":"A card never stamped reads as an empty board; any other pass kind is a 404.","parameters":[{"name":"passId","in":"path","description":"Pass identifier.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Board returned.","content":{"text/plain":{"schema":{"description":"The state of a stamp board.","$ref":"#/components/schemas/StampCardResponse"}},"application/json":{"schema":{"description":"The state of a stamp board.","$ref":"#/components/schemas/StampCardResponse"}},"text/json":{"schema":{"description":"The state of a stamp board.","$ref":"#/components/schemas/StampCardResponse"}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.pass:read</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"404":{"description":"No such pass (type `#not-found`), or the pass is not a stamp card (type `#not-a-stamp-card`).","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```

## Stamp a card

> Reaching the goal follows the pass template (board stays full, clears at once, or clears on the next stamp) and emits \`Pass:GoalReached\`, which grants the configured reward benefit template. Every movement emits \`Pass:StampApplied\`, a clearing \`Pass:StampsReset\`, and the pass is pushed to the holder's devices. Send the last-read \`count\` as \`oldValue\`: the movement lands only while the board is at that count, so a retried request is refused with 409 rather than stamping twice. Errors are \`application/problem+json\`; branch on \`type\`.

```json
{"openapi":"3.1.1","info":{"title":"Neostore internal API","version":"v1"},"tags":[{"name":"StampCard"}],"servers":[{"url":"https://app.neostore.cloud","description":"Production Server"},{"url":"https://app-qa.neostore.cloud","description":"Staging Server"}],"security":[{"admin-bearer":["tenant.pass:write"]},{"apiKey":[]}],"components":{"securitySchemes":{"admin-bearer":{"type":"oauth2","flows":{"implicit":{"authorizationUrl":"https://auth.neostore.cloud/authorize?audience=https://app.neostore.cloud/api/","scopes":{}}}},"apiKey":{"type":"apiKey","name":"X-API-KEY","in":"header"}},"schemas":{"ApplyStampRequest":{"required":["oldValue","value"],"type":"object","properties":{"value":{"maximum":100,"minimum":-100,"type":"integer","description":"Signed change in stamps. Positive stamps the card, negative corrects it — a double scan is\nundone with `-1`.","format":"int32"},"oldValue":{"type":"integer","description":"Count the caller last read (`count` on the board), for optimistic concurrency: the movement lands only while the board is at this count, so a retried request is refused with 409.","format":"int32"},"remarks":{"maxLength":500,"type":["null","string"],"description":"Free-text note stored on the movement and sent with the `Pass:StampApplied` event. At most 500 characters, otherwise 400."}},"additionalProperties":false,"description":"Request to add stamps to, or correct, a card."},"ApplyStampResponse":{"type":"object","properties":{"movementId":{"type":"string","description":"Identifier of the movement that was recorded."},"value":{"type":"integer","description":"The signed change that was recorded, always the one that was asked for.","format":"int32"},"count":{"type":"integer","description":"Stamps on the board afterwards, and the `oldValue` for the next call. Already back to 0 when the goal was reached on a `resetImmediately` card.","format":"int32"},"target":{"type":"integer","description":"Stamps needed to reach the goal.","format":"int32"},"state":{"type":"string","description":"`goalReached` when `count` is at or above `target`, otherwise `collecting`."},"goalReached":{"type":"boolean","description":"Whether this movement reached the goal, even when the board was cleared right after."}},"additionalProperties":false,"description":"The outcome of applying a movement."},"ProblemDetails":{"type":"object","properties":{"type":{"type":["null","string"]},"title":{"type":["null","string"]},"status":{"type":["null","integer"],"format":"int32"},"detail":{"type":["null","string"]},"instance":{"type":["null","string"]}},"additionalProperties":{}},"HttpValidationProblemDetails":{"type":"object","allOf":[{"$ref":"#/components/schemas/ProblemDetails"}],"properties":{"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}},"additionalProperties":{}}}},"paths":{"/api/{tenantId}/passes/{passId}/stamps":{"post":{"tags":["StampCard"],"summary":"Stamp a card","description":"Reaching the goal follows the pass template (board stays full, clears at once, or clears on the next stamp) and emits `Pass:GoalReached`, which grants the configured reward benefit template. Every movement emits `Pass:StampApplied`, a clearing `Pass:StampsReset`, and the pass is pushed to the holder's devices. Send the last-read `count` as `oldValue`: the movement lands only while the board is at that count, so a retried request is refused with 409 rather than stamping twice. Errors are `application/problem+json`; branch on `type`.","parameters":[{"name":"passId","in":"path","description":"Pass identifier.","required":true,"schema":{"type":"string"}},{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"The movement to apply.","content":{"application/json":{"schema":{"description":"Request to add stamps to, or correct, a card.","$ref":"#/components/schemas/ApplyStampRequest"}},"text/json":{"schema":{"description":"Request to add stamps to, or correct, a card.","$ref":"#/components/schemas/ApplyStampRequest"}},"application/*+json":{"schema":{"description":"Request to add stamps to, or correct, a card.","$ref":"#/components/schemas/ApplyStampRequest"}}}},"responses":{"201":{"description":"Movement applied; `Location` points to the board.","content":{"text/plain":{"schema":{"description":"The outcome of applying a movement.","$ref":"#/components/schemas/ApplyStampResponse"}},"application/json":{"schema":{"description":"The outcome of applying a movement.","$ref":"#/components/schemas/ApplyStampResponse"}},"text/json":{"schema":{"description":"The outcome of applying a movement.","$ref":"#/components/schemas/ApplyStampResponse"}}}},"400":{"description":"The request is invalid (`value` zero or out of range, `remarks` too long), or the card refuses\nthe movement, by problem type: `#stamp-count-below-zero`, `#stamp-goal-reached` (a full `stayAtGoal` card), or\n`#stamp-target-exceeded` (more than the board has room for, with `roomLeft` in the problem).","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"401":{"description":"The caller is not authenticated.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"403":{"description":"The caller lacks the <c>tenant.pass:write</c> scope.","content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"404":{"description":"No such pass (type `#not-found`), or the pass is not a stamp card (type `#not-a-stamp-card`).","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"409":{"description":"The board is no longer at `oldValue` (type `#stamp-count-changed`, with `currentValue` and `expectedValue`); nothing was applied.","content":{"text/plain":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}},"text/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}},"429":{"description":"Over 1200 requests per minute to this endpoint for the tenant (default limit); retry after <c>Retry-After</c>.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Sent when the limiter knows it.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ProblemDetails"},{"$ref":"#/components/schemas/HttpValidationProblemDetails"}]}}}}}}}}}
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.thewalletcrew.io/api-reference/pass-management/stamp-card.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
