Skip to main content

BLIK OneClick

BLIK OneClick enables one-click payments without requiring the customer to enter a six-digit BLIK code for subsequent transactions. The customer registers a bank alias during the first payment and then pays with one click.

Benefits​

  • Faster payments: no T6 code for subsequent transactions
  • Higher conversion: fewer steps in the payment process
  • Customer convenience: one-click payment

How BLIK OneClick works​

The process has two stages:

  1. Alias registration: the first payment uses a BLIK code and includes consent to save the alias
  2. Alias payment: subsequent payments do not require a BLIK code
POST/api/v1_0/payments/registerComplete registration contract: parameters, checksum, and error codes.Full contract in the API Reference

Requirements​

  • An active Payment Point with BLIK OneClick enabled
  • Secure server-side storage for alias_value, associated with the customer's account
  • Access to the customer's IP address and User-Agent, as required by applicable regulations

Endpoint​

POST https://api-payments.dpay.pl/api/v1_0/payments/register
Content-Type: application/json

Register an alias (first payment)​

For the first payment, the customer enters a BLIK code and consents to saving the alias. The request is the same as for BLIK Level 0, with the additional register_blik_alias field.

Request parameters​

FieldTypeRequiredDescription
transactionTypestringYes"transfers"
servicestringYesService name from the panel
valuestringYesAmount in PLN
url_successstringYesURL used after a successful payment
url_failstringYesURL used after a failed payment
url_ipnstringYesURL for IPN notifications
checksumstringYesSHA-256 checksum
blik_codestringYesSix-digit BLIK code
user_ipstringYesCustomer's IP address
user_agentstringYesCustomer's User-Agent header
register_blik_aliasobjectYesAlias data to register
alias_ipn_urlstringNoURL for alias-status notifications, maximum 500 characters; if omitted, notifications are sent to url_ipn

register_blik_alias object​

FieldTypeRequiredDescription
labelstringYesAlias label visible to the customer, maximum 35 characters (the BLIK limit)
typestringYesAlias type; it must be "UID"
valuestringNoYour own alias value, maximum 128 characters; if omitted, dpay generates one automatically

Checksum generation​

Generate the checksum exactly as for a standard payment:

sha256({service}|{SecretHash}|{value}|{url_success}|{url_fail}|{url_ipn})
Recommendation: provide your own alias value

We recommend providing your own value in register_blik_alias.value, such as an identifier generated by your system, and storing it on your server in association with the customer's account. You need it for subsequent alias payments and to check the alias status with POST /blik/aliases. If you omit the field, dpay generates the value automatically.

Example request​

cURL​

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/register \
-H "Content-Type: application/json" \
-d '{
"transactionType": "transfers",
"service": "abc123",
"value": "29.99",
"url_success": "https://myshop.example/success",
"url_fail": "https://myshop.example/error",
"url_ipn": "https://myshop.example/api/ipn",
"checksum": "e3b0c44298fc1c149afb...",
"blik_code": "123456",
"user_ip": "192.168.1.100",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"register_blik_alias": {
"label": "My shop",
"type": "UID"
}
}'

PHP​

<?php
$service = getenv('DPAY_SERVICE');
$secretHash = getenv('DPAY_SECRET_HASH');

$value = '29.99';
$urlSuccess = 'https://myshop.example/success';
$urlFail = 'https://myshop.example/error';
$urlIpn = 'https://myshop.example/api/ipn';

$checksum = hash('sha256',
$service . '|' . $secretHash . '|' . $value . '|' .
$urlSuccess . '|' . $urlFail . '|' . $urlIpn
);

$payload = json_encode([
'transactionType' => 'transfers',
'service' => $service,
'value' => $value,
'url_success' => $urlSuccess,
'url_fail' => $urlFail,
'url_ipn' => $urlIpn,
'checksum' => $checksum,
'blik_code' => $_POST['blik_code'],
'user_ip' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'register_blik_alias' => [
'label' => 'My shop',
'type' => 'UID',
],
]);

$ch = curl_init('https://api-payments.dpay.pl/api/v1_0/payments/register');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

JavaScript (Node.js / Express)​

const crypto = require('crypto');
const axios = require('axios');

async function registerBlikAlias(req, res) {
const service = process.env.DPAY_SERVICE;
const secretHash = process.env.DPAY_SECRET_HASH;

const value = '29.99';
const urlSuccess = 'https://myshop.example/success';
const urlFail = 'https://myshop.example/error';
const urlIpn = 'https://myshop.example/api/ipn';

const checksum = crypto
.createHash('sha256')
.update(`${service}|${secretHash}|${value}|${urlSuccess}|${urlFail}|${urlIpn}`)
.digest('hex');

const response = await axios.post(
'https://api-payments.dpay.pl/api/v1_0/payments/register',
{
transactionType: 'transfers',
service,
value,
url_success: urlSuccess,
url_fail: urlFail,
url_ipn: urlIpn,
checksum,
blik_code: req.body.blik_code,
user_ip: req.ip,
user_agent: req.headers['user-agent'],
register_blik_alias: {
label: 'My shop',
type: 'UID',
},
}
);

return response.data;
}

