Show / Hide Table of Contents

Token service

Token service is a service which takes card data and returns a token
This token can be used in various API calls instead of presenting card data

sequenceDiagram
    Browser->>+Website: Load page / start request to initiate payment
    Website->>+Api: GetMerchantSessionKey
    Api->>+Website: Response with MerchantSessionKey
    Website->>+Browser: Render payment page (local)
    Browser->>+Api: Tokenize Card
    Api->>+Browser: Card Token
    Browser->>Website: Card Token

How long a card is kept

A stored card is kept while it is used. A card that has not been used for two years is deleted, and the token stops working (TOK07). Every approved payment made with the token, and tokenising the same card again, counts as a use and starts the two years again.

The agreements of a card (see Hosted Payment) are deleted together with the card: PayLolly does not keep an agreement, or the consent evidence in it, for a card it no longer holds. If you need the evidence for longer, keep your own record of it (the agreement block of the payment, and your own consent record referenced by evidenceRef).

Use Cases

Call token service to tokenise existing card data

Call TokenizeCard with the details Store returned Token

request:

curl -X 'POST' \
  'https://api.dev.paylolly.app/api/rest/v1.0/Token/TokenizeCard' \
  -H 'accept: application/json' \
  -H 'MerchantKey: 35236fcf-12f4-4c94-b4ba-5d236457b68a' \
  -H 'Content-Type: application/json' \
  -d '{
  "cardNo": "4000000000000002",
  "expiryYear": "30",
  "expiryMonth": "12",
  "expiryYYMM": "3012",
  "email": "test@email.com",
  "name": "NAME SURNAME",
  "traceId": "1234567890A0B0C0D0E0F"
}'

response:

"9C2C6412351A5BED6529ED5698DE395E"
Note

A token created with TokenizeCard (for example with a traceId you imported) is just a card: it has no agreement and no recorded consent. Record the consent with Agreement/RecordConsent (below) to give it one, and to make the card appear in the hosted lookup of returning customers.

Detokenise card

For security reasons, only masked card details are returned

request:

curl -X 'GET' \
  'https://api.dev.paylolly.app/api/rest/v1.0/Token/DeTokenizeCard?token=9C2C6412351A5BED6529ED5698DE395E' \
  -H 'accept: application/json' \
  -H 'MerchantKey: 35236fcf-12f4-4c94-b4ba-5d236457b68a'

response:

{
  "token": "9C2C6412351A5BED6529ED5698DE395E",
  "maskedPAN": "400000*0002",
  "expiryYear": "30",
  "expiryMonth": "12",
  "expiryYYMM": "3012",
  "email": "test@email.com",
  "name": "NAME SURNAME",
  "traceId": "1234567890A0B0C0D0E0F"
}

Call token service directly from javascript

Before serving website, from your backend call GetMerchantSessionKey
Ticks should be a good estiamte for maximum session time until tokenisation is completed - typically suggest "00:20:00" ie 20 minutes
Return is a MerchantSessionKey

This MerchantSessionKey is to be embedded / sent to the javscript domain so that a CORS request is possible to TokenizeCard directly from the browser
Insert header MerchantSessionKey in the request header

Note

CORS is enabled for TokenizeCard only

Of course card token is now returned to javascript domain, and should be uploaded to your backend for further processing

request:

curl -X 'GET' \
  'https://api.dev.paylolly.app/api/rest/v1.0/Token/GetMerchantSessionKey?timeSpan=00%3A20%3A00' \
  -H 'accept: application/json' \
  -H 'MerchantKey: 35236fcf-12f4-4c94-b4ba-5d236457b68a'

response:

"CfDJ8LX3uRJAScJAif7HfPfxL1DJh6t97s7VHMqDR7AG4RG64Y4_tiZkz6_ttvqA-RWlFZp9TZiw4AjlN7l3UZ-sSUvAI8HnNdfoVtvGdgWvJN3aOrhAr-zoX_-j-GcI8LChjIrdUwjF9trG_8oiAjhqdjfhNFZbdL0Z5R4zCgw45UMe"

Request from Browser:

curl -X 'POST' \
  'https://api.dev.paylolly.app/api/rest/v1.0/TokenJS/TokenizeCard' \
  -H 'accept: application/json' \
  -H 'MerchantSessionKey: CfDJ8LX3uRJAScJAif7HfPfxL1DJh6t97s7VHMqDR7AG4RG64Y4_tiZkz6_ttvqA-RWlFZp9TZiw4AjlN7l3UZ-sSUvAI8HnNdfoVtvGdgWvJN3aOrhAr-zoX_-j-GcI8LChjIrdUwjF9trG_8oiAjhqdjfhNFZbdL0Z5R4zCgw45UMe' \
  -H 'Content-Type: application/json' \
  -d '{
  "cardNo": "4000000000000002",
  "expiryYear": "30",
  "expiryMonth": "12",
  "expiryYYMM": "3012",
  "email": "test@email.com",
  "name": "NAME SURNAME"
}'

