Coupons

Coupons are a core concept for the Wallet App platform, Coupons are used as a 1 time use code that can be redeemed for a discount on a product or service in the real world. Coupons can be created and managed through the API.

The coupons model

The coupon model contains the information about a coupon. Such as the webshop pricing, when and for how long it should be active and the look and feel in the Apple or Android passwallet. The following properties are available:

Properties

  • Name
    identifier
    Type
    string
    Description

    Unique identifier for the coupon.

  • Name
    price
    Type
    float
    Description

    The sale price of the coupon.

  • Name
    points
    Type
    integer
    Description

    The sale amount of points of the coupon.

  • Name
    expiration_label
    Type
    string
    Description

    Label for the active, blocked, expired states of the coupon in the apple wallet.

  • Name
    active_label
    Type
    string
    Description

    The text in the apple wallet for once a coupon is active.

  • Name
    blocked_label
    Type
    string
    Description

    The text in the apple wallet for once a coupon is blocked.

  • Name
    expired_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass has expired.

  • Name
    redeemed_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass has been redeemed.

  • Name
    show_title
    Type
    boolean
    Description

    whether or not to show the title in the apple wallet.

  • Name
    show_subtitle
    Type
    boolean
    Description

    whether or not to show the subtitle in the apple wallet.

  • Name
    organization
    Type
    object
    Description

    Contains in formation about the coupons organization. contains: ['identifier', 'name']

  • Name
    primary_color
    Type
    string
    Description

    A Hexadecimal color code for the primary color of the coupon (background color for the apple wallet pass).

  • Name
    text_color
    Type
    string
    Description

    A Hexadecimal color code for the text color of the coupon (text color for the apple wallet pass).

  • Name
    label_color
    Type
    string
    Description

    A Hexadecimal color code for the label color of the coupon (label color for the apple wallet pass).

  • Name
    title
    Type
    string
    Description

    The title of the coupon.

  • Name
    subtitle
    Type
    string
    Description

    The subtitle of the coupon.

  • Name
    thumbnail_url
    Type
    string|url
    Description

    The URL to the image of the coupon.

  • Name
    start_date
    Type
    timestamp
    Description

    Used to set the availablity of the coupon in the webshop.

  • Name
    end_date
    Type
    timestamp
    Description

    Used to set the availablity of the coupon in the webshop.

  • Name
    use_start_and_end
    Type
    boolean
    Description

    whether or not to use a start and end date in the webshop.

  • Name
    stock
    Type
    integer
    Description

    Amount of coupons available for sale or usage.

  • Name
    use_stock
    Type
    boolean
    Description

    whether or not to use a stock in the webshop.

  • Name
    created_at
    Type
    timestamp
    Description

    A timestamp when the coupon was created.

  • Name
    updated_at
    Type
    timestamp
    Description

    A timestamp when the coupon was last updated.

Note

Because a user can have access to multiple organizations we require a organization_id to be provided for most requests. We will also return an organization reference in each response.


GET/coupons

List all coupons

This endpoint returns a list of all the coupons the currently authenticated user has access to.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    coupons.get
    Type
    string
    Description

    The scope required to access this endpoint.

Request

GET
/coupons
curl -X GET https://api.walletapp.co/coupons 
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
"message": "Request successful",
"data": [
    {
        "active_label": "ongebruikt",
        "blocked_label": "geblokkeerd",
        "created_at": "<timestamp>",
        "end_date": "<timestamp>",
        "expiration_days": 30,
        "expiration_label": "Geldig t/m",
        "expired_label": "verlopen",
        "identifier": "<UUID>",
        "organization": {
            "name": "<organization_name>",
            "identifier": "<UUID>"
        },
        "points": 0,
        "price": 0,
        "primary_color": "#ffffff",
        "redeemed_label": "ingeleverd",
        "show_subtitle": 0,
        "show_title": 0,
        "start_date": "<timestamp>",
        "stock": 0,
        "subtitle": "<subtitle>",
        "text_color": "#000000",
        "thumbnail_url": "<url>",
        "title": "<title>",
        "updated_at": "2022-12-23T09:59:31.000000Z",
        "use_start_and_end": 0,
        "use_stock": 0
    },
],
...
}

POST/coupons

Create a coupon

This endpoint allows you to create a coupon.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    coupons.store
    Type
    string
    Description

    The scope required to access this endpoint.

