Loyalty API (v2)

Download OpenAPI specification:Download

This document is a technical description of the Loyalty API for Storebox. The Storebox Loyalty API is the programming interface for the Storebox Loyalty Bank.

Storebox Loyalty Bank is an API that provides merchants the opportunity to dynamically track their customers purchase history patterns and award points or coupons based on business rules and for users of the loyalty program to utilize these points and coupons.

The Storebox Loyalty Bank includes services for linking customers to the bank and any existing loyalty programs that may exist for future reference, so that the Storebox Loyalty Bank can be used with an existing loyalty card.

Merchants can use the API to integrate purchases in the physical store or at their webshop to the Storebox Loyalty Bank and thereby have a central and simple identification process based on the customers’ payment card (PAN).

The intended audience for this documentation is technicians developing system integration to Storebox.

The Storebox Loyalty API is organized around REST. The API is designed to have predictable, resource-oriented URLs and to use HTTP response codes to indicate API errors. We use built-in HTTP features, like HTTP authentication and HTTP verbs. JSON is the data interchange format and will be returned in responses from the API, including errors.

Users

Users are a central part the loyalty API. They are the entity to be identified based on provided tokens and will often have coupons, points and/or cards associated.

Concepts:

Member id A user can have one or more member ids with an associated type, for identification purposes. A member id is provided upon user creation and must be unique.
Member type To each of the member id there can be connected member type. Member type can later be used to filter users when assigning points.
User linkage Users can linked either one-directional or bi-directional. The linkage can be used at lookup time to identify whether a member is part of a company, family, etc.

Create a new user

Creates a new user, associates it with the given member ids and links it with the given linkedMemberIds

Request Body schema: application/json
required
Array of objects (member-id-set)
Array of objects (member-id-set)

Responses

Request samples

Content type
application/json
{
  • "memberIds": [
    ],
  • "linkedMemberIds": [
    ]
}

Response samples

Content type
application/json
{
  • "userId": "string"
}

Get user on member id

Lookup a user based on a provided member Id. This endpoint will return all relevant information on the user like memberIds, points (if enabled), coupons (if enabled) and linked users (if enabled).

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Response samples

Content type
application/json
{
  • "provider": "storebox",
  • "memberIds": [
    ],
  • "card": {
    },
  • "linkedMemberIds": [
    ],
  • "coupons": [
    ]
}

Delete a user

Deletes the user on the specified memberId. Deleting a user will delete all cards, coupons, points, etc. associated with the user. This operation cannot be undone.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Update a user

Add/remove member ids and add/remove linked users

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Request Body schema: application/json
Array of objects (member-id-set)
Array of objects (member-id-set)
Array of objects (member-id-set)
Array of objects (member-id-set)

Responses

Request samples

Content type
application/json
{
  • "addMemberIds": [
    ],
  • "removeMemberIds": [
    ],
  • "addLinkedMemberIds": [
    ],
  • "removeLinkedMemberIds": [
    ]
}

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Get basic user by token

Lookup a user based on token. This endpoint keeps the footprint small and will only return the most basic user and card information.

query Parameters
token
required
string

Token referencing the users card

Responses

Response samples

Content type
application/json
{
  • "provider": "storebox",
  • "memberIds": [
    ],
  • "prefersNoPrintedReceipts": true,
  • "card": {
    }
}

Get user by token

Lookup a user based on a provided token. This endpoint will return all relevant information on the user like memberIds, points (if enabled), coupons (if enabled) and linked users (if enabled).

path Parameters
token
required
string

Token referencing the users card

Responses

Response samples

Content type
application/json
{
  • "provider": "storebox",
  • "memberIds": [
    ],
  • "card": {
    },
  • "linkedMemberIds": [
    ],
  • "coupons": [
    ]
}

Get users by token - includes linked users

Like the get user endpoint this endpoint returns the user found, based on the provided token. In addition, this endpoint will also return all directly linked members complete with coupons, points etc.

path Parameters
token
required
string

Token referencing the users card

Responses

Response samples

Content type
application/json
{
  • "memberIds": [
    ],
  • "coupons": [
    ],
  • "linkedMember": [
    ]
}

Get users by member id - includes linked users

Like the get user endpoint this endpoint returns the user found, based on the provided member id. In addition, this endpoint will also return all directly linked members complete with coupons, points etc.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Response samples

Content type
application/json
{
  • "memberIds": [
    ],
  • "coupons": [
    ],
  • "linkedMember": [
    ]
}

Cards

Cards are another central part of the loyalty API.

When users have registered their card number, Storebox will collect and maintian token values from multiple sources in order to identify users realtime based on their paymentcard. This usually requires collaboration with the terminal which provides the token sent to Storebox.

Note that Storebox stores cards in a PCI-DSS compliant environment and never exposes a users raw card number. All endpoints containing card information returns only a masked version of the card number.

Concepts:

Truncated/Masked card number A masked card number consists of the first 6 and last 4 digits of the card number. The middle digits have been replaced by a character, we use X.
Example: 4571000000000000 -> 457100XXXXXX0000
Token A token is a one-way reference to a card number. Tokens are usually looked up in PSP systems via a payment terminal, which in turn can be used to obtain a user from the loyalty API.
Card types When cards are entered in Storebox, we identify the type of the card based on the IIN.

