Skip to content
Last updated

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.

One-Way TLS Encryption Support

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.

Callback Retry Policy

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 Headers

Callback requests contain several headers, including:

signature: <JWS Signature>
content-type: application/json
user-agent: Payconiq Payments/v3
NameDescription
signatureA JSON Web Signature (JWS) in base64url format, digitally signed by Payconiq.
user-agentIdentifies the Payconiq callback sender.
content-typeIndicates the media type of the payload (application/json).

Callback Signature

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)))

JOSE Header Example

{
  "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"
}

Signature Verification Steps

  1. Cache the JWKS from Payconiq.

  2. Extract kid from JOSE header.

  3. 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.
  4. If not matched, fetch and re-cache the JWKS, then repeat step 3.

Callback Body

The body contains JSON with payment status details. Verify the signature before processing this data.

paymentIdstring= 24 charactersrequired

PaycBancontact Payconiq Company Payment ID

currencystringrequired

Only EUR is supported currently

Default "EUR"
amountinteger(int64)required

Requested amount in cents

descriptionstring
referencestring
createdAtstring(date-time)required

When the payment was created

expireAtstring(date-time)

When the payment is going to expire. After that date the payment can't be confirmed anymore

succeededAtstring(date-time)

if the payment is SUCCEEDED, then this field represents the date-time on which the payment was SUCCEEDED

statusstring(MerchantPaymentStatus)required
StatusDescription
PENDINGThe merchant has created the payment and and is pending to proceed with identify step.
IDENTIFIEDThe user has scanned the payment's QR code with the Payconiq By Bancontact APP.
AUTHORIZEDThe user has confirmed the payment and the bank authorized it.
AUTHORIZATION_FAILEDThe authorization with the bank failed.
FAILEDSomething went wrong during the payment process(e.g authorization failed).
SUCCEEDEDThe payment has succeeded.
CANCELLEDWhen the payment has been canceled after the user has scanned it, or the merchant has cancelled the payment.
EXPIREDThe payment has expired.
PENDING_MERCHANT_ACKNOWLEDGEMENTThe payment is waiting for the merchant to acknowledge.
VOIDEDThe payment has been voided
Enum"PENDING""IDENTIFIED""AUTHORIZED""AUTHORIZATION_FAILED""SUCCEEDED""FAILED""CANCELLED""EXPIRED""PENDING_MERCHANT_ACKNOWLEDGEMENT""VOIDED"
debtorobjectrequired

Customer that paid

debtor.​ibanstringrequired

Debtor's IBAN masked

debtor.​namestring

Debtor's first name

Sample Request – callback

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"
    }
  }'

Certificates

Payconiq publishes its public keys in JWKS format:

Certificate Rotation

  • 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.