Request body

  • Name
    title
    Type
    string|Required
    Description

    The title of the coupon.

  • Name
    subtitle
    Type
    string|Required
    Description

    The subtitle of the coupon.

  • Name
    organization_id
    Type
    string|Required
    Description

    The organization id the coupon should be created for.

  • Name
    description
    Type
    string
    Description

    The webshop description of a coupon.

  • Name
    thumbnail_url
    Type
    string|url
    Description

    A valid url to the thumbnail image of a coupon.

  • Name
    price
    Type
    float
    Description

    The webshop price of a coupon.

  • Name
    external_reference
    Type
    string
    Description

    An external reference returned with each pass

  • Name
    points
    Type
    integer
    Description

    The webshop amount of points for a coupon.

  • Name
    expiration_label
    Type
    string
    Description

    The text shown in the apple wallet for the expiration date.

  • Name
    expiration_days
    Type
    integer
    Description

    The amount of days the associated pass will be valid for after creation.

  • Name
    blocked_label
    Type
    string
    Description

    The text in the apple wallet for once a coupon is blocked.

  • Name
    expired_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass has expired.

  • Name
    active_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass is active.

  • Name
    redeemed_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass has been redeemed.

  • Name
    show_title
    Type
    boolean
    Description

    whether or not to show the title in the apple wallet.

  • Name
    show_subtitle
    Type
    boolean
    Description

    whether or not to show the subtitle in the apple wallet.

  • Name
    primary_color
    Type
    string
    Description

    A Hexadecimal color code for the primary color of the coupon (background color for the apple wallet pass).

  • Name
    text_color
    Type
    string
    Description

    A Hexadecimal color code for the text color of the coupon (text color for the apple wallet pass).

  • Name
    label_color
    Type
    string
    Description

    A Hexadecimal color code for the label color of the coupon (label color for the apple wallet pass).

  • Name
    stock
    Type
    integer
    Description

    Amount of coupons available for sale or usage.

  • Name
    use_stock
    Type
    boolean
    Description

    whether or not to use a stock in the webshop.

  • Name
    start_date
    Type
    timestamp
    Description

    Used to set the availablity of the coupon in the webshop.

  • Name
    end_date
    Type
    timestamp
    Description

    Used to set the availablity of the coupon in the webshop.

  • Name
    use_start_and_end
    Type
    boolean
    Description

    whether or not to use a start and end date in the webshop.

Request

POST
/coupons
curl -X POST https://api.walletapp.co/coupons 
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"
-d '{
    "title":"<your_title>",
    "subtitle":"<your_subtitle>",
    "description":"<your_description>",
    "organization_id":"<organization_id>",
    "thumbnail_url":"<image_url>",
    "price": 1.50,
    "expiration_label":"Pass status",
    "expiration_days": 22,
    "external_reference": "<string>",
    "expired_label":"Expired",
    "primary_color":"#ff00ff",
    "text_color":"#ff0000",
    "label_color":"#00ff00",
    "show_title": true,
    "show_subtitle": true,
    "active_label":"Active",
    "blocked_label":"Blocked",
    "redeemed_label":"Redeemed",
    "points": 12,
    "use_stock": true,
    "use_start_and_end": true,
    "stock":15,
    "start_date": "2022-01-01",
    "end_date":"2023-01-01"
}'

Response

{
"message": "Request successful",
"data": {
        "active_label": "ongebruikt",
        "blocked_label": "geblokkeerd",
        "created_at": "<timestamp>",
        "end_date": "<timestamp>",
        "expiration_days": 30,
        "expiration_label": "Geldig t/m",
        "expired_label": "verlopen",
        "identifier": "<UUID>",
        "organization": {
            "name": "<organization_name>",
            "identifier": "<UUID>"
        },
        "points": 0,
        "price": 0,
        "primary_color": "#ffffff",
        "redeemed_label": "ingeleverd",
        "show_subtitle": 0,
        "show_title": 0,
        "start_date": "<timestamp>",
        "stock": 0,
        "subtitle": "<subtitle>",
        "text_color": "#000000",
        "thumbnail_url": "<url>",
        "title": "<title>",
        "updated_at": "2022-12-23T09:59:31.000000Z",
        "use_start_and_end": 0,
        "use_stock": 0
    }
}


GET/coupons/:identifier

Inspect a coupon

The endpoint allows you to fetch a coupon by its identifier.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    coupons.get
    Type
    string
    Description

    The scope required to access this endpoint.

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The id of the coupon you want to update.

Request

