Validate Signing Requests
To validate your request, Rabobank applies the following security checks to ensure authenticity and integrity:
- Mutual TLS (mTLS) - The request must be authenticated using an EV SSL certificate.
- HTTP Request Signing - The request is cryptographically signed following the IETF HTTP Signatures draft standard. The request must be signed using a different EV SSL certificate.
- Digest header - A hash of the request body is included, as defined in RFC 3230 to guarantee body integrity..
- OAuth 2.0 - Used to authorize access to the API.
- Rate limits - Applied to ensure fair usage and maintain system stability.
EV SSL Certificates
Rabobank accepts certificates from the certificates issuers in the Mozilla Certificate Report .
- TLS Client Certificate: EV SSL certificate from an accepted CA (RSA ≥ 2048 bits, max validity 1 year).
- Signing Certificate: EV SSL certificate for signing requests.
TLS Certificate
Public
Upload the public part of the TLS certificate (full chain in PEM format) in the Rabobank developer portal under My Organizations → Apps → Configuration → Certificate.
Private
Keep the private key secure in your infrastructure, it is used to set up the mTLS connection.
Signing certificate
Public
The public key should be shared with Rabobank in the Signature-Certificate header of a request.
Private
Keep the private key secure in your infrastructure, it is used for creating the HTTP Signature. Rabobank does not store your signing certificate.
Sandbox vs Production
Rabobank offers two environments: Sandbox for testing and Production for live transactions. These environments have different certificate requirements, domains, and signature. Understanding these distinctions help you plan your move from development to production.
Rate limits can differ for every API and per environment, check our API guides for rate limits per API.
Environment | Certificate | Domain | Signature |
|---|---|---|---|
Sandbox | Any certificate works for mTLS and Signing; Rabobank provides downloadable test sandbox certificates and keys for convenience and testing. TLS Download Example Certificate ** Download Example Private Key ** Signing Download Example Signing Certificate Download Signing Certificate Key | Rabobank servers use EV SSL certificates (e.g., | Requires |
Production | Requires Two valid EV SSL certificates from an accepted CA. One for mTLS, and | Rabobank servers use EV SSL certificates (e.g., | Requires |
Digest and HTTP Signature headers
Digest and HTTP Signature headers are mandatory for all requests and ensure message integrity and authenticity.
You should include the following headers in your request:
- date - Must contain the current HTTP date in RFC 7231 format.
- digest - Hash of the request body using SHA-512 (or SHA-256). For Bulk payments, hash of the request body including the metadata.
- x-request-id - Unique UUID for each request to ensure traceability.
- Signature - Contains the signing string of selected headers using your private key.
- Signature-Certificate - Public certificate stripped of tags and line breaks, used to verify the signature.
Additional headers
This header is additional for PSD2 - Single and Bulk payments:
- tpp-redirect-uri - Mandatory for HTTP POST requests.
Set up the following headers:
Date Header
The date is the HTTP-date in RFC 7231 format.
Mon, 15 Dec 2025 13:39:29 GMT
Digest Header
Digest ensures the request body hasn’t been altered in transit.
Steps:
- Use the exact sequence for the HTTP request body as sent (Do not add any extra spaces or line breaks).
For Bulk payments: Take the body of the request and include the metadata of the file. Example values are present here. - Compute the binary hash using SHA-512 or SHA-256 hashing algorithm.
SHA‑256 and SHA‑512 are two hash functions from the SHA‑2 family. They work the same way but differ mainly in output size, security level, and performance.
Both are considered cryptographically secure for hashing request bodies. They differ mainly in performance and strength depending on the hardware and requirements. - Base64-encode the hash.
- Add the header:
digest: sha-512=<Base64Value>
Example:
An example of the digest header for an empty body using SHA-512:
sha-512=z4PhNX7vuL3xVChQ1m2AB9Yg5AULVxXcg/SpIdNs6c5H0NE8XYXysP+DGNKHfuwvY7kxvUdBeoGlODJ6+SfaPg==X-Request-ID Header
This is a UUID for each request to ensure traceability.
Example:
x-request-id: f9b311bb-b1e7-4ec8-b276-d1c6e38f78dbSignature Header
The Signature header proves the authenticity of your request by signing critical headers with your private key.
Components:
- keyId - The serial number of the certificate (Integer format).
- algorithm - Algorithm used for hashing:
rsa-sha512orrsa-sha256RSA on its own is just a public/private key algorithm. When you create a signature with RSA, you must also choose a hashing algorithm—that’s where RSA‑SHA256 and RSA‑SHA512 come in.
- headers - The list of headers included in the signature.
- signature - The Base64-encoded RSA signature of the signing string.
Steps to build the signature header:
- Retrieve the Certificate Serial Number from the EV SSL certificate and convert it to an integer format:
openssl x509 -in cert.pem -noout -serial | cut -d'=' -f2 | tr -d ':' | awk '{print strtonum("0x"$0)}' - Choose the algorithm, you can use rsa-512 or rsa-256.
- Define the headers:
- All lowercase
- Separated by a space
- In the same order as in the signing string.
headers="date digest x-request-id" - Create the signing string. Concatenate the
Date,DigestandX-Request-IDseparated by line breaks\nto create the signing string. For example:
Optionally, adddate: <current HTTP date> digest: sha-512=<Base64Digest> x-request-id: <uuid>tpp-redirect-uri. - Sign the signing string using:
rsa-sha512orrsa-sha256and your private key.- Base64encode the output. The output should look like this:
Example:signature: keyId="<base64 cert>",algorithm="rsa-sha512",headers="date digest x-request-id",signature="<Base64-signed-string>"
The resulting signature header using our example private key:signature: keyId="1523433508",algorithm="rsa-sha512",headers="date digest x-request-id",signature="aS6D/cKMgEnAES6yVpKs2AjkxbPReF760F8hDHXLZ2ic0OFI84eIjRl2DYLJc4EPjNcsYvxaSyPypJvMnOiU3gnj4vrs/PrR5A/x2COA9fe6OwJThfLTPxeXoRxxw6sGEjRCrF06sY/IKmRPdp4AjVzYfBeAeshjzr/icghp/Zzi4DOOBp+39bdWUJDCVHM9m0V/LRM18xdJtBKssP6Wzy5wncCmk7fHm1nLD31N+SARYcPuMutGHgIwQrNB/czR3e6g7o+2C8J0nC0kPM95VBWAyChTOqPsvcBHKcxreZe9aNywclpVOtXJit05q3O3PfLvJHH3QoPTRpzsP38pOw=="
Signature-Certificate Header
To verify your signature, Rabobank requires you to send your public certificate in a request header.
Steps:
- Take your PEM-encoded certificate.
- Remove the
-----BEGIN CERTIFICATE-----and-----END CERTIFICATE-----tags. - Remove all line breaks so the certificate becomes a single continuous string.
- Add it to the header:
Signature-Certificate: <PEM certificate without tags or line breaks>
Example:
The result with our example certificate should be:
Signature-Certificate: MIIDkDCCAnigAwIBAgIEWs3AJDANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMCTkwxEDAOBgNVBAgMB1V0cmVjaHQxEDAOBgNVBAcMB1V0cmVjaHQxETAPBgNVBAoMCFJhYm9iYW5rMRwwGgYDVQQLDBNPbmxpbmUgVHJhbnNhY3Rpb25zMSUwIwYDVQQDDBxQU0QyIEFQSSBQSSBTZXJ2aWNlcyBTYW5kYm94MB4XDTE4MDQxMTA3NTgyOFoXDTIzMDQxMTA3NTgyOFowgYkxCzAJBgNVBAYTAk5MMRAwDgYDVQQIDAdVdHJlY2h0MRAwDgYDVQQHDAdVdHJlY2h0MREwDwYDVQQKDAhSYWJvYmFuazEcMBoGA1UECwwTT25saW5lIFRyYW5zYWN0aW9uczElMCMGA1UEAwwcUFNEMiBBUEkgUEkgU2VydmljZXMgU2FuZGJveDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANoAjqGWUgCIm2F+0sBSEwLal+T3u+uldLikpxHCB8iL1GD7FrRjcA+MVsxhvHly7vRsHK+tQyMSaeK782RHpY33qxPLc8LmoQLb2EuiQxXj9POYkYBQ74qkrZnvKVlR3WoyQWeDOXnSY2wbNFfkP8ET4ElwyuIIEriwYhab0OIrnnrO8X82/SPZxHwEd3aQjQ6uhiw8paDspJbS5WjEfuwY16KVVUYlhbtAwGjvc6aK0NBm+LH9fMLpAE6gfGZNy0gzMDorVNbkQK1IoAGD8p9ZHdB0F3FwkILEjUiQW6nK+/fKDNJ0TBbpgZUpY8bR460qzxKdeZ1yPDqX2Cjh6fkCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAYL4iD6noMJAt63kDED4RB2mII/lssvHhcxuDpOm3Ims9urubFWEpvV5TgIBAxy9PBinOdjhO1kGJJnYi7F1jv1qnZwTV1JhYbvxv3+vk0jaiu7Ew7G3ASlzruXyMhN6t6jk9MpaWGl5Uw1T+gNRUcWQRR44g3ahQRIS/UHkaV+vcpOa8j186/1X0ULHfbcVQk4LMmJeXqNs8sBAUdKU/c6ssvj8jfJ4SfrurcBhY5UBTOdQOXTPY85aU3iFloerx7Oi9EHewxInOrU5XzqqTz2AQPXezexVeAQxP27lzqCmYC7CFiam6QBr06VebkmnPLfs76n8CDc1cwE6gUl0rMA==Updated about 20 hours ago