The identified type resolves to a cardType:
1 - Dankort/VISA Dankort
2 - eDankort
3 - VISA/VISA Electron
4 - Mastercard
5 - Reserved
6 - JCB
7 - Maestro
8 - Diners Club
9 - American Express
10 - Reserved
11 - Forbrugsforeningen
16 - BankAxept
Card frame To support users in registering their payment card information, Storebox delivers a PCI-DSS certified webpage.
The page can be embedded in an IFrame on any page and is highly customizable.

Show card frame

For online card registration via web or a smartphone app, a Storebox provided PCI-DSS compliant webpage must be used to comply with international card issuer standards. This webpage can be integrated with an existing webpage using an iframe or a mobile app by using a webview.

The flow can be seen in the following Figure:

Upon completed card registration Storebox can send a notification.

Strong Customer Authentication

To have Strong Customer Authentication (SCA) like 3D Secure activated contact Storebox.

If SCA is enabled, a declineurl must also be provided, when loading the cardframe. The SCA flow will start automatically after the card submit and will redirect the user through the relevant verification flow.

Only if the SCA flow is successfull will the card be added to Storebox and the user will be redirected to the accept URL. If the flow for some reason is unsuccessfull the user will be redirected to the decline URL.

Basic example

Server-side you generate the cardframe URL with all parameters (salt must never fall in the hands of client) and provide it to the client.

A quick demo can be had via https://developer.storebox.com/frame/index.html

Example data:

Hash generation: md5(id + accepturl + declineurl + callbackurl + cssurl + languageurl + salt) md5 -s yourcustomeridhttps://developer.storebox.com/frame/accepted.htmlhttps://developer.storebox.com/frame/declined.htmlhttps://storebox.comhttps://developer.storebox.com/frame/assets/card.css?v=5https://developer.storebox.com/frame/assets/lang.json?v=64H8r63CSEYvbdJarNpF7

Final URL with proper URL encoded parameters, provider and hash that is provided to client: https://test-loyalty.storebox.com/v2/cards/url?id=yourcustomerid1&accepturl=https%3A%2F%2Fdeveloper.storebox.com%2Fframe%2Faccepted.html&declineurl=https%3A%2F%2Fdeveloper.storebox.com%2Fframe%2Fdeclined.html&callbackurl=https%3A%2F%2Fstorebox.com&cssurl=https%3A%2F%2Fdeveloper.storebox.com%2Fframe%2Fassets%2Fcard.css%3Fv%3D5&languageurl=https%3A%2F%2Fdeveloper.storebox.com%2Fframe%2Fassets%2Flang.json%3Fv%3D6&provider=yourproviderid&hash=1045d4756af23a321429ae55766bd15d

Result in browser

Result

Styling

The card frame is styled via the CSS specified in the cssurlparameter in the initial call.

The stylesheet is cached and is only downloaded if the URL changes. For this reason a version parameter can be used in the cssurl, for example https://.../style.css?v=1. Please refrain from using a constantly changing parameter, like a timestamp.

This is the Card Frame HTML structure that can be styled:

<form class="">
  <div class="field field-input">
    <div class="field-label">Kortnummer</div>
    <input type="tel" value="" placeholder="Kortnummer" name="CardNumber" id="CardNumber" autocomplete="off" required="" class="">
    <span class="field-validation-error">Ugyldigt kortnummer</span>
  </div>
  <div class="field field-input">
    <div class="field-label">Udløbsmåned</div>
    <input type="tel" value="" placeholder="Indtast udløbsmåned" name="ExpMonth" id="ExpMonth" autocomplete="off" required="" maxlength="2" class="">
    <span class="field-validation-valid"></span>
  </div>
  <div class="field field-input">
    <div class="field-label">Udløbsår</div>
    <input type="tel" value="" placeholder="Indtast udløbsår" name="ExpYear" id="ExpYear" autocomplete="off" required="" maxlength="2" class="">
    <span class="field-validation-valid"></span>
  </div>
  <div class="field field-btn">
    <input type="submit" value="Gem kort" class="button" id="submit" name="add" disabled="disabled">
  </div>
</form>

<div class="generalError">
</div>

<div class="maxCards">
</div>

JSON language file

A JSON file specified in languageurl configures the text displayed in the card input. The file contains a translation label and value like in the following example. The language file must be provided in UTF-8.

{
  "expMonth": {
    "errorInvalid": "Skal være mellem 1 og 12",
    "label": "Udløbsmåned",
    "placeholder": "Indtast udløbsmåned"
  },
  "expYear":{
    "label": "Udløbsår",
    "placeholder": "Indtast udløbsår",
    "errorExpired":"Kortet er udløbet"
  },
  "error":{
    "generalError":"Der skete en fejl. Prøv venligst igen",
    "maxCards":"Du kan ikke tilføje flere kort"
  },
  "btn":{
    "save":"Gem kort"
  },
  "card":{
    "errorInvalid":"Ugyldigt kortnummer",
    "unsupportedType":"Denne korttype kan ikke bruges",
    "unsupportedBinRange":"Dette kortnummer kan ikke bruges",
    "label":"Kortnummer",
    "placeholder":"Indtast kortnummer",
    "duplicate":"Kortet er allerede registreret"
  }
}

The text values are cached and are only downloaded if the URL changes. For this reason a version parameter should be used in the languageurl, for example https://.../en.json?v=1. Please refrain from using a constantly changing parameter, like a timestamp.

