Card API (v1)

Download OpenAPI specification:Download

This document contains a technical description for adding cards and deleting cards to and from Storebox PCI DSS Certified environment.

This only includes card operations that are out of PCI-scope. For operations like programatically adding cardholder data use the Vault API.

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

The 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.

Authentication

basicAuth

HTTP Basic Authentication is supported using the delivered username and the API key. For each API call HTTP Authorization header should be set

Security Scheme Type HTTP
HTTP Authorization Scheme basic

Cards

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:

open
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, for example: 4571000000000000 -> 457100XXXXXX0000
Card types When cards are entered in Storebox, we try to identify the type of the card based on the IIN.

The identified type resolves to a cardTypeId:
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 or webview on any page and is highly customizable.

Show card frame

When submitting a card to Storebox’ PCI compliant environment, Storebox will make as many validations checks as possible before accepting the request.

Checks include:

  • Valid Cardnumber
  • Valid CardType (setup dependent)
  • Account verification (setup dependent)
  • Card expiry

It is important to note that requests also will return http code 200 on validation errors.

For cardframe submits the cardframe will handle card validation responses from the backend and only send the enduser to the accepturl if a valid card has been entered.

When the backend accepts a submit request, the processing of the card will continue asynchronously. When processing has completed and only then, the PCI environment will send a notification to the provided callbackurl.

The accept URL is the URL where the enduser is redirected after they click the add payment card button. The URL is mainly an indicator to the caller that the operation is done, and the input window can be closed. The following is an example of completion detection in the iframe integration.

<iframe src="..." onload="done()"></iframe>

<script>
function done() {
  // ... remove iframe etc
}
</script>

The callback URL is where the registered data is sent. This will usually be the server that hosts the integrating website/API.

Frame structure

The card frame is styled by the caller via the CSS specified by cssurl in the initial call. The following structure is used.

<form action="" method="post">
  <div class="field field-input">
    <div class="field-label">Kortnummer</div>
    <input id="CardNumber" name="CardNumber">
  </div>
  <div class="field field-input">
    <div class="field-label">Udløbsmåned</div>
    <input id="ExpMonth" name="ExpMonth">
  </div>
  <div class="field field-input">
     <div class="field-label">Udløbsår</div>
    <input id="ExpYear"name="ExpYear">
  </div>
  <div class="field field-btn">
    <input type="submit" class="button" value="Gem nyt kort ">
  </div>
</form>

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

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

Localization

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

{
  "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",
    "accountVerification": "Kort gyldighed kunne ikke verificeres."
  },
  "btn": {
    "save":"Gem kort"
  },
  "accountno": {
    "errorInvalid":"Ugyldigt kontonummer",
    "errorMinLength":"Skal minimum være 11 tegn",
    "label":"Kontonummer",
    "placeholder":"Indtast kontonummer",
    "duplicate":"Kontonumret er allerede registreret"
  },
  "card": {
    "errorInvalid":"Ugyldigt kortnummer",
    "unsupportedType":"Denne korttype 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 http://.../en.json?v=1. Refrain from using a constantly changing parameter, like a timestamp.

Add card callback

When the card has been processed, a notification will be sent to the specified callbackurl.

The request is a GET request with the following parameters

NameDescription
userIdThe external user id that was used when requesting the card frame.
cardtypeAn id representing the card type. For card frame type "accountno" this is always "0".
cardnoMasked card number. For card frame type "accountno" no value is provided.
expmonthThe expiry month of the card. This may be zero prefixed.
expyearA two digit representation of the expiry year. For example 2019 will be 19
accountnoFull account number. Returned on card frame type "accountno" only.
externalCardIdThe card id. Used when deleting the card.
providerThe identity of the receiver. The same as the original call.
hashHMAC-SHA256 hash of the parameters. hmac-sha256({signatureKey}, expmonth + expyear + cardno + userId + externalCardId + provider + cardtype)

At the time of writing, the callback is the only way to obtain these values. If the values are lost or ignored, they cannot be re-sent. Especially externalCardId should be stored as this makes it possible to remove the card from the PCI environment at a later point.

Account number frame recommendation

When handling cards that support payment via account number, it is necessary to register both account number as well as the card number. Just like how all the card numbers must be registered for any combined card that contains multiple payment methods, e.g. MasterCard with both debit and credit.

  1. Show card frame type "card"
  2. Show an interrim landing page that asks end-user whether account number payment method exists on card
  3. If account number payment method exists, show card frame type "account"

Alternatively you may consider letting the user choose what they will be adding: a card number or an account number.

query Parameters
userId
required
string

External id of the user who owns the card

provider
required
string

The identity of the caller. This is issued by Storebox

accepturl
required
string

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

cssurl
string

Absolute URL for the CSS file for input styling

languageurl
string

Public URL for the translation JSON file

callbackurl
string

The URL to callback when the card has finished processing.

type
string
Enum: "card" "accountno"

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

Possible values

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

HMAC-SHA256 hash of the parameters. hmac-sha256({signatureKey}, userId + provider + accepturl + callbackurl + cssurl + languageurl). The signatureKey is provided by Storebox along with the provider value

Responses

301

The card frame is located in a PCI DSS certified environment and the API request is redirected to it

get /api/v1/cards/cardframe

Production

https://cardapi.prod.storebox.com/api/v1/cards/cardframe

Test

https://cardapi.test.storebox.com/api/v1/cards/cardframe

Add card

NOTE It is only allowed to add non-EMV cards, for example BankAxept or customer card using this interface. For EMV card, please contact Storebox support.

The API accepts an encrypted package containing the full cardnumber and expiry month/year.

The encrypted payload is a JSON string in the form:

{
  "expiry": {
    "year": 20,
    "month": 1
  },
  "cardNumber": "...",
  "par": "..."
}

cardNumber or par may be omitted. If PAR is omitted, Storebox will try to look it up. If cardNumber is omitted, the receipts will only work with PAR-based payment methods.

The string is encrypted and Base64 encoded. The supported encryption algorithm is RSA with OAEP padding.

Test example of generating the card payload from the command line.

cat <carddata.txt> | openssl pkeyutl  -encrypt -pubin -inkey <transport.pem> -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 -pkeyopt rsa_mgf1_md:sha256 | base64

The resulting card payload should be added in the encryptedCard request property.

If BankAxept cards are added, they have to be in their card number for i.e. 957852<account-number><luhn-digit>.

Request Body schema: application/json
provider
required
string

The provider name

userId
required
string

The user id

encryptionProvider
required
string

The encryption provider

encryptedCard
required
string

The card encrypted with the RSA transport key using OAEP padding

callbackUrl
string

The URL to receive the callback when the card is created

Responses

200

Card added

post /api/v1/cards

Production

https://cardapi.prod.storebox.com/api/v1/cards

Test

https://cardapi.test.storebox.com/api/v1/cards

Request samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "provider": "storebox",
  • "userId": "1234",
  • "encryptionProvider": "storebox",
  • "encryptedCard": "string",
  • "callbackUrl": "string"
}