GET
/coupons/:identifier
curl -X GET https://api.walletapp.co/coupons/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
"message": "Request successful",
"data": {
        "active_label": "ongebruikt",
        "blocked_label": "geblokkeerd",
        "created_at": "<timestamp>",
        "end_date": "<timestamp>",
        "expiration_days": 30,
        "expiration_label": "Geldig t/m",
        "expired_label": "verlopen",
        "identifier": "<UUID>",
        "organization": {
            "name": "<organization_name>",
            "identifier": "<UUID>"
        },
        "points": 0,
        "price": 0,
        "primary_color": "#ffffff",
        "redeemed_label": "ingeleverd",
        "show_subtitle": 0,
        "show_title": 0,
        "start_date": "<timestamp>",
        "stock": 0,
        "subtitle": "<subtitle>",
        "text_color": "#000000",
        "thumbnail_url": "<url>",
        "title": "<title>",
        "updated_at": "2022-12-23T09:59:31.000000Z",
        "use_start_and_end": 0,
        "use_stock": 0
    }
}

PUT/coupons/:identifier

Update a coupon

The endpoint allows you to modify a coupon

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    coupons.update
    Type
    string
    Description

    The scope required to access this endpoint.

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The id of the coupon you want to update.

Request body

  • Name
    title
    Type
    string
    Description

    The title of the coupon.

  • Name
    subtitle
    Type
    string
    Description

    The subtitle of the coupon.

  • Name
    organization_id
    Type
    string
    Description

    The organization id the coupon should be updated to.

  • Name
    description
    Type
    string
    Description

    The webshop description of a coupon.

  • Name
    thumbnail_url
    Type
    string|url
    Description

    A valid url to the thumbnail image of a coupon.

  • Name
    price
    Type
    float
    Description

    The webshop price of a coupon.

  • Name
    points
    Type
    integer
    Description

    The webshop amount of points for a coupon.

  • Name
    expiration_label
    Type
    string
    Description

    The text shown in the apple wallet for the expiration date.

  • Name
    expiration_days
    Type
    integer
    Description

    The amount of days the associated pass will be valid for after creation.

  • Name
    blocked_label
    Type
    string
    Description

    The text in the apple wallet for once a coupon is blocked.

  • Name
    expired_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass has expired.

  • Name
    active_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass is active.

  • Name
    redeemed_label
    Type
    string
    Description

    The text shown in the apple wallet once a pass has been redeemed.

  • Name
    show_title
    Type
    boolean
    Description

    whether or not to show the title in the apple wallet.

  • Name
    show_subtitle
    Type
    boolean
    Description

    whether or not to show the subtitle in the apple wallet.

  • Name
    primary_color
    Type
    string
    Description

    A Hexadecimal color code for the primary color of the coupon (background color for the apple wallet pass).

  • Name
    text_color
    Type
    string
    Description

    A Hexadecimal color code for the text color of the coupon (text color for the apple wallet pass).

  • Name
    label_color
    Type
    string
    Description

    A Hexadecimal color code for the label color of the coupon (label color for the apple wallet pass).

  • Name
    stock
    Type
    integer
    Description

    Amount of coupons available for sale or usage.

  • Name
    use_stock
    Type
    boolean
    Description

    whether or not to use a stock in the webshop.

  • Name
    start_date
    Type
    timestamp
    Description

    Used to set the availablity of the coupon in the webshop.

  • Name
    end_date
    Type
    timestamp
    Description

    Used to set the availablity of the coupon in the webshop.

  • Name
    use_start_and_end
    Type
    boolean
    Description

    whether or not to use a start and end date in the webshop.

Request

PUT
/coupons/:identifier
curl -X PUT https://api.walletapp.co/coupons/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"
-d '{
    "title":"<your_title>",
    "subtitle":"<your_subtitle>",
    "description":"<your_description>",
    "organization_id":"<organization_id>",
    "thumbnail_url":"<image_url>",
    "price": 1.50,
    "expiration_label":"Pass status",
    "expiration_days": 22,
    "expired_label":"Expired",
    "primary_color":"#ff00ff",
    "text_color":"#ff0000",
    "label_color":"#00ff00",
    "show_title": true,
    "show_subtitle": true,
    "active_label":"Active",
    "blocked_label":"Blocked",
    "redeemed_label":"Redeemed",
    "points": 12,
    "use_stock": true,
    "use_start_and_end": true,
    "stock":15,
    "start_date": "2022-01-01",
    "end_date":"2023-01-01"
}'

Response