Card Created Notification

When a card has been fully processed a callback (GET) will happen if the callbackUrl parameter was defined on initial cardframe request.

A call to list cards is only guaranteed to include a newly created card after the notification has been sent. Under some circumstances a notification may be sent more than once. The notification will be sent as a server to server GET request and is documented under 'Callbacks' below.

The callback does not act upon the responses sent from the callbackurl endpoint. I.e. a redirect will not be followed.

query Parameters
id
required
string

Member id of the user that should have the card appended

provider
required
string

The card provider (container/owner) in Storebox systems

accepturl
required
string

The URL where the page is redirected after successful card submit

declineurl
string

Required if Strong Customer Authentication (like 3DS) is enabled. The URL where the page is redirected after unsuccessful Strong Customer Authentication.

callbackurl
string

The URL that receives a callback once a submitted card is ready for use. Must be accessible from Storebox servers.

cssurl
required
string

Absolute URL for the CSS file for input styling. Must be accessible from Storebox servers.

languageurl
string

Public URL for the translation JSON file. Must be accessible from Storebox servers.

type
string
Enum: "card" "accountno"

What type of frame should be displayed. Default is the card frame

Possible values

  • card - card input
  • accountno - account number input
hash
required
string

MD5 hash of the value of the parameters plus a salt, md5(id + accepturl + declineurl + callbackurl + cssurl + languageurl + salt).
The salt is provided by Storebox

Responses

Callbacks

List cards

Returns a list of cards registered to the user

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Start card verification

If existing cards are stored in Storebox, which have not yet been verified by 3DS, this endpoint can be used to start the 3DS flow.

The card owner must complete the authentication, so this endpoint will redirect and start the 3DS flow. The endpoint integration must therefore be from a browser or webview like the card frame.

After a successful completion the card will be marked as verified.

query Parameters
provider
required
string

The card provider (container/owner) in Storebox systems.

externalCardId
required
string

Id of the card to verify. The card id was delivered in the callback on card creation.

accepturl
required
string

The URL where the page is redirected after successful card verification. This happens in the frontend so app handlers can be used.

declineurl
required
string

The URL where the page is redirected if the verification was unsuccessful. This happens in the frontend so app handlers can be used.

hash
required
string

MD5 hash of the value of the parameters plus a salt, md5(provider + externalCardId + accepturl + declineurl + salt).
The salt is provided by Storebox.

Responses

Delete card

Deletes the card referenced by cardId. This also deletes the card in the PCI-DSS environment and cannot be undone.

path Parameters
cardId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

ExternalCardId of the card.

Responses

Update card

Update the name of the card. Emojis are not supported.

path Parameters
cardId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

ExternalCardId of the card.

Request Body schema: application/json
name
required
string <= 64 characters

The name of the card. Emojis are not supported.

object

Optional metadata describing the card, this could be whether the card has been externally verified or blacklisted.

Note that all metadata are overridden if the property is set, so it has to be a full set of metadata.

Responses

Request samples

Content type
application/json
{
  • "name": "Kostkort",
  • "metadata": {
    }
}

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Pending Cards

A pending card, is a card that is temporarily stored in Storebox' PCI environment. It cannot be looked up via cardlink functionality. The card is entered via i.e. a terminal integration or via an external PCI environment. The pending state, allows the enduser to enter any information needed and accept terms before the card is enrolled. Once the enduser creation is completed the card can be activated by the activation code.

The supported way of entering a pending card is currently:

  • Via Payment Terminals backed by Nets DAM

A pending card is deleted after 30 days if it has not been activated.

Verify that an activation code is known.

Verifies that an activation code is known. This may be done before starting a signup flow.

path Parameters
activationCode
required
string

Id of the pendingcard to be activated

Responses

Fully enroll the card

Enroll the pending card and enable it to be lookup up

path Parameters
activationCode
required
string

Id of the pendingcard to be activated

Request Body schema: application/json
memberId
string

Id of the member that should have the pending card associated

Responses

Request samples

Content type
application/json
{
  • "memberId": "e75ca15c8ae1401c943ff15df437f1d8"
}

Coupons

A coupon (or voucher) is a "ticket or small printed piece of paper that entitles the holder to a discount, or that may be exchanged for goods or services."

The typical coupon operations are: assign -> authorize -> capture/cancel. Cancel removes the authorize state from a coupon so its use is unlocked and it may be authorized/captured again. Multi-use coupons can be authorized while they have usages left to authorize. An authorized coupon/usage will wait for capture/cancel for 3 hours, after which the authorize will be automatically cancelled and the coupon/usage is available again.

The get user endpoint, returns both points and coupons of a user. This section contains more specialized coupon endpoints.

Authorized coupons are not returned in lookups.

Campaign name and code are used to define a context.

List user coupons

Returns all user coupons, that are not in authorized state

path Parameters
token
required
string

Token referencing the users card

Responses

Response samples

Content type
application/json
{
  • "couponId": "WYgJ41dzZMTvFywjUPFFbf3ylzMVm83G",
  • "couponName": "30% off pepperoni pizza",
  • "startDate": "2022-05-14T15:22:11Z",
  • "expiryDate": "2022-05-14T15:22:11Z",
  • "campaignCode": "campaign-502",
  • "campaignName": "Summer special",
  • "useCount": 1,
  • "value": 7,
  • "metadata": {
    }
}

