Authentication - SNAP
About Authentication - SNAP
NICEPAY implements two authentication security mechanisms across all SNAP API, in accordance with applicable international standard, there are:
- Access Token, to ensure the called API already authenticate and authorized.
- Signature, to ensure the real sender and the request content don't change during the API communication process.
The implementation steps for both two authentication standards will be explained in detail on this page, covering everything from obtaining an Access Token to generating a Signature for processing transactions with NICEPAY .
Key Information
Component | Function | Created By |
|---|---|---|
Client ID / X-CLIENT-KEY | Identity owned by Merchant that given by NICEPAY | NICEPAY |
Access Token | Authorization to access NICEPAY protected resources. Valid for 15 minutes. | NICEPAY (Merchant need to send request beforehand) |
Signature (X-SIGNATURE) | Ensure the data integrity and secure non-repudiation during communication process with the on-going API. | Merchant |
Flow
- Merchant must create Signature beforehand. Then, proceed to request the Access Token.
- NICEPAY verify the Signature, then return accessToken.
- Merchant use accessToken (Bearer) on the next API SNAP request; such as payment, transaction status checking, and refund.
- If the used Access Token already expired, Merchant need to request the new Access Token.
Integration Essentials
Before continue to the next phase, please ensure Merchant already have these following:
- Client ID from NICEPAY . This value will be used as header on X-CLIENT-KEY parameter.
- RSA pairing key (Private Key and Public Key). Private Key only saved by Merchant, meanwhile Public Key registered to NICEPAY .
- The accuracy of server time (NTP synchronous), because X-TIMESTAMP will also be validated.
Never sending, saving in repository, or put Private Key on the application (whether on browser or mobile application)
All Signature creation process must be done on the server on by Merchant.
NICEPAY Base URL
NICEPAY provides two environments that can be accessed by Merchant, which are Sandbox/Development and Production. All proceed request must use HTTPS with adding endpoint path after entered base URL. Ensure Client ID and Key that being use is suitable with the designated environment.
Environment | Protocol | Current NICEPAY Base URL | New NICEPAY Base URL |
|---|---|---|---|
Development | HTTPS | https://dev.nicepay.co.id/ | https://dev-services.nicepay.co.id/ |
Production | HTTPS | https://www.nicepay.co.id/ | https://services.nicepay.co.id/ |
Please proceed the NICEPAY Base URL changes into the newest URL as soon as possible before 25 December 2026.
Testing Credential
To test the NICEPAY SNAP API before proceeding with integration, please use the credentials below and specify IONPAYTEST as clientID.
This sandbox credential is shared among users and its associated Private Key is intended for public testing purposes only. Please use it exclusively in the Development Environment.
Never use this credential in the Production Environment, even when generating your own key pair.
Credential | Function | Used on | Origin | Testing Credential Sample on Development |
|---|---|---|---|---|
Client ID | Merchant identity. Sent as X-CLIENT-KEY (Access Token) and X-PARTNER-ID (service request). | All request. | Given by NICEPAY. | IONPAYTEST |
Channel ID | Merchant channel identity, is Client ID added with 01. | Header CHANNEL-ID on service request. | Shape from Client ID. | IONPAYTEST01 |
Client Secret * | HMAC-SHA512 key for Symmetric Signature. | Service request (Registration, Check Status, Cancel, and others). | Given by NICEPAY and available on Client Secret field on Merchant Back Office. Please visit Credential Management. | Please contact NICEPAY IT Integration to gain the credential. |
Private key (RSA 2048) | Signing Signature Asymmetric. | Request Access Token. | Created and saved by by Merchant. | Please view Signature page to learn further on creating Private Key. |
Public key (RSA 2048) * | Proceed verification on Asymmetric Signature. | Registered on NICEPAY. | Created along side Private Key, then attached by Merchant with Merchant Public Key available on Merchant Back Office - Credential Management on PEM format. | Please registered your Public Key by contacting NICEPAY IT Integration team. |
Public key NICEPAY * | Proceed Signature verification on notification from NICEPAY. | Needed during API SNAP Notification integration with NICEPAY. | Given by NICEPAY through email of could be check on the NICEPAY Public Key field on Merchant Back Office - Credential Management. | Please contact NICEPAY IT Integration team to gain the credential. |
Access Token | Authorization service request valid for 15 minutes. | Header Authorization. | Request result from Access Token. | - |
The following are two additional mandatory parameters generated by the Merchant's system for each request, rather than being provided by NICEPAY:
- X-TIMESTAMP: the timestamp when the Merchant sends the request, formatted according to ISO 8601 with the GMT+7 time zone.
- X-EXTERNAL-ID: unique reference number for every transaction request.
For transactions that require notifications, such as Virtual Account transactions, make sure to prepare the Merchant's Notification URL. This URL must be provided as dbProcessUrl when using the Registration API.
Sandbox Credential Guidance
- Save Private Key Sandbox that given from NICEPAY team, then create Asymmetric Signature with IONPAYTEST as Client ID. The complete example available on Sample Demo (Asymmetric) part.
- Request Access Token to Development endpoint.
- Once the Access Token has been obtained, generate the Symmetric Signature using the Client Secret provided by NICEPAY and include the Access Token value in the Authorization header.
- Use NICEPAY Public Key to validate notification that sent by NICEPAY.
Access Token API
Access Token is an authentication string value that given by NICEPAY to Merchant for accessing API, such as payment, check transaction status, or refund.
Request Access Token
Service Code | 73 |
|---|---|
API Endpoint | |
HTTP Method | POST |
Description | Request Token for Authentication |
Content-type | application/json |
Header
Request Access Token Header
Parameter Header Name | Type | Attribute | Content |
|---|---|---|---|
Content-Type | String | Mandatory | Application/json |
X-TIMESTAMP | String | Mandatory | The request timestamp in ISO 8601 format, including the time zone. YYYY-MM-DDTHH:MM:SS 2022-03-21T10:11:40+07:00 |
X-CLIENT KEY | String | Mandatory | NICEPAY Provided this Client ID Value, please make sure to (X-CLIENT KEY = CLIENT_ID) |
X-SIGNATURE | String | Mandatory | Generated by Merchant created using Asymmetric Signature SHA256withRSA algorithm (Private_Key, stringToSign) stringToSign = client ID + “|” + X-TIMESTAMP Please refer to the following Signature section. |
Body
Request Access Token Parameter
Parameter | Type | Required | Description |
|---|---|---|---|
grantType | String | Mandatory | Please only input this value “client_credentials” |
additionalInfo | Object | Optional | Additional Information. Can be sent as empty object {} |
Response Access Token Parameter
Parameter BI | Parameter NICEPAY | Type | Size | Required | Description |
|---|---|---|---|---|---|
responseCode | responseCd | String | | Optional | |
responseMessage | responseMsg | String | | Optional | Response Message Provides further insight into the API response. |
accessToken | | String | 2048 | Mandatory | A string that represents the authorization issued by NICEPAY for Merchant, so can it can be used to access the transaction API. |
tokenType | | String | | Mandatory | Always has Bearer value. |
expiresIn | | String | | Mandatory | Token validity in second: 900 (15 minutes). |
Sample Parameter
curl --location 'https://dev-services.nicepay.co.id/nicepay/v1.0/access-token/b2b' \
--header 'Content-Type: application/json' \
--header 'X-CLIENT-KEY: IONPAYTEST' \
--header 'X-TIMESTAMP: 2024-12-31T10:11:40+07:00' \
--header 'X-SIGNATURE: DZ9iZR6xtWoFwFaARgo9h6mDgckZpPRLQjMTAlGqrYrJ4xah/deCsxe159H7sf9i2clJeGrsoq5ZDe4tzM+IRQhcxY47K3mYcbnPFGdP5maCC/tCCi63TScB0XUpJzpuPc4TM3G+2uIo816VcoKTXxR5v188m5yGDsGmfW4urddjI1Xor9lZdXP1c6fMH19psMN0g137GCD4tOdjeKW/gGpbvjMi0HQu9PjaJtoFxGmypdxayXfUU3VxWtSWf6AZ88UQ++iOBXfAQIX5Vtt6+fKh/1DOCEcZFe87Em1437VZcTET5dOuEXeQ+ow2PT/Or9iey0M8qQzk3Y6oWJg/sw==' \
--data '{
"grantType": "client_credentials",
"additionalInfo": {}
}'
Access Token Guidance
Include token on Authorization header in every next API SNAP request.
Expiry Date and Requesting New Access Token
- Token validity around 900 seconds (15 minutes) after publish.
- There are no refresh token. After expired, please request new token through the same endpoint.
- Save token in memory or Merchant server cache, then re-use until near the expired time. Please don't request new token on every transaction if the token expiry time is still active.
- If a transaction request is rejected due to an invalid or expired token, please obtain a new Access Token and retry the transaction request once.
API SNAP Service Code
The following is the Service Code list related to the service that Merchant can use after receive Access Token from NICEPAY .
Method | Service Code | API Reference |
|---|---|---|
Virtual Account | 27 | |
Virtual Account | 26 | |
Virtual Account | 31 | |
E-Wallet | 73 | |
E-Wallet | 54 | |
E-Wallet | 55 | |
E-Wallet | 58 | |
QRIS | 47 | |
QRIS | 51 | |
QRIS | 78 | |
Payout | 00 | |
Payout | 11 |
Common API Errors (Access Token)
The following are common issues encountered during token requests. Please refer to the General Response Code and Message - API SNAP for further information.
Case | Things that need to be checked |
|---|---|
Signature is not valid | stringToSign format, frequent use Private Key, and encoding Base64. |
Client ID is not recognized | X-CLIENT-KEY value and environment (Development/Sandbox atau Production). |
Wrong X-TIMESTAMP format | ISO-8601 format with time zone, example +07:00. |
Empty mandatory field | Header X-TIMESTAMP, X-CLIENT-KEY, X-SIGNATURE, and grantType. |
Wrong grantType | Must be filled with "client_credentials" value |
Signature
Signature (X-SIGNATURE) is a digital signage on every API SNAP request. This signature provide three layer security, including:
- Data Integrity. Ensure request data unchange during sending request process without undetect by system. If there are data changes, digital signature is no longer valid so the request will be rejected.
- Non-Repudiation. Ensure the sender can't deny the request that has been sign with their Private Key, because that sign only can be created by the party that has the suitable Private Key. This mechanism is valid for signage with Asymmetric Signature.
- Replay Protection. Prevent the old request that has been intercept for re-send and re-process as valid request. This should be done by attached X-TIMESTAMP on the sign data, so the request valid time could be verify.
SNAP standard from Bank Indonesia using two type of Signature depends on the called API.
Type | Used for | Algorithm | Key |
|---|---|---|---|
Asymmetric | Request Access Token. | SHA256withRSA | Private Key Merchant |
Symmetric | Request layanan (transaksi). | HMAC-SHA512 | Client Secret |
Create Key Pair for Asymmetric Signature A (Private Key and Public Key)
Asymmetric Signature uses an RSA key pair consisting of two keys:
- Private Key: Used by the Merchant to sign API requests. It must be kept confidential and must never be shared.
- Public Key: Provided to NICEPAY for signature verification.
Both keys must use the RSA 2048-bit key length.
The following is a sample using OpenSSL.
1. Created Private Key.
File private_key.pem has PKCS#8 (start with -----BEGIN PRIVATE KEY-----), that can be used directly on Java dan Node.js.
2. Create Public Key from Private Key.
File public_key.pem start with -----BEGIN PUBLIC KEY-----.
3. Give Public Key to NICEPAY.
Only send public_key.pem to NICEPAY. Ensure Merchant register the Public Key for the environment that will be used (Development/Sandbox or Production). Use PEM format, which is public_key.pem complete with -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- row. Only paste the Public Key. Never paste the Private Key on any field.
4. Save the Private Key securely.
Save private_key.pem on Merchant server with limited access, like in secret manager or protected variable environment. If Private Key leak, create new key pair and register the newest Public Key to NICEPAY.
5. Test the create Signature (optional)
Merchant can try create Signature for the terminal to compare the result with the owned code.
Format remark: If Private Key Merchant start with -----BEGIN RSA PRIVATE KEY----- (PKCS#1), change to PKCS#8 into openssl pkcs8 -topk8 -nocrypt -in private_key.pem -out private_key_pkcs8.pem because Java commonly need PKCS#8 format.
This command produce X-SIGNATURE value for that stringToSign.
Signature for Access Token (Asymmetric)
1. Prepare stringToSign.
Example:
X-TIMESTAMP value on stringToSign must be identic to the sent one on Header.
2. Sign withSHA256withRSA.
Use SHA256withRSA algorithm with Private Key the Merchant to sign stringToSign.
3. Encode with Base64.
Signature result (byte) is encode to Base64.
4. Sent as Header.
Input the result into X-SIGNATURE Header.
Sample Code
const crypto = require('crypto');
const fs = require('fs');
const clientId = 'IONPAYTEST';
const timestamp = '2024-12-31T10:11:40+07:00'; // must exactly match the X-TIMESTAMP header.
const stringToSign = `${clientId}|${timestamp}`;
const privateKey = fs.readFileSync('private_key.pem', 'utf8');
const signer = crypto.createSign('RSA-SHA256');
signer.update(stringToSign);
signer.end();
const xSignature = signer.sign(privateKey, 'base64');Sample Demo (Asymmetric)
Use the following demo data to practice and compare the Merchant result code.
Key pair on the below specially created for demo. Never use it on Development/Sandbox or Production.
Data input
stringToSign
Private Key demo (save as ionpaytest_sandbox_private_key.pem)
Public Key demo (save as ionpaytest_sandbox_public_key.pem)
Result: X-SIGNATURE
Since SHA256withRSA (PKCS#1 v1.5) produces the same Signature value for identical inputs and keys, the Merchant's test should generate a Signature that exactly matches the example above. The Merchant can also verify the result using the terminal:
Client Secret (Symmetric Key)
Unlike an RSA key pair, the key used for Symmetric Signature is not generated by the Merchant. Instead, it is the Client Secret issued by NICEPAY and used as the key for the HMAC-SHA512 algorithm. NICEPAY uses the same key to verify the Signature generated by the Merchant.
| Asymmetric (Access Token) | Symmetric (Service Request) |
|---|---|---|
Key | Private Key RSA | Client Secret |
Created by | Merchant | NICEPAY |
Given to NICEPAY | Public Key | None. The key must not be shared with any party. |
Saved by | Merchant (Private Key) | Merchant andNICEPAY |
Client Secret Management Guidelines:
- Store the Client Secret on the Merchant's server using a secure secret manager or protected environment variables.
- Never store the Client Secret in source code, repositories, or client-side applications, including browsers and mobile applications.
- Never include the Client Secret in API requests, logs, or communications with any party, including the NICEPAY Support Team.
- Use the Client Secret corresponding to the appropriate environment, either Development/Sandbox or Production.
- If the Client Secret is suspected of being compromised or exposed, immediately contact the NICEPAY team to request a new Client Secret.
Signature for Transaction Service Request (Symmetric)
Once the Access Token has been obtained, Merchant able to request NICEPAY SNAP transaction service (such as registration transaction, payment, check status and refund). Each request must be signed using a Symmetric Signature.
The following headers must be included in the request:
Header Name | Required | Description |
|---|---|---|
Content-Type | Mandatory | application/json |
Authorization | Mandatory | Bearer {accessToken} |
X-TIMESTAMP | Mandatory | Request time, ISO-8601 format on time zone GMT+7 (Jakarta). Example: 2024-12-31T10:11:40+07:00 |
X-SIGNATURE | Mandatory | Symmetric Signature that has been created by Merchant, with the formula below. |
X-PARTNER-ID | Mandatory | Client ID from NICEPAY. Maximum 20 characters. |
X-EXTERNAL-ID | Mandatory | Unique reference number for every request. Maximum 40 characters. |
CHANNEL-ID | Mandatory | "Client ID" added with "01". Example: IONPAYTEST + 01 into IONPAYTEST01 Maximum 20 characters. |
1. Count hash body
Minify the request body by removing whitespace and line breaks outside string values, calculate its SHA-256 hash, and convert the result to lowercase hexadecimal.
2. Construct stringToSign
EndpointUrl The EndpointUrl refers to the API Endpoint value provided on each API documentation page. Include the query string, if applicable, but exclude the domain.
For example: /api/v1.0/transfer-va/create-va for Registration - API Virtual Account SNAP.
3. Sign with HMAC-SHA512
Sample Code
const crypto = require('crypto');
const body = JSON.stringify(requestBody); //JSON.stringify already produces a minified JSON body.
const bodyHash = crypto.createHash('sha256').update(body).digest('hex').toLowerCase();
const stringToSign = [method, endpointUrl, accessToken, bodyHash, timestamp].join(':');
const xSignature = crypto
.createHmac('sha512', clientSecret)
.update(stringToSign)
.digest('base64');The hashed request body must exactly match with the sent body in request. If the library used by Merchant to send the request modifies the JSON structure, field order or formatting after the Signature created, then the verification process will fail.
Sample Demo (Symmetric)
The following sample is using Registration - API Virtual Account SNAP (Service Code 27, Bank BMRI), with Client Secret and Access Token demo. Don't use this demo value to proceed the real request whether on Development or Production environment.
Data input
Request body (minify already)
1. bodyHash
2. stringToSign
3. Result: X-SIGNATURE
4. Include the Signature in the Request
The generated Signature must be included in the X-SIGNATURE header, along with the other required headers listed in the table above.
Important Notes:
- The request body provided in --data-raw must match the request body used to generate the SHA-256 hash exactly. Any differences in formatting, whitespace, line breaks, or values may result in an invalid Signature.
- The example above uses a demo Access Token and Signature. Therefore, the request will be rejected if submitted as is.
- Before testing, replace the demo values with your actual Access Token, Client Secret, and Merchant Client ID corresponding to the environment you are using.
Additionally, Merchant can compare the generated result with the output obtained by running the following terminal command:
Common Mistake on Signature Creation
Case | Frequent issue |
|---|---|
The Signature rejected although the code looks right. | The X-TIMESTAMP value in the stringToSign differs from the value sent in the request header. |
The Signature is rejected for only some requests. | The request body is modified after hashing (whitespace, field order, or encoding). |
The Signature rejected on all requests. | Private Key didn't match with registered Public Key on NICEPAY. |
Signature Rejected when switching environments. | Using a Client ID or key from one environment in another environment. |
Weird character appears on the Signature. | Forgot to encode Base64 or there is new line carried along. |