{
"message": "Request successful",
"data": {
        "active_label": "ongebruikt",
        "blocked_label": "geblokkeerd",
        "created_at": "<timestamp>",
        "end_date": "<timestamp>",
        "expiration_days": 30,
        "expiration_label": "Geldig t/m",
        "expired_label": "verlopen",
        "identifier": "<UUID>",
        "organization": {
            "name": "<organization_name>",
            "identifier": "<UUID>"
        },
        "points": 0,
        "price": 0,
        "primary_color": "#ffffff",
        "redeemed_label": "ingeleverd",
        "show_subtitle": 0,
        "show_title": 0,
        "start_date": "<timestamp>",
        "stock": 0,
        "subtitle": "<subtitle>",
        "text_color": "#000000",
        "thumbnail_url": "<url>",
        "title": "<title>",
        "updated_at": "2022-12-23T09:59:31.000000Z",
        "use_start_and_end": 0,
        "use_stock": 0
    }
}

DELETE/coupons/:identifier

Delete a coupon

The endpoint allows you to delete a coupon.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    coupons.delete
    Type
    string
    Description

    The scope required to access this endpoint.

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The id of the coupon you want to update.

Request

DELETE
/coupons/:identifier
curl -X delete https://api.walletapp.co/coupons/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
    "message": "Request successful",
    "data": "Coupon Archived",
}

PATCH/coupons/:identifier

Restore a coupon

The endpoint allows you to restore a coupon.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    coupons.delete
    Type
    string
    Description

    The scope required to access this endpoint.

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The id of the coupon you want to update.

Request

PATCH
/coupons/:identifier
curl -X PATCH https://api.walletapp.co/coupons/:identifier
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response

{
    "message": "Request successful",
    "data": "Coupon Restored",
}

POST/coupons/:identifier/redemptions

Redeem a points reward

Redeems a coupon that costs points for a member in one atomic step: the points are deducted from the member's storecard, a coupon pass is issued to the member already marked as redeemed, and the stock goes down by one. Either all of it happens or none of it does; there is no state where points are gone but no reward was registered.

The call is idempotent on reference: sending the same reference again changes nothing and returns was_duplicate: true with the original result (200), so it is safe to retry after a timeout. A reference is unique per coupon; reusing it for another member or storecard returns 409. Re-sending the reference of a reversed redemption returns the original (reversed) result and deducts nothing; to redeem again, use a new reference.

The points are deducted as a normal points transaction (reference redeem-<reference>, description Reward: <coupon title>), so it appears in the points history and in GET /storecards/:identifier/transactions. If you have a webhook subscription you receive points.changed, coupon.issued and coupon.redeemed once each, after the redemption was committed.

Which storecard? The points come from the member's storecard with points in the organization of the coupon. When the member has exactly one, it is used. When the member has several, storecard_id is required (422, storecard_required, the response lists the candidates). Points are never split over several cards.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

  • Name
    Idempotency-Key
    Type
    string|optional
    Description

    Optional. When sent it must equal reference, otherwise the call is rejected with 422. The general Idempotency-Key behavior applies on top: the same key with the same body within 24 hours replays the first response (201, with Idempotent-Replayed: true) without running again, and the same key with a different body returns 422. A replay shows the state of the first response; without the header, reference alone returns the current state (200, was_duplicate: true).

Abilities

  • Name
    coupons.store
    Type
    string
    Description

    Required.

  • Name
    storecards.store
    Type
    string
    Description

    Required as well, because points are deducted. Without it the call returns 403.

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The identifier of the coupon. It must belong to the organization of your token, otherwise 404.

Body parameters

  • Name
    member_id
    Type
    string|Required
    Description

    The member's UUID (member_id as returned by the members endpoints).

  • Name
    reference
    Type
    string|Required
    Description

    Your own unique id for this redemption, for example a till receipt number (max 56 characters).

  • Name
    storecard_id
    Type
    string|optional
    Description

    The identifier of the storecard to take the points from. Only needed when the member has more than one storecard with points.

Response fields

  • Name
    redemption_id
    Type
    integer
    Description

    Use this to reverse the redemption.

  • Name
    status
    Type
    string
    Description

    redeemed or reversed.

  • Name
    pass_id
    Type
    string
    Description

    The UUID of the coupon pass that was issued to the member.

  • Name
    points_spent
    Type
    integer
    Description

    The coupon's points price.

  • Name
    points_balance
    Type
    number
    Description

    The member's points on that storecard after the redemption.

  • Name
    stock
    Type
    integer|null
    Description

    Remaining stock, or null when the coupon does not use stock management.

