Each merchant may define a specific asynchronous HTTPS confirmation URL (callback URL) through which Payconiq notifies the status of a payment. This enables the merchant's or partner's backend to act upon the payment status (e.g., mark the payment in a database, update stock, send confirmation emails, etc.).
Callbacks are asynchronous and issued via HTTP POST requests using TLS 1.2 encryption.
For certain products (e.g., Top Up), a callback URL must be provided at the time of product creation.
In one-way TLS, Payconiq encrypts callback requests and validates the merchant's server certificate. No certificate exchange is needed beforehand. Callbacks should function out of the box.
Contact: devsupport@payconiq.be for assistance.
Payconiq retries sending callbacks for up to 24 hours if an HTTP 200 OK response is not received. Retry triggers include:
- No response within 15 seconds
- HTTP 429 Too Many Requests
- HTTP 500 Internal Server Error
- HTTP 503 Service Unavailable
- HTTP 504 Gateway Timeout
- HTTP 509 Bandwidth Limit Exceeded
Notes:
- The payment status does not change.
- The callback content (headers, body, target URL) remains identical.
- Payconiq stops retrying after a 200 OK or after 24 hours.
Callback requests contain several headers, including:
signature: <JWS Signature>
content-type: application/json
user-agent: Payconiq Payments/v3
Name | Description |
---|---|
signature | A JSON Web Signature (JWS) in base64url format, digitally signed by Payconiq. |
user-agent | Identifies the Payconiq callback sender. |
content-type | Indicates the media type of the payload (application/json). |
To verify Payconiq-generated callbacks, use the detached JSON Web Signature (JWS) sent in the signature
header.
The JWS includes:
- JOSE Header (base64url encoded)
- JWS Payload (not included)
- JWS Signature
jws = base64URLEncode(JOSE Header)..base64URLEncode(Signature(base64URLEncode(JOSE Header) + base64URLEncode(Request Body)))
{
"typ": "jose+json",
"kid": "JWK kid",
"alg": "ES256",
"crit": ["https://payconiq.com/sub", "https://payconiq.com/iss", "https://payconiq.com/iat", "https://payconiq.com/jti", "https://payconiq.com/path"],
"https://payconiq.com/sub": "{PaymentProfileId}",
"https://payconiq.com/iss": "Payconiq",
"https://payconiq.com/iat": "{ISO 8601 UTC Timestamp}",
"https://payconiq.com/jti": "{Unique-request-identifier}",
"https://payconiq.com/path": "https://www.merchantcallback.com/payconiqpayment"
}
Cache the JWKS from Payconiq.
Extract
kid
from JOSE header.Match
kid
with cached JWK:- If matched, verify signature using your preferred library (e.g., jose4j for Java).
- Ensure all
crit
headers are present and valid.
If not matched, fetch and re-cache the JWKS, then repeat step 3.
The body contains JSON with payment status details. Verify the signature before processing this data.
PaycBancontact Payconiq Company Payment ID
Only EUR is supported currently
Requested amount in cents
Description of the payment that will be shown to the debtor, also used in the bank statement for reconciliation purposes. The characters used must comply with the SEPA Requirements for an Extended Character Set (UNICODE Subset) - Best Practices | European Payments Council.
Merchant payment reference, used to reference the Bancontact Payconiq Company payment in the merchant’s system. The characters used must comply with the SEPA Requirements for an Extended Character Set (UNICODE Subset) - Best Practices | European Payments Council.
When the payment was created
When the payment is going to expire. After that date the payment can't be confirmed anymore
if the payment is SUCCEEDED, then this field represents the date-time on which the payment was SUCCEEDED
Status | Description |
---|---|
PENDING | The merchant has created the payment and and is pending to proceed with identify step. |
IDENTIFIED | The user has scanned the payment's QR code with the Payconiq By Bancontact APP. |
AUTHORIZED | The user has confirmed the payment and the bank authorized it. |
AUTHORIZATION_FAILED | The authorization with the bank failed. |
FAILED | Something went wrong during the payment process(e.g authorization failed). |
SUCCEEDED | The payment has succeeded. |
CANCELLED | When the payment has been canceled after the user has scanned it, or the merchant has cancelled the payment. |
EXPIRED | The payment has expired. |
PENDING_MERCHANT_ACKNOWLEDGEMENT | The payment is waiting for the merchant to acknowledge. |
VOIDED | The payment has been voided |
Customer that paid
Debtor's IBAN masked
Debtor's first name
- PREPROD merchant API
https://merchant.api.preprod.bancontact.net/callback
- PROD merchant API
https://merchant.api.bancontact.net/callback
- curl
- JavaScript
- Node.js
- Python
- Java
- C#
- PHP
- Go
- Ruby
- R
- Payload
curl -i -X POST \
https://merchant.api.preprod.bancontact.net/callback \
-H 'Content-Type: application/json' \
-H 'Signature: YOUR_API_KEY_HERE' \
-H 'User-Agent: Payconiq' \
-d '{
"paymentId": "5f91483d-78a7-4914-bc6f=",
"currency": "EUR",
"amount": 0,
"description": "string",
"reference": "19848995",
"createdAt": "2019-08-24T14:15:22Z",
"expireAt": "2019-08-24T14:15:22Z",
"succeededAt": "2019-08-24T14:15:22Z",
"status": "PENDING",
"debtor": {
"iban": "*************12636",
"name": "John"
}
}'
Payconiq publishes its public keys in JWKS format:
- PREPROD JWK: jwks.preprod.bancontact.net
- PROD JWK: jwks.bancontact.net
- Bancontact Payconiq may rotate its certificate without prior notice.
- Merchants who pin certificates must pin only the CN name of the certificate, enabling seamless rotation.
- A new JWK will be added for 24 hours before the old one is removed.
- Merchants should cache JWKs for up to 12 hours and re-fetch if verification fails.