API response​

{
"error": false,
"msg": "Internal processing",
"status": true,
"transactionId": "abc-def-123-456"
}

The status field is a Boolean (true or false).

After this response, the customer must approve both the transaction and the alias registration in their banking app. You receive the payment result through IPN.

Pay with an alias (OneClick)​

For subsequent payments, the customer does not need to enter a BLIK code. Send the saved alias_value instead.

Request parameters​

FieldTypeRequiredDescription
transactionTypestringYes"transfers"
servicestringYesService name from the panel
valuestringYesAmount in PLN
url_successstringYesURL used after a successful payment
url_failstringYesURL used after a failed payment
url_ipnstringYesURL for IPN notifications
checksumstringYesSHA-256 checksum
blik_aliasstringYesBLIK OneClick alias, maximum 128 characters
user_ipstringYesCustomer's IP address
user_agentstringYesCustomer's User-Agent header
warning

Do not send blik_code or register_blik_alias when paying with an alias; blik_alias is mutually exclusive with both. The blik_code and register_blik_alias pair is valid and required when registering an alias during the first payment.

Example request​

cURL​

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/register \
-H "Content-Type: application/json" \
-d '{
"transactionType": "transfers",
"service": "abc123",
"value": "29.99",
"url_success": "https://myshop.example/success",
"url_fail": "https://myshop.example/error",
"url_ipn": "https://myshop.example/api/ipn",
"checksum": "e3b0c44298fc1c149afb...",
"blik_alias": "a1b2c3d4e5f6...",
"user_ip": "192.168.1.100",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}'

PHP​

<?php
$service = getenv('DPAY_SERVICE');
$secretHash = getenv('DPAY_SECRET_HASH');

$value = '29.99';
$urlSuccess = 'https://myshop.example/success';
$urlFail = 'https://myshop.example/error';
$urlIpn = 'https://myshop.example/api/ipn';

$checksum = hash('sha256',
$service . '|' . $secretHash . '|' . $value . '|' .
$urlSuccess . '|' . $urlFail . '|' . $urlIpn
);

// $aliasValue - the customer's previously saved alias
$payload = json_encode([
'transactionType' => 'transfers',
'service' => $service,
'value' => $value,
'url_success' => $urlSuccess,
'url_fail' => $urlFail,
'url_ipn' => $urlIpn,
'checksum' => $checksum,
'blik_alias' => $aliasValue,
'user_ip' => $_SERVER['REMOTE_ADDR'],
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
]);

$ch = curl_init('https://api-payments.dpay.pl/api/v1_0/payments/register');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);

$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

JavaScript (Node.js / Express)​

const crypto = require('crypto');
const axios = require('axios');

async function payWithBlikAlias(req, res) {
const service = process.env.DPAY_SERVICE;
const secretHash = process.env.DPAY_SECRET_HASH;

const value = '29.99';
const urlSuccess = 'https://myshop.example/success';
const urlFail = 'https://myshop.example/error';
const urlIpn = 'https://myshop.example/api/ipn';

const checksum = crypto
.createHash('sha256')
.update(`${service}|${secretHash}|${value}|${urlSuccess}|${urlFail}|${urlIpn}`)
.digest('hex');

// aliasValue - the customer's previously saved alias
const aliasValue = await getUserBlikAlias(req.user.id);

const response = await axios.post(
'https://api-payments.dpay.pl/api/v1_0/payments/register',
{
transactionType: 'transfers',
service,
value,
url_success: urlSuccess,
url_fail: urlFail,
url_ipn: urlIpn,
checksum,
blik_alias: aliasValue,
user_ip: req.ip,
user_agent: req.headers['user-agent'],
}
);

return response.data;
}

API response​

{
"error": false,
"msg": "Internal processing",
"status": true,
"transactionId": "abc-def-123-456"
}

The status field is a Boolean (true or false).

Depending on the bank's settings, the customer may be asked to approve the transaction in their banking app. You receive the payment result through IPN.

Manage aliases​

Retrieve an alias​

Check the BLIK alias registered for a customer.

POST/api/v1_0/payments/blik/aliasesComplete contract: parameters and alias-status fields.Full contract in the API Reference

Endpoint​

POST https://api-payments.dpay.pl/api/v1_0/payments/blik/aliases
Content-Type: application/json

Parameters​