Assign coupon by token

Assigns a coupon as defined in the request to the member referenced by the token.

path Parameters
token
required
string

Token referencing the users card

Request Body schema: application/json
couponName
required
string

Human readable name of the coupon

startDate
string <date-time> (iso-8601)

Date-time notation as defined by RFC 3339, section 5.6, for example, 2022-05-14T15:22:11Z

expiryDate
required
string <date-time> (iso-8601)

Date-time notation as defined by RFC 3339, section 5.6, for example, 2022-05-14T15:22:11Z

campaignCode
string

Campaigncode can be used to identify the campaign

campaignName
required
string

Name of the campaign the coupon is associated with

useCount
integer <int32> (coupon-useCount)
Default: -1

Indicator showing how many uses the coupon has left

1 Single use
>1 Multi use
-1 Unlimited use

value
integer <int32>

Default 0
Indicator of the coupons discount rate. The unit of "value" can be decided by the integrating part.

Responses

Request samples

Content type
application/json
{
  • "couponName": "30% off pepperoni pizza",
  • "startDate": "2022-05-14T15:22:11Z",
  • "expiryDate": "2022-05-14T15:22:11Z",
  • "campaignCode": "campaign-502",
  • "campaignName": "Summer special",
  • "useCount": 1,
  • "value": 7
}

Response samples

Content type
application/json
{
  • "couponId": "WYgJ41dzZMTvFywjUPFFbf3ylzMVm83G"
}

Pre-authorize and list all of a users coupons

Returns all the coupons to a user. Before the coupons are returned they are all authorized, so they are ready to be captured or cancelled. Please note! Authorized coupons (or usages on multi-use coupons) are locked until the authorizations have been either cancelled or captured or a 3 hour window has passed and the authorization is auto cancelled.

path Parameters
token
required
string

Token referencing the users card

Responses

Response samples

Content type
application/json
{
  • "memberIds": [
    ],
  • "linkedMemberIds": [
    ],
  • "coupons": [
    ]
}

Assign coupon(s) to multiple users

Assign multiple coupons as defined in the request to multiple users. Each user in the list will be given coupons based on the contents of the couponTemplates in the request.

Please note that the term couponTemplates in this context is literal and refers only to the request data as templates for issuing coupons for that specific request. It is not a reference to the Coupon Template concept and endpoints and no template is persisted in any way. Use the 'create coupon template' method in case a persisted template is desired, from which coupons can be assigned at any time.

Request Body schema: application/json
Array of objects

Responses

Request samples

Content type
application/json
{
  • "couponTemplates": [
    ]
}

Response samples

Content type
application/json
{
  • "generatedCoupons": [
    ],
  • "memberIdsNotFound": [
    ]
}

Delete a coupon

Endpoint to delete a specific coupon. This cannot be undone.

path Parameters
couponId
required
string

Id of specific coupon

Responses

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Authorize coupon

Authorize/reserve a coupon to avoid simultaneous uses of the same coupon.

An authorization attempt will fail if:

  • The coupon is already authorized (incl. multiuse/unlimited coupons)
  • An authorization is attempted before startDate or after expiryDate.
path Parameters
couponId
required
string

Id of specific coupon

Responses

Response samples

Content type
application/json
{
  • "eventId": "nxb3wMhjIjeElyNMQGzW431RCqLVL2vt"
}

Cancel or capture multiple coupons

Endpoint for capturing or cancelling multiple coupons in a single request.

  • A capture will remove the coupon from the user (or deduct a usage).
  • A cancel will remove the reservation on the coupon and make it available for another authorization.
Request Body schema: application/json
capture
Array of strings

eventIds to be captured

cancel
Array of strings

eventIds to be cancelled

Responses

Request samples

Content type
application/json
{
  • "capture": [
    ],
  • "cancel": [
    ]
}

Response samples

Content type
application/json
{
  • "captureStatus": [
    ],
  • "cancelStatus": [
    ]
}

Capture unauthorized coupon

If you do not want to authorize a coupon before using it, this endpoint allows for capturing a coupon that has not been authorized.

This may be because the presence of a coupon simply marks the user as being a certain kind of user (premium/platin/etc.), so mutual exclusion is not an issue.

Capturing the coupon allows Storebox to collect statistics about the usage.

path Parameters
couponId
required
string

Id of specific coupon

Responses

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Coupon Templates

Coupon Templates are predefined coupon templates with no user association.

When a Coupon Template has been created a coupon based on the template can be assigned to users in different ways:

  • Direct assignment - specify a member id that should receive a coupon based on a specific template
  • Batch assignment - specify a template based on which a coupon should be assigned to all users
  • Progress based assignment by templateId or by campaignCode - Coupon Templates can thus act as a point counter by setting the value "progressGoal" to ie. 10.

    When registering progress to a user on a template, the system stores the progress over time. When the point goal is reached, a coupon based on the template is assigned to the user and the counter is automatically reset. Any overflow of points will count towards next coupon.

Create Coupon Template

Creates a new template. Once a template is created, progress for individual users can be registered towards its progress goal, it can be assigned on signup or it can be used to directly assign coupons to users.

Request Body schema: application/json
templateName
required
string

Human readable name of the template, for example "Coffee discount template"

couponName
required
string

Human readable name of the coupon when assigned, for example "Here's half off on your next coffee!"

