Merchant Tokenization API
The LCM Merchant Tokenization API enables Payment Service Providers (PSPs) and Token Requestor Aggregators (TRAs) to securely tokenize merchants' payment cards, manage tokens, and generate transaction credentials for eCommerce payments across Dankort, Visa, Mastercard, and future payment schemes.
URLs
Authorization server Base URL - Production
Authorization server Base URL - Sandbox
https://api-gateway-pp.nets.eu/
Authentication
Before you can use the Merchant Tokenization APIs, your application must complete the on-boarding process. You will receive two sets of credentials: - Sandbox credentials (for test transactions) - Production credentials (for live transactions) Each set consists of a Client ID and a Client Secret. The Client Secret is confidential and must not be shared. To invoke this API you must obtain an OAuth 2.0 access token and send it in the HTTP Authorization header as a Bearer token. Important: The OAuth2 Token/Revoke endpoints are exposed by the Authorization Server (separate host) and are documented here for convenience. They are not part of the Resource Server paths in this OpenAPI document.
OAuth 2.0
OAuth 2.0 is the industry-standard protocol for authorization. See: RFC 6749. This API supports OAuth 2.0 with the confidential client type. A confidential client can keep its credentials secret when interacting with the Authorization Server. OAuth 2.0 defines four roles:
- Resource owner: Entity capable of granting access to a protected resource. 2. Resource server: Server hosting protected resources, accepting requests using access tokens. 3. Client: An application requesting protected resources on behalf of the resource owner. 4. Authorization server: The server issuing access tokens to the client after successful authentication/authorization. At a high level, the flow is:
- Get an access token from the Authorization Server. 2. Use the access token to call this API (the Resource Server). OAuth 2.0 uses an "authorization grant" to represent the authorization used to obtain an access token. This API supports the Client Credentials grant type.
Authorization Server
Token Endpoint
POST /token
With the Client Credentials grant type, the client requests an access token using only its own credentials. The access token returned for this API is of type Bearer.
Clients should request the minimal necessary scope and lifetime. The Authorization Server may issue an access token with fewer rights than requested.
Generate an access token (Client Credentials grant):
- Obtain a valid
client_idandclient_secret. 2. Combine them asclient_id:client_secretand Base64-encode the result. 3. Call the Token Endpoint. Example:
-H "Authorization: Basic <Base64 encoded client_id:client_secret>" \
-H "Content-Type: application/x-www-form-urlencoded" \
https://api-gateway2.nets.eu/token
Example response (access token may be opaque, not necessarily a JWT):
"token_type": "Bearer",
"expires_in": 2061,
"access_token": "ca19a540f544777860e44e75f605d927"
} ```
Note: Per RFC 6749, the Client Credentials grant type does **not** issue refresh tokens.
### Revoke Endpoint
`POST` /revoke
In case of credential theft or a security incident, revoke an access token using the Revoke Endpoint.
**Parameters** - `token` (required): The token to revoke. - Basic Authorization header (required): `Authorization: Basic <Base64 encoded client_id:client_secret>` - `token_type_hint` (optional): Use `access_token` for Client Credentials. If omitted, the server searches multiple token spaces and revocation may take longer.
Example:
```bash curl -X POST \
https://api-gateway2.nets.eu/revoke \
-H "Authorization: Basic <Base64 encoded client_id:client_secret>" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=<token_to_be_revoked>&token_type_hint=access_token"
Responses
-
Valid token - HTTP Status 200 - OK You receive an empty response with the HTTP status as 200. The following HTTP headers are returned:
Revokedaccesstoken: a0d210c7a3de7d548e03f1986e9a5c39 Authorizeduser: admin@carbon.super Revokedrefreshtoken: 5e87a8235cd4d066e15c4c989f5ecf94 Content-Type: text/html Pragma: no-cache Cache-Control: no-store Date: Tue, 23 Aug 2018 19:28:52 GMT Transfer-Encoding: chunked -
Invalid token - HTTP Status 200 - OK You still receive an empty response with the HTTP status as 200 but only the following HTTP headers are returned:
Content-Type: text/html Pragma: no-cache Cache-Control: no-store Date: Tue, 23 Aug 2018 19:31:45 GMT Transfer-Encoding: chunkedBecause the authorization server cannot find the token in any key space, you will not see Revokedaccesstoken or Revokedrefreshtoken
API Specification
Headers and payload
Request headers are case-sensitive. Request data must be sent as JSON message. The Content-Type header value must be application/json. Responses are sent as JSON messages. The Accept header value must be application/json.
Reason codes and virtual account Lifecycle actions
| Virtual Account Lifecycle Action | Reason code | Service API | Description |
|---|---|---|---|
| 1023 | Change the state of a virtual account | Delete virtual account | |
| 1024 | Change the state of a virtual account | Delete virtual account due to confirmed fraud | |
| DELETE | 1025 | Change the state of a virtual account | Delete virtual account because the device is confirmed lost. |
| 1026 | Change the state of a virtual account | Delete virtual account because the device is confirmed stolen. | |
| 1027 | Change the state of a virtual account | Delete virtual account because the card expired and was not renewed |
Error codes
| Error code | Description |
|---|---|
| MTS-1611 | Agreement Related error (Agreements between PSP, Acquirer, Provider, and Merchants) |
| MTS-1612 | Bin Range Invalid |
| MTS-1614 | Invalid Input Format |
| MTS-1616 | Invalid Input Data |
| MTS-1617 | Cryptography Error |
| MTS-1618 | Server Error |
| MTS-1619 | Tokenization Client Error |
| MTS-1620 | Generic Error |
Scroll down for code samples, example requests and responses.
Select a language for code samples from the tabs or the mobile navigation menu.
Merchant Tokenization - Inbound
Tokenize cards and generate transaction credentials and manage the tokenized cards.
Create token
POST /virtual-accounts/tokenCreate a virtual account token for a payment card to enable secure, recurring transactions within the eCommerce Card-on-File (CoF) ecosystem.
The card data MUST be provided as a JWE (encrypted) payload to reduce PCI exposure. The service decrypts, validates, and tokenizes the card data, returning a virtual account token.
Decrypted card payload (inside JWE, for reference only): Once decrypted, accountInfo.encryptedData contains a JSON object with the plain card fields: { "account": "4571456789012345", "accountExpiry": "122028", "cvv": "123", "name": "cardHolderName" } where 'cvv' and 'name' are optional fields.
Parameters
X-Acquirer-IDstringrequired
Acquirer ID assigned during onboarding.
X-Provider-IDstringrequired
Provider ID assigned during onboarding.
X-PSP-IDstringrequired
Payment Service Provider ID assigned during onboarding.
X-Request-IDstring (uuid)required
End-to-end request correlation identifier generated by the caller. Use a UUID to simplify troubleshooting across distributed systems.
Request body
merchantInfoobjectrequired
merchantIdstringrequired
example: acquirerMerchId1Acquirer merchant identifier assigned during onboarding.
accountInfoobjectrequired
The payment card data encrypted as JWE Compact Serialization. After decryption, the plaintext JSON conforms to DecryptedAccountInfoDto. Crypto contract (example):
- protected header MUST include: alg=RSA-OAEP-256, enc=A256GCM, kid=
- kid identifies the recipient key used for decryption (support key rollover)
- AAD is the ASCII bytes of the Base64URL-encoded protected header (JWE rules)
Processing Flow:
- Receive encrypted JWE ciphertext
- Decrypt to extract card account data
- Validate all fields against constraints
- Forward to tokenization processing
- Store only necessary fields in the virtual account (never store CVV)
encryptedDatastringrequired
example: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiazEifQ.O4HcKx8Q9u0gCw2y8b2zJrJxgq8n3Q0m0yQ6g6lqgYwZP2VqJw.48V1_ALb6US04U3b.VbQw0KQ0YyBv1m8yVq2wq7yQp1f8rWw1vZ8sT2d8p9d3wQ.2xvTq9RjQd7e3m1nPzv2mQJWE Compact Serialization consisting of 5 dot-separated Base64URL segments: protectedHeader.encryptedKey.iv.ciphertext.tag
- Tokenize encrypted account data (JWE)
- Decrypted account data (only for reference)
{ "merchantInfo": { "merchantId": "acquirerMerchId" }, "accountInfo": { "encryptedData": "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiazEifQ.O4HcKx8Q9u0gCw2y8b2zJrJxgq8n3Q0m0yQ6g6lqgYwZP2VqJw.48V1_ALb6US04U3b.VbQw0KQ0YyBv1m8yVq2wq7yQp1f8rWw1vZ8sT2d8p9d3wQ.2xvTq9RjQd7e3m1nPzv2mQ" } }
Responses
201optional
Token created successfully. The `encryptedData` field contains a JWE. After decryption, the plaintext JSON contains: ``` { "token": "958098150010000273", "tokenExpiry": "122028" } ```virtualAccountIdstringrequiredexample: 12345678901234567890123456
virtualAccountStatestringrequired
Current status of the Virtual Account.
ACTIVE,SUSPENDED,DELETEDparstringoptional
example: PAR123456789012345678901234Payment Account Reference (PAR). Conditional (C) - Shall be present only when a PAR has been assigned by the token service provider.
encryptedDatastringrequired
example: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiazEifQ.O4HcKx8Q9u0gCw2y8b2zJrJxgq8n3Q0m0yQ6g6lqgYwZP2VqJw.48V1_ALb6US04U3b.VbQw0KQ0YyBv1m8yVq2wq7yQp1f8rWw1vZ8sT2d8p9d3wQ.2xvTq9RjQd7e3m1nPzv2mQJWE Compact Serialization consisting of 5 dot-separated Base64URL segments: protectedHeader.encryptedKey.iv.ciphertext.tag
400400 Bad Requestoptional
errorCodestringrequired
example: MTS-1616Error code assigned by the Merchant Token Service.
401Unauthorizedoptional
403Forbiddenoptional
404Not Foundoptional
500Internal Server Erroroptional
503Service Unavailableoptional
- Token Creation Response (as received)
- Decrypted payload (only for reference)
- Agreement Related Error
- Invalid BinRange
- Invalid Format Error
- Cryptography Error
- Invalid Input Data
- Server Error
- Tokenization Client Error
- Generic Error
{ "virtualAccountId": "17739982144633747098724372", "virtualAccountState": "ACTIVE", "par": "8844D3IWOQYUKASFHF23FF69UUYX", "encryptedData": "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiazEifQ.O4HcKx8Q9u0gCw2y8b2zJrJxgq8n3Q0m0yQ6g6lqgYwZP2VqJw.48V1_ALb6US04U3b.VbQw0KQ0YyBv1m8yVq2wq7yQp1f8rWw1vZ8sT2d8p9d3wQ.2xvTq9RjQd7e3m1nPzv2mQ" }
Create transaction
POST /virtual-accounts/{virtualAccountId}/transactionCreate payment credentials for a tokenized card in eCommerce Card-on-File transactions. Returns encrypted transaction data (JWE) containing the cryptogram and tokenized card details needed by the merchant/payment platform to process an eCommerce transaction. After decrypting the JWE in the response, the plaintext JSON conforms to the TransactionCredentials schema.
Parameters
virtualAccountIdstringrequired
Virtual account identifier.
X-Acquirer-IDstringrequired
Acquirer ID assigned during onboarding.
X-Request-IDstring (uuid)required
End-to-end request correlation identifier generated by the caller. Use a UUID to simplify troubleshooting across distributed systems.
X-Provider-IDstringrequired
Provider ID assigned during onboarding.
X-PSP-IDstringrequired
Payment Service Provider ID assigned during onboarding.
Request body
merchantInfoobjectrequired
merchantIdstringrequired
example: acquirerMerchId1Acquirer merchant identifier assigned during onboarding.
transactionInfoobjectrequired
transactionIdstringrequired
example: Rrn123456789Unique transaction identifier.
transactionDateTimestringrequired
example: 20260225140530UTC Transaction date in 'YYYYMMDDhhmmss' format.
amountstringrequired
example: 000000002100Transaction amount in minor units, right-justified with leading zeros. Example: 000000002100 represents 21.00 when the currency has 2 decimals.
currencyCodestringrequired
example: 978ISO 4217 numeric currency code (3 digits).
Generate transaction credentials
{ "merchantInfo": { "merchantId": "acquirerMerchantId1" }, "transactionInfo": { "transactionId": "Rrn123456789", "transactionDateTime": "20260225140530", "amount": "000000002100", "currencyCode": "978" } }
Responses
201optional
Transaction created successfully. The `encryptedData` field contains a JWE. After decryption, the plaintext JSON contains: ``` { "token": "9580981500100002", "tokenExpiry": "122026", "cryptogram": "45f8grzty7f4f5gs5s2c" } ```encryptedDatastringrequired
example: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiazEifQ.O4HcKx8Q9u0gCw2y8b2zJrJxgq8n3Q0m0yQ6g6lqgYwZP2VqJw.48V1_ALb6US04U3b.VbQw0KQ0YyBv1m8yVq2wq7yQp1f8rWw1vZ8sT2d8p9d3wQ.2xvTq9RjQd7e3m1nPzv2mQJWE Compact Serialization consisting of 5 dot-separated Base64URL segments: protectedHeader.encryptedKey.iv.ciphertext.tag
400400 Bad Requestoptional
errorCodestringrequired
example: MTS-1616Error code assigned by the Merchant Token Service.
401Unauthorizedoptional
403Forbiddenoptional
404Not Foundoptional
500Internal Server Erroroptional
503Service Unavailableoptional
- Encrypted response (as received)
- Decrypted plaintext (for reference only)
- Agreement Related Error
- Invalid BinRange
- Invalid Format Error
- Cryptography Error
- Invalid Input Data
- Server Error
- Tokenization Client Error
- Generic Error
{ "encryptedData": "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2lkIjoiazEifQ.Vw2aZ5f0QpQmF3YxjJ6uZ7bY2t0kq2V9r1hZk0vWcJY.9Qm5dQb8cJQpYx2R.5kq3n0b7u3b6mWwq7v8yN2Qzqk6wqK0f2wWwZQ.3xA2m2wzVtQj2wNqZ1xYqQ" }
Update token state
PUT /virtual-accounts/{virtualAccountId}/tokenStateUpdates the token state for the specified virtual account.
Parameters
virtualAccountIdstringrequired
Virtual account identifier.
X-Acquirer-IDstringrequired
Acquirer ID assigned during onboarding.
X-Request-IDstring (uuid)required
End-to-end request correlation identifier generated by the caller. Use a UUID to simplify troubleshooting across distributed systems.
X-Provider-IDstringrequired
Provider ID assigned during onboarding.
X-PSP-IDstringrequired
Payment Service Provider ID assigned during onboarding.
Request body
tokenStatestringrequired
example: DELETEThe lifecycle action to be performed on the virtual Account. Supported lifecycle action: DELETE
DELETEreasonCodestringrequired
example: 1023Specify the mentioned reason code applicable for performing this token lifecycle event.
Request body
{ "tokenState": "DELETE", "reasonCode": "1023" }
Responses
204No Contentoptional
400400 Bad Requestoptional
errorCodestringrequired
example: MTS-1616Error code assigned by the Merchant Token Service.
401Unauthorizedoptional
403Forbiddenoptional
404Not Foundoptional
500Internal Server Erroroptional
503Service Unavailableoptional
- Agreement Related Error
- Invalid Format Error
- Invalid Input Data
- Server Error
- Tokenization Client Error
- Generic Error
{ "errorCode": "MTS-1611" }
Merchant Tokenization - Outbound
Notify the TRA of card and token lifecycle events.
Notify Card or Token Update to Token Requester Aggregator
POST /v1/{acquirerMerchantId}/virtual-accounts/{virtualAccountId}/notify-updateNotify the Token Requester Aggregator (TRA) when a card or token lifecycle event occurs for a tokenized card.
Parameters
acquirerMerchantIdstringrequired
Acquirer merchant identifier assigned during Merchant onboarding.
virtualAccountIdstringrequired
Virtual account identifier.
X-Request-IDstring (uuid)required
End-to-end request correlation identifier generated by the caller. Use a UUID to simplify troubleshooting across distributed systems.
X-Provider-IDstringrequired
Provider ID assigned during onboarding.
Request body
updateTypestringrequired
example: TOKEN_STATE_CHANGEType of lifecycle update being notified.
TOKEN_STATE_CHANGE,CARD_UPDATEaccountInfoobjectoptional
accountMaskedstringrequired
example: 447065xxxxxx8729Masked primary account number (PAN).
accountExpirystringrequired
example: 022030Expiry date of the underlying card in MMYYYY format.
accountParstringoptional
example: PAR123456789012345678901234Payment Account Reference (PAR) associated with the card account.
tokenInfoobjectrequired
tokenMaskedstringrequired
example: 447065xxxxxx8729Masked Token value.
tokenExpirystringrequired
example: 022027Expiry date of the Token in MMYYYY format.
tokenStatusstringrequired
example: ACTIVECurrent status of the token.
ACTIVE,SUSPENDED,DELETEDtokenUpdateDatestring (date-time)required
example: 2026-02-25T14:05:30ZUTC transaction timestamp in RFC 3339 format when the token update occurred.
- Card Update
- Token Update
{ "updateType": "CARD_UPDATE", "accountInfo": { "accountMasked": "447065xxxxxx8729", "accountExpiry": "022028", "accountPar": "PAR123456789012345678901234" }, "tokenInfo": { "tokenMasked": "447065xxxxxx8729", "tokenExpiry": "022027", "tokenStatus": "ACTIVE", "tokenUpdateDate": "2024-08-12T08:15:00Z" } }
Responses
200Notification received successfully. optional
400Bad Requestoptional
errorCodestringrequired
example: MTS-1616Error code assigned by the Merchant Token Service.
401Unauthorizedoptional
403Forbiddenoptional
404Not Foundoptional
500Internal Server Erroroptional
503Service Unavailableoptional
- fieldInvalidFormat
- cryptoError
- InvalidInputData
{ "errorCode": "MTS-1614" }