FieldTypeRequiredDescription
servicestringYesService name from the panel
alias_valuestringYesAlias value
alias_typestringNoAlias type; defaults to "UID"
checksumstringYesSHA-256 checksum

Checksum generation​

sha256({service}|{secret}|{alias_value})

Example request​

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/blik/aliases \
-H "Content-Type: application/json" \
-d '{
"service": "abc123",
"alias_value": "a1b2c3d4e5f6...",
"alias_type": "UID",
"checksum": "f5a3b2c1d0..."
}'

Response​

The data field is a single object describing the alias:

{
"status": "success",
"data": {
"alias_value": "a1b2c3d4e5f6...",
"alias_type": "UID",
"status": "ACTIVE",
"expiration_date": "2027-03-22",
"apps": [
{ "key": "app1", "label": "Bank app" }
]
}
}
FieldTypeDescription
alias_valuestring|nullAlias value
alias_typestringAlways "UID"
statusstring|nullCurrent alias status, such as "ACTIVE", "INACTIVE", "UNREGISTERED", or "EXPIRED"
expiration_datestring|nullAlias expiration date
appsarrayBanking apps associated with the alias, as { key, label } objects

Unregister an alias​

Remove a registered BLIK alias.

POST/api/v1_0/payments/blik/aliases/unregisterComplete BLIK alias unregistration contract.Full contract in the API Reference

Endpoint​

POST https://api-payments.dpay.pl/api/v1_0/payments/blik/aliases/unregister
Content-Type: application/json

Parameters​

FieldTypeRequiredDescription
servicestringYesService name from the panel
alias_valuestringYesAlias value to unregister
alias_typestringNoAlias type - "UID" (default). Cancel a recurring payment with the /payments/recurring/cancel endpoint
reasonstringNoReason for unregistering the alias
checksumstringYesSHA-256 checksum

Checksum generation​

sha256({service}|{secret}|{alias_value})

Example request​

curl -X POST https://api-payments.dpay.pl/api/v1_0/payments/blik/aliases/unregister \
-H "Content-Type: application/json" \
-d '{
"service": "abc123",
"alias_value": "a1b2c3d4e5f6...",
"alias_type": "UID",
"reason": "The customer requested removal",
"checksum": "f5a3b2c1d0..."
}'

Response​

{
"status": "success",
"data": {
"status": "success"
}
}

Alias notifications (IPN)​

dpay.pl sends an alias_update IPN notification to the merchant endpoint whenever an alias status changes, including registration, unregistration, and expiration.

Notification URL

The notification is sent to the alias_ipn_url provided during transaction registration. If that field was omitted, dpay uses url_ipn.

Notification schema​

dpay.pl sends a POST request with the Content-Type: application/json header and the following body:

{
"id": "abc-def-123-456",
"type": "alias_update",
"change_type": "ALIAS_REGISTER",
"alias_type": "UID",
"alias_status": "ACTIVE",
"alias_key": "a1b2c3d4e5f6...",
"alias_label": "Moja karta",
"alias_expire_at": "2027-01-01T00:00:00+00:00",
"change_reason_category": null,
"change_reason_message": null,
"version": 1,
"signature": "e3b0c44298fc..."
}

Field descriptions​

FieldTypeDescription
idstringdpay.pl transaction identifier
typestringNotification type; always "alias_update"
change_typestring|nullChange type: "ALIAS_REGISTER", "ALIAS_UPDATE", "ALIAS_UNREGISTER", "ALIAS_EXPIRED", or "ALIAS_DECLINED"
alias_typestring|nullAlias type: "UID" (OneClick) or "PAYID" (recurring payments)
alias_statusstring|nullCurrent alias status: "ACTIVE", "INACTIVE", "UNREGISTERED", "EXPIRED", or "DECLINED"
alias_keystring|nullAlias identifier in the BLIK system (the same one POST /blik/aliases returns in alias_value). It is not equal to the alias value you send with payments
alias_labelstring|nullAlias label; it can be empty if no label was assigned
alias_expire_atstring|nullAlias expiration timestamp in ISO 8601 format; it can be empty
change_reason_categorystring|nullChange-reason category
change_reason_messagestring|nullChange-reason description
versionintegerSchema version, currently 1
signaturestringDigital signature used to verify authenticity
Identifying the alias

Correlate the notification with the stored alias by the id field - it identifies the transaction in which the alias was registered. The alias_key field contains the alias identifier in the BLIK system, not the alias value used for payments. You can retrieve the current alias status and expiration date at any time with POST /blik/aliases.

Signature verification​

The signature uses SHA-256:

sha256({id}{SecretHash}{type}{version})

Values are concatenated without a separator, exactly as in a standard IPN signature.

PHP​

<?php
$data = json_decode(file_get_contents('php://input'), true);

if (!$data || $data['type'] !== 'alias_update') {
http_response_code(400);
exit;
}