startDate
string <date-time>

Date-time notation as defined by RFC 3339, section 5.6, for example, 2022-05-14T15:22:11Z

Absolute start date and time of coupons assigned from template. Any coupon assigned earlier than a templates startDate and will get startDate now().

expiryDate
required
string <date-time>

Date-time notation as defined by RFC 3339, section 5.6, for example, 2024-05-14T15:22:11Z

Absolute expiry date of coupons assigned from template. Use voucherExpiry for setting a relative expiry date on assigned coupons.

campaignName
required
string

Human readable name of the campaign

campaignCode
required
string

A unique code identifying the campaign.

progressGoal
required
integer <int32>

How many points are needed to trigger a coupon creation.

value
integer <int32>
Default: 0

Metadata. A value that can be used to indicate e.g. discount level or a coupons value.

useCount
integer <int32> (coupon-useCount)
Default: -1

Indicator showing how many uses the coupon has left

1 Single use
>1 Multi use
-1 Unlimited use

assignOnSignup
boolean
Default: false

If true, new users will be assigned a coupon based on the template, when they sign up

voucherExpiry
string

Assigned coupons will be created with an expiryDate relative to date-time of issuing.

Must follow the regular expression pattern: ^([DWM])(\d*)$

Available time units: D(ays), W(eeks), M(onths). Examples:

  • D5 - coupon expires 5 days after assignment
  • W12 - coupon expires 12 weeks after assignment
  • M6 - coupon expires 6 months after assignment
object

Responses

Request samples

Content type
application/json
{
  • "templateName": "Coffee discount template",
  • "couponName": "Here's half off on your next coffee!",
  • "startDate": "2022-05-14T15:22:11Z",
  • "expiryDate": "2024-05-14T15:22:11Z",
  • "campaignName": "Discount on your 10th. cup of coffee",
  • "campaignCode": "campaign-502",
  • "progressGoal": 10,
  • "value": 50,
  • "useCount": 1,
  • "assignOnSignup": false,
  • "voucherExpiry": "W2",
  • "metadata": {
    }
}

Response samples

Content type
application/json
{
  • "couponTemplateId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj"
}

List all Coupon Templates

Get all Coupon Templates

Responses

Response samples

Content type
application/json
{
  • "count": 1,
  • "templates": [
    ]
}

Update Coupon Template

Update an existing Coupon Template

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Request Body schema: application/json
templateName
required
string

Human readable name of the template, for example "Coffee discount template"

couponName
required
string

Human readable name of the coupon when assigned, for example "Here's half off on your next coffee!"

startDate
string <date-time>

Date-time notation as defined by RFC 3339, section 5.6, for example, 2022-05-14T15:22:11Z

Absolute start date and time of coupons assigned from template. Any coupon assigned earlier than a templates startDate and will get startDate now().

expiryDate
required
string <date-time>

Date-time notation as defined by RFC 3339, section 5.6, for example, 2024-05-14T15:22:11Z

Absolute expiry date of coupons assigned from template. Use voucherExpiry for setting a relative expiry date on assigned coupons.

campaignName
required
string

Human readable name of the campaign

campaignCode
required
string

A unique code identifying the campaign.

progressGoal
required
integer <int32>

How many points are needed to trigger a coupon creation.

value
integer <int32>
Default: 0

Metadata. A value that can be used to indicate e.g. discount level or a coupons value.

useCount
integer <int32> (coupon-useCount)
Default: -1

Indicator showing how many uses the coupon has left

1 Single use
>1 Multi use
-1 Unlimited use

assignOnSignup
boolean
Default: false

If true, new users will be assigned a coupon based on the template, when they sign up

voucherExpiry
string

Assigned coupons will be created with an expiryDate relative to date-time of issuing.

Must follow the regular expression pattern: ^([DWM])(\d*)$

Available time units: D(ays), W(eeks), M(onths). Examples:

  • D5 - coupon expires 5 days after assignment
  • W12 - coupon expires 12 weeks after assignment
  • M6 - coupon expires 6 months after assignment

Responses

Request samples

Content type
application/json
{
  • "templateName": "Coffee discount template",
  • "couponName": "Here's half off on your next coffee!",
  • "startDate": "2022-05-14T15:22:11Z",
  • "expiryDate": "2024-05-14T15:22:11Z",
  • "campaignName": "Discount on your 10th. cup of coffee",
  • "campaignCode": "campaign-502",
  • "progressGoal": 10,
  • "value": 50,
  • "useCount": 1,
  • "assignOnSignup": false,
  • "voucherExpiry": "W2"
}

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Delete Coupon Template

Delete a Coupon Template

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Responses

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Get Coupon Template

Get a specific Coupon Template

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Responses

Response samples

Content type
application/json
{
  • "templateId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "templateName": "Coffee discount template",
  • "couponName": "Here's half off on your next coffee!",
  • "startDate": "2022-05-14T15:22:11Z",
  • "expiryDate": "2024-05-14T15:22:11Z",
  • "campaignName": "Discount on your 10th. cup of coffee",
  • "campaignCode": "campaign-502",
  • "progressGoal": 10,
  • "value": 50,
  • "useCount": 1,
  • "assignOnSignup": false,
  • "voucherExpiry": "W2",
  • "metadata": {
    }
}

Register user progress by templateId

