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 50 characters
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_typestringYesAlias type, "UID"
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", "ALIAS_DECLINED", or "SCA_REJECTED"
alias_typestring|nullAlias type, for example "UID"
alias_statusstring|nullCurrent alias status: "ACTIVE", "INACTIVE", "UNREGISTERED", "EXPIRED", "DECLINED", or "SCA_REJECTED"
alias_keystring|nullAlias identifier; the same value used as alias_value for subsequent 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

The alias_key field contains the alias identifier—the same alias_value used for payments—so you can correlate the notification with the stored alias. The id field identifies the initiating transaction. 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 alias_key (= your alias_value) or by transaction $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':
case 'SCA_REJECTED':
// 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 alias_key (= your alias_value) or by transaction 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':
case 'SCA_REJECTED':
// 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 50 characters
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.