$secretHash = 'TWOJ_SECRET_HASH';

$expectedSignature = hash('sha256',
$data['id'] . $secretHash . $data['type'] . $data['version']
);

if (!hash_equals($expectedSignature, $data['signature'])) {
http_response_code(403);
echo 'Invalid signature';
exit;
}

// The signature is valid; handle the alias change
// Correlate the alias by the transaction that registered it: $data['id']
switch ($data['change_type']) {
case 'ALIAS_REGISTER':
// Alias registered; mark the customer's alias as active
break;
case 'ALIAS_UPDATE':
// Alias data changed; refresh its status through POST /blik/aliases
break;
case 'ALIAS_UNREGISTER':
// Alias unregistered; remove it from the database
break;
case 'ALIAS_EXPIRED':
// Alias expired; mark it as inactive
break;
case 'ALIAS_DECLINED':
// Registration rejected by the customer or bank; remove the alias
break;
}

http_response_code(200);
echo 'OK';

Node.js​

const crypto = require('crypto');

app.post('/api/alias-ipn', (req, res) => {
const data = req.body;

if (!data || data.type !== 'alias_update') {
return res.status(400).send('Invalid payload');
}

const secretHash = 'TWOJ_SECRET_HASH';
const expectedSignature = crypto
.createHash('sha256')
.update(`${data.id}${secretHash}${data.type}${data.version}`)
.digest('hex');

if (expectedSignature !== data.signature) {
return res.status(403).send('Invalid signature');
}

// The signature is valid; handle the alias change
// Correlate the alias by the transaction that registered it: data.id
switch (data.change_type) {
case 'ALIAS_REGISTER':
// Alias registered; mark the customer's alias as active
break;
case 'ALIAS_UPDATE':
// Alias data changed; refresh its status through POST /blik/aliases
break;
case 'ALIAS_UNREGISTER':
// Alias unregistered; remove it from the database
break;
case 'ALIAS_EXPIRED':
// Alias expired; mark it as inactive
break;
case 'ALIAS_DECLINED':
// Registration rejected by the customer or bank; remove the alias
break;
}

res.status(200).send('OK');
});

Retry schedule​

The retry mechanism is the same as for standard IPN notifications:

AttemptDelayTime since the first attempt
1immediately0 min
22 min2 min
34 min6 min
48 min14 min
516 min30 min
632 min~1 h
764 min~2 h
8128 min~4 h
9256 min~8.5 h
10512 min~17 h

Your endpoint must respond with HTTP 200 and the body "OK". Otherwise, dpay.pl retries delivery.

Idempotency

Your endpoint can receive multiple notifications about the same alias. Make the handler idempotent so processing the same notification more than once does not create errors or duplicates.

Validation and constraints​

RuleDescription
Mutually exclusive fieldsblik_alias cannot be sent with blik_code or register_blik_alias. The blik_code and register_blik_alias pair is valid for alias registration
register_blik_alias.labelMaximum 35 characters (the BLIK limit)
register_blik_alias.typeMust be "UID"
register_blik_alias.valueOptional, maximum 128 characters
alias_valueMaximum 128 characters
blik_codeExactly six digits

Rate limits​

EndpointLimit
POST /payments/register120 requests/min
POST /blik/aliases60 requests/min
POST /blik/aliases/unregister30 requests/min

Error handling​

When a payment is declined, the registration response has the form {"error": true, "msg": "Transaction canceled", "status": false, ...}. The error code is in additionalInfo.error, with an optional description in additionalInfo.error_description.

In test mode (sandbox), the following simulation codes are used:

Error codeDescriptionAction
DECLINETransaction declinedAsk the customer to retry
EXPIRED_CARDPayment instrument expiredInform the customer
INSUFFICIENT_FUNDSInsufficient fundsInform the customer
USER_DECLINEDCustomer declined the transaction in their banking appAsk the customer to retry
TIMEOUTTimed out while waiting for confirmationAsk for a new code
ALIAS_NOT_FOUNDAlias not foundRegister a new alias or use a BLIK code
SYSTEM_ERRORSystem errorRetry later

In production, additionalInfo.error contains the raw BLIK decline code passed through without modification, or one of the following codes:

Error codeDescriptionAction
ALIAS_NOT_FOUNDAlias not foundRegister a new alias or use a BLIK code
ALIAS_APP_NOT_FOUNDThe selected banking app is not associated with the aliasRetrieve the app list with POST /blik/aliases
ALIAS_APP_AMBIGUOUSThe alias is associated with multiple apps and requires a selectionLet the customer select an app from the apps list
INTERNAL_ERRORInternal errorRetry later
tip

If an alias expires or the customer unregisters it in their banking app, register it again during the next payment made with a BLIK code.