Using templateId to reference a coupon template and register user progress towards a coupon. Once the progressGoal is reached a coupon is automatically assigned to the user. Progress counts up by the registered progress. Progress and issuing of coupons is cyclic. If the registered progress exceeds progressGoal then any leftover progress goes towards next coupon.

Example: progressGoal is 5. Current progress is 4. Registering progress of 3 will assign a coupon and the progress is now 2.

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Request Body schema: application/json
memberId
required
string
progress
required
integer <int32>

Responses

Request samples

Content type
application/json
{
  • "memberId": "aa987654321",
  • "progress": 5
}

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Register user progress by campaignCode

Using campaignCode to reference a coupon template and register user progress towards a coupon. Once the progressGoal is reached a coupon is automatically assigned to the user. Progress counts up by the registered progress. Progress and issuing of coupons is cyclic. If the registered progress exceeds progressGoal then any leftover progress goes towards next coupon.

Example: progressGoal is 5. Current progress is 4. Registering progress of 3 will assign a coupon and the progress is now 2.

path Parameters
campaignCode
required
string
Example: campaign-502

campaignCode of the Coupon Template

Request Body schema: application/json
memberId
required
string
progress
required
integer <int32>

Responses

Request samples

Content type
application/json
{
  • "memberId": "aa987654321",
  • "progress": 5
}

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Get user progress

Get all progress information on a specific member.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Assign a coupon from template

Assign a single coupon based on a Coupon Template to a single user

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Response samples

Content type
application/json
{
  • "couponId": "WYgJ41dzZMTvFywjUPFFbf3ylzMVm83G",
  • "couponName": "30% off pepperoni pizza",
  • "startDate": "2022-05-14T15:22:11Z",
  • "expiryDate": "2022-05-14T15:22:11Z",
  • "campaignCode": "campaign-502",
  • "campaignName": "Summer special",
  • "useCount": 1,
  • "value": 7
}

Assign a coupon from template to all

Assign coupon to all users based on a specific template

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Responses

Response samples

Content type
application/json
{
  • "userCount": 58235
}

Set coupon template metadata

Set extra information as name/value pairs on a template. The name/value pairs are returned in coupons created be the referenced template. If a metatdata name already exists, it is overriden with the new value.

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Request Body schema: application/json
Array of objects

List of metadata name/value pairs to be added

removeMetadata
Array of strings

List of metadata name/value pairs to be deleted

Responses

Request samples

Content type
application/json
{
  • "addMetadata": [
    ],
  • "removeMetadata": [
    ]
}

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Create Template Filter

Creates a new assignment filter for the coupon template. When assigning a coupon based on a template, the filter is used to ensure that the users metadata qualifies for the coupon. Currently only 'country' is supported.

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Request Body schema: application/json
filterType
required
string

Type of the filter. Supported values: "country"

filterValues
required
Array of strings

List of filter values

Responses

Request samples

Content type
application/json
{
  • "filterType": "country",
  • "filterValues": [
    ]
}

Response samples

Content type
application/json
{
  • "filterType": "country",
  • "filterValues": [
    ],
  • "filterId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj"
}

List all Template Filters

Get all filters for the template

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Delete Filters for Template

Delete all filters for the template

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

Responses

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Update Template Filter

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

filterId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template Filter

Request Body schema: application/json
filterType
required
string

Type of the filter. Supported values: "country"

filterValues
required
Array of strings

List of filter values

Responses

Request samples

Content type
application/json
{
  • "filterType": "country",
  • "filterValues": [
    ]
}

Response samples

Content type
application/json
{
  • "filterType": "country",
  • "filterValues": [
    ],
  • "filterId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj"
}

Delete single Template filter

Delete specific filters to the template

path Parameters
couponTemplateId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template

filterId
required
string
Example: ptsnaxm5q5bazf9y1b1ek42a3isxosuj

Id of the Coupon Template Filter

Responses

Response samples

Content type
application/json
{
  • "timestamp": 1549880850241,
  • "status": "40X",
  • "error": "Http status text",
  • "message": "Cause of the error"
}

Point bank with expiry

A point bank is a named collection of points.

Concepts:

Expiry period Every point bank has an expiry period of the points inserted to it. It can be days, weeks, months or years. The expiry of points is calculated based on the time the points where inserted.

For this to work we track what points are used when, and will always select the oldest points in a burn operation.
Grace period A grace period is the time beyond the expiry period that the points are active. Ex. inserting points in a point bank today with 1 year expiry + grace period = MONTH will make the points expire in 1 year + running month.

Grace period can be set to; instant (no grace period), month, quarter

Get points

Get the available points from the default point bank. The points available equals to: sum in point bank - authorized points.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Response samples

Content type
application/json
{
  • "pointBank": "pointBankName",
  • "availablePoints": 50
}

Insert points

Insert points to the named point bank. If no point bank name is given the points will be inserted on the default point bank.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Request Body schema: application/json
pointBank
string

name of the point bank being accessed

points
integer

how many points are available

Responses

Request samples

Content type
application/json
{
  • "pointBank": "pointBankName",
  • "points": 50
}

Response samples

Content type
application/json
{
  • "pointBank": "pointBankName",
  • "availablePoints": 50
}

Authorize points

Authorizes (locks) points on a named point bank. If no point bank name is given the points will be inserted on the default point bank.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Request Body schema: application/json
pointBank
string

