New payment URLs
Following the decommissioning of the Payconiq brand in Belgium, these URL changes are essential to ensure compliance and
mark the final phase in aligning our branding with the new Bancontact Pro identity.

Please implement adaptations described here promptly to avoid service interruptions and guarantee the continued acceptance of mobile payments via Bancontact Pay and Wero.

Changes are already available in our pre-production environement and will be rolled out in production starting 11/05/2026

Merchant Callback

Each merchant may define a specific asynchronous HTTPS confirmation URL (callback URL) through which Bancontact 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, Bancontact 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@bancontact.com](mailto:devsupport@bancontact.com) for assistance.

## Callback Retry Policy

Bancontact 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.
* Bancontact stops retrying after a 200 OK or after 24 hours.


## Callback Headers

Callback requests contain several headers, including:


```http
signature: <JWS Signature>
content-type: application/json
user-agent: Bancontact Payments/v3
```

| Name | Description |
|  --- | --- |
| `signature` | A JSON Web Signature (JWS) in base64url format, digitally signed by Bancontact. |
| `user-agent` | Identifies the Bancontact callback sender. |
| `content-type` | Indicates the media type of the payload (application/json). |


## Callback Signature

To verify Bancontact-generated callbacks, use the detached [JSON Web Signature (JWS)](https://tools.ietf.org/html/rfc7797) sent in the `signature` header.

The JWS includes:

* JOSE Header (base64url encoded)
* JWS Payload (not included)
* JWS Signature



```text
jws = base64URLEncode(JOSE Header)..base64URLEncode(Signature(base64URLEncode(JOSE Header) + base64URLEncode(Request Body)))
```

### JOSE Header Example


```json
{
  "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 Bancontact.
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.

## Certificates

Bancontact publishes its public keys in JWKS format:

* **PREPROD JWK**: jwks.preprod.bancontact.net
* **PROD JWK**: jwks.bancontact.net


### Certificate Rotation

* Bancontact 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.