Errors

  • Name
    403
    Type
    status
    Description

    The token misses storecards.store.

  • Name
    404
    Type
    status
    Description

    coupon_not_found, member_not_found (also for a member of another organization) or storecard_not_found.

  • Name
    409
    Type
    status
    Description

    reference_conflict: the reference was used for another member or storecard.

  • Name
    422
    Type
    status
    Description

    insufficient_points, out_of_stock, coupon_unavailable (archived, no points price, outside its start and end date, or a voucher type that needs an external code), storecard_required, pass_blocked / pass_disabled, or a validation error.

Request

POST
/coupons/:identifier/redemptions
curl -X POST https://api.walletapp.co/coupons/cpn_free_coffee/redemptions
-H "Content-Type: application/json"
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"
-d '{
    "member_id": "0b7d5c1e-3f0a-4d51-9a64-2f5c1d8e7a10",
    "reference": "till-2026-10-09-0042"
}'

Response (201 Created)

{
    "data": {
        "redemption_id": 318,
        "reference": "till-2026-10-09-0042",
        "was_duplicate": false,
        "status": "redeemed",
        "coupon_id": "cpn_free_coffee",
        "member_id": "0b7d5c1e-3f0a-4d51-9a64-2f5c1d8e7a10",
        "storecard_id": "sc_8f3a1c",
        "pass_id": "5e0c9a52-7b1d-4a6e-8f33-0c2d9b6a41e7",
        "points_spent": 40,
        "points_balance": 60,
        "points_transaction_id": 1051,
        "reversal_transaction_id": null,
        "stock": 24,
        "redeemed_at": "2026-10-09T14:12:05+02:00",
        "reversed_at": null
    }
}

Response on a retry (200 OK)

{
    "data": {
        "redemption_id": 318,
        "was_duplicate": true,
        "status": "redeemed",
        "...": "same as the original response"
    }
}

Not enough points (422)

{
    "error": "insufficient_points",
    "message": "The member does not have enough points"
}

Several storecards (422)

{
    "error": "storecard_required",
    "message": "The member has several storecards with points: pass storecard_id",
    "storecards": ["sc_8f3a1c", "sc_2d77e0"]
}

POST/coupons/:identifier/redemptions/:id/reverse

Reverse a redemption

Reverses a redemption exactly once and atomically: the points are refunded (a compensating points transaction with the reference reverse-redeem-<reference>, see Reverse a transaction), the stock is restored, and the coupon pass that was issued is voided.

A voided pass is no longer counted as redeemed and is blocked, so the member cannot use the reward after getting the points back. A second reversal returns 409 (already_reversed) and changes nothing. The original reference stays used: repeating the original redeem call returns the redemption with status: reversed and does not redeem again; use a new reference to redeem again.

Required headers

  • Name
    Authorization
    Type
    string
    Description

    The token itself as a bearer token.

Abilities

  • Name
    coupons.store
    Type
    string
    Description

    Required.

  • Name
    storecards.store
    Type
    string
    Description

    Required as well, because points are refunded.

Route parameters

  • Name
    identifier
    Type
    string
    Description

    The identifier of the coupon of the redemption.

  • Name
    id
    Type
    integer
    Description

    The redemption_id returned when the reward was redeemed.

Errors

  • Name
    404
    Type
    status
    Description

    coupon_not_found or redemption_not_found.

  • Name
    409
    Type
    status
    Description

    already_reversed.

  • Name
    422
    Type
    status
    Description

    pass_blocked / pass_disabled: the member's storecard pass was blocked since, so points cannot be refunded; nothing is changed.

Request

POST
/coupons/:identifier/redemptions/:id/reverse
curl -X POST https://api.walletapp.co/coupons/cpn_free_coffee/redemptions/318/reverse
-H "Accept: application/json"
-H "Authorization: Bearer <your_token>"

Response (200 OK)

{
    "data": {
        "redemption_id": 318,
        "reference": "till-2026-10-09-0042",
        "was_duplicate": false,
        "status": "reversed",
        "coupon_id": "cpn_free_coffee",
        "member_id": "0b7d5c1e-3f0a-4d51-9a64-2f5c1d8e7a10",
        "storecard_id": "sc_8f3a1c",
        "pass_id": "5e0c9a52-7b1d-4a6e-8f33-0c2d9b6a41e7",
        "points_spent": 40,
        "points_balance": 100,
        "points_transaction_id": 1051,
        "reversal_transaction_id": 1052,
        "stock": 25,
        "redeemed_at": "2026-10-09T14:12:05+02:00",
        "reversed_at": "2026-10-09T14:20:41+02:00"
    }
}

Response on a second reversal (409)

{
    "error": "already_reversed",
    "message": "Redemption was already reversed",
    "redemption_id": 318,
    "reversed_at": "2026-10-09T14:20:41+02:00"
}