name of the point bank being accessed

points
integer

how many points are available

Responses

Request samples

Content type
application/json
{
  • "pointBank": "pointBankName",
  • "points": 50
}

Response samples

Content type
application/json
{
  • "eventId": "nxb3wMhjIjeElyNMQGzW431RCqLVL2vt"
}

Capture authorization.

Burns authorized points and subtract them from the bank. The oldest points will be burned first.

path Parameters
eventId
required
string
Example: nxb3wMhjIjeElyNMQGzW431RCqLVL2vt

Transaction specific id used to confirm an operation

Responses

Response samples

Content type
application/json
{
  • "pointBank": "pointBankName",
  • "availablePoints": 50
}

Cancel authorization.

Cancel authorized points and unlocks them to be used.

path Parameters
eventId
required
string
Example: nxb3wMhjIjeElyNMQGzW431RCqLVL2vt

Transaction specific id used to confirm an operation

Responses

Response samples

Content type
application/json
{
  • "pointBank": "pointBankName",
  • "availablePoints": 50
}

Get point bank details

List user point bank details including expiry information

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

query Parameters
includeExpired
boolean

Flag indicating whether expired points should be included in returned results

includeFullyBurned
boolean

Flag indicating whether fully burned points should be included in returned results

page
integer <int32>

Pagenumber to return. The page index is zero-based. Defaults to 0 (zero)

size
integer <int32>

Elements returned per page. Defaults to 100.