response:

"9C2C6412351A5BED6529ED5698DE395E"

Perform AsyncPayment with Token

Follow "Call token service directly from javascript above"
Follow "Async Payments" but instead of entering card details, you can pass token

Note

Please note that CORS is only enabled for TokenizeCard, so all other requests must be made from the backend **

request:

curl -X 'POST' \
  'https://api.dev.paylolly.app/api/rest/v1.0/Payment/CreateAsyncPayment' \
  -H 'accept: application/json' \
  -H 'MerchantKey: 35236fcf-12f4-4c94-b4ba-5d236457b68a' \
  -H 'Content-Type: application/json' \
  -d '{
  "merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
  "currency": "EUR",
  "amount": 1,
  "merchantRef": "9e31818e-407b-48d8-8bbf-eb19fa565723",
  "cardHolder": {
    "email": "test@email.com",
    "name": "NAME SURNAME"
  },
"cardData":{
"cvc":"123"
},
  "tokenData": {
    "token": "9C2C6412351A5BED6529ED5698DE395E",
    "traceId": "0102030405060708090A0B0C0D0E0F"
  },
  "authorisationType": "Auth",
  "recurrence": "OneTime",
  "initiation": "CIT",
  "returnUrl": "https://mywebsite.com/payment/return/abc123",
  "validUntil": "2026-12-31T13:55:10.603Z"
}'

response:

{
  "redirectUrl": "https://api.dev.paylolly.app/payment/async/21f8d828-c855-4ef3-ab47-867fee51bdcb/Index",
  "paymentId": "21f8d828-c855-4ef3-ab47-867fee51bdcb",
  "merchantId": "dbdab964-82ee-4b09-a26b-68403c31afa7",
  "accountId": "81de44cb-4b70-4207-9f5e-54355491a5cc",
  "currency": "EUR",
  "amount": 1,
  "cardData": {
    "maskedPAN": "400000*0002",
    "expiryYYMM": "3012",
    "token": "9C2C6412351A5BED6529ED5698DE395E"
  },
  "result": {
    "status": "Async",
    "processorId": "dd1ccb51-29e0-4967-a8de-8cc0a39c1d85",
    "message": "redirect to async"
  },
  "merchantRef": "9e31818e-407b-48d8-8bbf-eb19fa565723"
}

The payment is a customer present payment, so initiation is CIT (MIT and MOTO are rejected with VAL13 on async payments) and cardData.cvc is required. A traceId is only needed for merchant initiated payments (see Payment Actions). To record what the cardholder agreed to, add the optional agreement object, or send an agreementId of an existing agreement: see Agreements.

Perform 3Dsecure with Token

Follow "Call token service directly from javascript above"
Follow "3DS API" but instead of entering card details, you can pass token

  • Use ThreeDSVersionTokenized call instead of ThreeDSVersion
  • Use ThreeDSAuthenticateTokenized call instead of ThreeDSAuthenticate

The challenge indicator 04 (challenge mandated) is forced only for the registering payment (CIT with recurrence OneClick); for other payments the value configured in 3DS Config is used.

Record consent for an existing token

Attach an agreement and your consent evidence to a token that already exists, without a payment. Full description and all fields: Agreements.

curl -X 'POST' \
  'https://api.dev.paylolly.app/api/rest/v1.0/Agreement/RecordConsent' \
  -H 'accept: application/json' \
  -H 'MerchantKey: 35236fcf-12f4-4c94-b4ba-5d236457b68a' \
  -H 'Content-Type: application/json' \
  -d '{
  "token": "08524FF1F8BE79B7EA0CE19204E81BF2",
  "cardHolder": { "reference": "CUST-1" },
  "agreement": {
    "agreementRef": "TOPUP-1",
    "description": "Wallet top-ups",
    "consent": { "textVersion": "v3", "timestamp": "2026-09-01T09:00:00Z" }
  }
}'

response:

{
  "agreementId": "0198ab5c-6f37-7a02-9d7e-3a5e2c1f4b10",
  "status": "Created",
  "agreementRef": "TOPUP-1",
  "consentStatus": "Recorded"
}

The same token, customer and agreementRef again returns Updated with the same agreementId. The token must belong to your merchant (TOK07 otherwise).

Cancel an agreement

Flag an agreement as cancelled. It is no longer offered to the cardholder on the hosted page; payments that quote it are counted and still processed.

curl -X 'POST' \
  'https://api.dev.paylolly.app/api/rest/v1.0/Agreement/Cancel?agreementId=0198ab5c-6f37-7a02-9d7e-3a5e2c1f4b10' \
  -H 'MerchantKey: 35236fcf-12f4-4c94-b4ba-5d236457b68a'

response:

{ "agreementId": "0198ab5c-6f37-7a02-9d7e-3a5e2c1f4b10", "status": "Cancelled" }

An unknown id, or one that belongs to another merchant, gives AGR08. See Agreements.

In this article
Back to top Generated by DocFX