Get all cards

Return all cards registered to the caller. The result is pageable and sortable.

Authorizations:
query Parameters
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 ^(cardNumber|cardTypeId|userId|created),(asc|desc)$

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

Sort can have any of the values: cardNumber, cardTypeId, userId or created.

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=cardNumber,asc&...'

Responses

200

Card content returned

get /api/v1/cards

Production

https://cardapi.prod.storebox.com/api/v1/cards

Test

https://cardapi.test.storebox.com/api/v1/cards

Response samples

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

Get user cards

Get all cards registered to a specific userId

Authorizations:
path Parameters
userId
required
string
Example: e75ca15c8ae1401c943ff15df437f1d8

Member id that should be looked up

Responses

200

UserId found and cards returned

404

userId not found

get /api/v1/cards/{userId}

Production

https://cardapi.prod.storebox.com/api/v1/cards/{userId}

Test

https://cardapi.test.storebox.com/api/v1/cards/{userId}

Response samples

Content type
application/json
Copy
Expand all Collapse all
[
  • {
    }
]

Delete a card

Deletes a card from the PCI DSS environment. This cannot be undone.

Authorizations:
path Parameters
externalCardId
required
string

Card id that was delivered in the callback on card creation

Responses

200

If the card was successfully deleted

404

The card was not found

delete /api/v1/cards/{externalCardId}

Production

https://cardapi.prod.storebox.com/api/v1/cards/{externalCardId}

Test

https://cardapi.test.storebox.com/api/v1/cards/{externalCardId}

BankAxept

Operations related to BankAxept. This is only relevant in Norway.

Show account number frame

Insert account number only. Note that even though this inserts an account number it is still conceptually a card, i.e. it is deleted as a card using the externalCardId. The callback is the same as the card frame.

query Parameters
userId
required
string

External id of the user who owns the card

provider
required
string

The identity of the caller. This is issued by Storebox

accepturl
required
string

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

cssurl
string

Absolute URL for the CSS file for input styling

languageurl
string

Public URL for the translation JSON file

callbackurl
string

The URL to callback when the card has finished processing

hash
required
string

HMAC-SHA256 hash of the parameters. hmac- sha256({signatureKey}, userId + provider + accepturl + callbackurl + cssurl + languageurl). The signatureKey is provided by Storebox along with the provider value

Responses

200

The frame HTML content

get /api/v1/accountnumbers/frame

Production

https://cardapi.prod.storebox.com/api/v1/accountnumbers/frame

Test

https://cardapi.test.storebox.com/api/v1/accountnumbers/frame

Add account no

Insert account number only by API. This endpoint verifies the format of the account defined by the accountNoType.

Request Body schema: application/json
accountNo
required
string

The accountNo that should be added.

accountNoType
required
string

The type of the submitted account no. This value is provided by Storebox.

userId
required
string

An unique identifier of the owner of the account no.

provider
required
string

The owner program of the account no. This value is provided by Storebox.

callbackUrl
string

Optional - Event url to call when the asynchronous add account no. operation has completed.

Responses

200

Account no processed - read response status for success evaluation.

400

Invalid request - the specific error is stated in the response body.

404

Provider not found in the system.

post /api/v1/accountnumbers

Production

https://cardapi.prod.storebox.com/api/v1/accountnumbers

Test

https://cardapi.test.storebox.com/api/v1/accountnumbers

Request samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "accountNo": "12345678901",
  • "accountNoType": "bankaxept",
  • "userId": "3sk2zjf65u97jrw4yl17",
  • "provider": "storebox",
  • "callbackUrl": "https://storebox.com"
}

Response samples

Content type
application/json
Copy
Expand all Collapse all
{
  • "status": 0,
  • "externalCardId": "hdwu2gbqesc49admkxnv"
}