sort
string^(created|earnedPoints|spentPoints),(asc|desc...

Sort of the returned content. Defaults to 'sort=expiringPointBankId,desc'.

Sort can have any of the values: created, earnedPoints or spentPoints.

In addition to defining the field to sort in, the sort direction is also defined in this field by either asc or desc

Example: '...&sort=created,desc&...'

Responses

Response samples

Content type
application/json
{
  • "content": [
    ],
  • "totalElements": 1000,
  • "totalPages": 10,
  • "first": true,
  • "last": false,
  • "numberOfElements": 100,
  • "page": 0
}

Payment

Enroll card at a Payment Service Provider (PSP) for online purchases. After card enrollment a ticketId is returned from the PSP to be used for recurring payments at the PSP. 3D Secure verification must be done directly with the PSP upon the first transaction.

Enroll card

Enroll card at a PSP and get a ticketId to use for recurring payments at the PSP. Upon succesfull enrollment the ticketId will also be saved as metadata on the card.

path Parameters
cardId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

ExternalCardId of the card.

Responses

Response samples

Content type
application/json
{
  • "ticketId": "8RzQao5HANxljjo4iswIjKcsepU="
}

Notifications

When certain events happen within the loyalty platform, a notification can be dispatched.

In order to setup notications, Storebox must receive an URL per notification type with static authentication headers. Storebox will not append information of the event type to the URL.

Example of valid URL sets:

  • Separation by path
    • https://yourServer.com/yourUri/createCoupon
    • https://yourServer.com/yourUri/assignCoupon
    • https://yourServer.com/yourUri/...
  • Separation by parameter
    • https://yourServer.com/yourUri/storeboxLoyaltyEvents?eventType=createCoupon
    • https://yourServer.com/yourUri/storeboxLoyaltyEvents?eventType=assignCoupon
    • https://yourServer.com/yourUri/storeboxLoyaltyEvents?eventType=...

Storebox monitors the response code returned, but will not handle the response body.

Note: None of the endpoints, in the "Notifications" section, exists in the loyalty API, but are endpoints the integrator must implement and expose. The suggested URL's, are only examples, and you, as an integrator, are free to define your own.

Create coupon notification

Notification that will be send when a coupon is created.

Note: You do not have to use "/coupon-create-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
memberId
required
string

member id of the user that has been assigned a coupon

provider
required
string

The card provider (container/owner) in Storebox systems that the user belongs to

required
object (user-coupons)

Responses

Request samples

Content type
application/json
{
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "provider": "storebox",
  • "coupon": {
    }
}

Delete coupon notification

Notification that will be send when a coupon is deleted.

Note: You do not have to use "/coupon-delete-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
memberId
required
string

member id of the user that has been assigned a coupon

provider
required
string

The card provider (container/owner) in Storebox systems that the user belongs to

campaignCode
required
string

Campaigncode can be used to identify the campaign

couponId
required
string

The unique coupon identification

Responses

Request samples

Content type
application/json
{
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "provider": "storebox",
  • "campaignCode": "campaign-502",
  • "couponId": "WYgJ41dzZMTvFywjUPFFbf3ylzMVm83G"
}

Expired coupon notification

Notification that will be send when a coupon is expired.

Note: You do not have to use "/coupon-expire-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
memberId
required
string

member id of the user that has been assigned a coupon

provider
required
string

The card provider (container/owner) in Storebox systems that the user belongs to

campaignCode
required
string

Campaigncode can be used to identify the campaign

couponId
required
string

The unique coupon identification

Responses

Request samples

Content type
application/json
{
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "provider": "storebox",
  • "campaignCode": "campaign-502",
  • "couponId": "WYgJ41dzZMTvFywjUPFFbf3ylzMVm83G"
}

Capture/redeem notification

Notification that will be send when a coupon is captured/redeemed.

Note: You do not have to use "/coupon-capture-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
memberId
required
string

member id of the user that has been assigned a coupon

provider
required
string

The card provider (container/owner) in Storebox systems that the user belongs to

campaignCode
required
string

Campaigncode can be used to identify the campaign

couponId
required
string

The unique coupon identification

itemNumber
string

Product number of the product that triggered the redeem. Special conditions are required to receive this information

itemNumberType
string

Type of the item number

storeId
string

Id of the store that redeemed the coupon. Special conditions are required to receive this information

storeIdType
string

Type of store id

Responses

Request samples

Content type
application/json
{
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "provider": "storebox",
  • "campaignCode": "campaign-502",
  • "couponId": "WYgJ41dzZMTvFywjUPFFbf3ylzMVm83G",
  • "itemNumber": "09843098234",
  • "itemNumberType": "EAN",
  • "storeId": "00032321",
  • "storeIdType": "GLN"
}

Progress added notification

Notification that will be send when a user received points on a Coupon Template.

Note: You do not have to use "/coupontemplate-progress-added-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
memberId
required
string

member id of the user that has been assigned a coupon

provider
required
string

The card provider (container/owner) in Storebox systems that the user belongs to

campaignCode
required
string

Campaigncode can be used to identify the campaign

Responses

Request samples

Content type
application/json
{
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "provider": "storebox",
  • "campaignCode": "campaign-502"
}

User created notification

Notification that will be send when a user is created.

Note: You do not have to use "/user-create-notification" in the path, when implementing the receiving endpoint, but you must have memberId at the end of the path.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

User deleted notification

Notification that will be send when a user is deleted.

Note: You do not have to use "/user-delete-notification" in the path, when implementing the receiving endpoint, but you must have memberId at the end of the path.

path Parameters
memberId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

Point bank earn notification

Notification that will be send when an enduser earns points.

Note: You do not have to use "/point-bank-exp-earn-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
provider
string

The card provider (container/owner) in Storebox systems.

memberId
string

member id of the user

pointBank
string

name of the point bank being accessed

availablePoints
integer

how many points are available after the operation

pointChange
integer

how many points added (in earn notifications) or subtracted (in burn/expire notifications)

operation
string

To support a single integration endpoint, the type of operation is added to the requestbody. Supported values are: 'EARN_POINTS', 'BURN_POINTS' and 'EXPIRE_POINTS'. It is still possible to have notifications sent to separate endpoints, and ignore this value

Responses

Request samples

Content type
application/json
{
  • "provider": "storebox",
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "pointBank": "pointBankName",
  • "availablePoints": 50,
  • "pointChange": 25,
  • "operation": "see supported values"
}

Point bank burn notification

Notification that will be send when an enduser captures authorized (burns) points

Note: You do not have to use "/point-bank-exp-burn-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
provider
string

The card provider (container/owner) in Storebox systems.

memberId
string

member id of the user

pointBank
string

name of the point bank being accessed

availablePoints
integer

how many points are available after the operation

pointChange
integer

how many points added (in earn notifications) or subtracted (in burn/expire notifications)

operation
string

To support a single integration endpoint, the type of operation is added to the requestbody. Supported values are: 'EARN_POINTS', 'BURN_POINTS' and 'EXPIRE_POINTS'. It is still possible to have notifications sent to separate endpoints, and ignore this value

Responses

Request samples

Content type
application/json
{
  • "provider": "storebox",
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "pointBank": "pointBankName",
  • "availablePoints": 50,
  • "pointChange": 25,
  • "operation": "see supported values"
}

Point bank expired notification

Notification that will be sent when points expires.

Note: You do not have to use "/point-bank-exp-expired-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
provider
string

The card provider (container/owner) in Storebox systems.

memberId
string

member id of the user

pointBank
string

name of the point bank being accessed

availablePoints
integer

how many points are available after the operation

pointChange
integer

how many points added (in earn notifications) or subtracted (in burn/expire notifications)

operation
string

To support a single integration endpoint, the type of operation is added to the requestbody. Supported values are: 'EARN_POINTS', 'BURN_POINTS' and 'EXPIRE_POINTS'. It is still possible to have notifications sent to separate endpoints, and ignore this value

Responses

Request samples

Content type
application/json
{
  • "provider": "storebox",
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "pointBank": "pointBankName",
  • "availablePoints": 50,
  • "pointChange": 25,
  • "operation": "see supported values"
}

Card expiry notification

When a registered card is close to expiry, a notification can be triggered. The timing of the notification is configurable by Storebox.

Note: You do not have to use "/card-expiry-notification" in the path, when implementing the receiving endpoint.

Request Body schema: application/json
provider
string

The card provider (container/owner) in Storebox systems.

memberId
string

member id of the user the card is registered to

cardId
string

external card id of the expiring card

maskedCardNumber
string

Masked card number of the expiring card

cardTypeId
integer

card type of the expiring card

expiryMonth
integer

expiry month of the expiring card

expiryYear
integer

expiry year of the expiring card

Responses

Request samples

Content type
application/json
{
  • "provider": "storebox",
  • "memberId": "ptsnaxm5q5bazf9y1b1ek42a3isxosuj",
  • "cardId": "e75ca15c8ae1401c943ff15df437f1d8",
  • "maskedCardNumber": "501932XXXXXX0325",
  • "cardTypeId": "1 (Dankort/VISA Dankort)",
  • "expiryMonth": 8,
  • "expiryYear": 24
}