Developer

Partner Docs

Merchant Docs

Request Field Level Encryption

Field Level Encryption (FLE), when enabled is a security feature that ensures sensitive data is protected when transmitted to Banked's APIs. This feature is particularly important for handling personal and financial information, providing an additional layer of security beyond standard TLS encryption.

FLE provides end-to-end encryption for sensitive data, ensuring it remains protected even when passing through third-party services.

Overview

The process involves:

  1. Fetch Banked's public keys from the https://api.banked.com/.well-known/jwks.json JWKS endpoint
  2. Prefix the sensitive field names with encrypted_
  3. Encrypt sensitive data field values before sending requests

Implementation Steps

Step 1. Get Banked's Public Keys

Using your API credentials in the Authrozation header field, fetch the public keys for encryption via a JWKS (JSON Web Key Set) endpoint:

http
GET https://api.banked.com/.well-known/jwks.json

It's mandatory to use include your API authorisation in the Authorization header field otherwise you won't get optimised keys for your regional location.

Response Format

json
{
    "keys": [
        {
            "kty": "RSA",
            "use": "enc",
            "alg": "RSA-OAEP-256",
            "kid": "4aeb1209-f09d-4d0d-90d0-488ac948fecc.1",
            "n": "n758mvJETwhB2v28yRsmXOGsjM9z1nbEcm8eyCtdR68laYuQB3XfbaGaQZN-MvV1RMx04tEvGJxux3Jm296G3XsWkWD2d4tvhN4EmSDcEIswv7h1YWScAvhCARmiH1LCXZFECpSluLiIF-xPom4bWi5koLApzT7Eh5b7NB-8m6uctrTBlLfWRtyX5MrAc8LhzBWLOC7zhw8k7dtbp2YYmYPDvco8NE5CKjT0ym6sSA2hW364HoxN_hbsI5BnrlzFjyUjb-XGDQbM10R1ItnEzSpiRLijdwR2Xzqs7AeSwK3s5H_jgLaVa3l9b-c7U470lZZoM7gNJVrqNptz-8FRj4nW3WfPfm8X8Q_ew_0ijkB69zwPdWX9cgAjIw60MjMM9M-lbbJvtghdfwbFYKiVzNmYDmOb3Jgp7VMmiIhIA9kLdsa0qRvwF6Zh5ur2uS_AU1Qnu7bkl__pDbQr2DCKGceIknj_xreo9m32qGghd5sfJRDHWLnOZKlE1_JI54tp",
            "e": "AQAB",
            "bnkd.iat": 1738665189,
            "bnkd.exp": 1773052389,
            "bnkd.test": true,
            "bnkd.region": "au"
        }
    ]
}

The response will contain the following properties:

  • kty - Key Type
  • use - “enc” indicates that a key can be used for encryption
  • alg - indicates the type of encryption algorithm to be used
  • kid - This is the unique Key ID which will be a RFC 4122 version 4 UUID plus the version number of the key with a . separating each component, for example: 04ff9caf-9696-4d9f-adf5-d678ff408755.1 where 42 04ff9caf-9696-4d9f-adf5-d678ff408755 is the V4 UUID and 1 is the version of the key. This is used by Banked to validate and decrypt the content encrypted with this key.
  • n - Public Key Modulus - https://www.rfc-editor.org/rfc/rfc7518.html#section-6.3.1.1
  • e - Public Key Exponent - https://www.rfc-editor.org/rfc/rfc7518.html#section-6.3.1.2
  • bknd.iat - The date/time the key was issued at. This will be a RFC3339 Unix timestamp.
  • bknd.exp - The expected expiry time of the key. This will be a RFC3339 Unix timestamp.

Step 2. Encrypt Sensitive Data

  1. Identify fields requiring encryption (see Fields Requiring Encryption)
  2. Encrypt each sensitive field.
  3. Prefix encrypted field names with encrypted_. For example the source bank account JSON field name becomes encrypted_source

Encrypted fields follow JOSE specifications with RSA-OEAP-256 (3072 bit RSA key, OEAP Padding - SHA256 Digest) and AES 256 GCM. The KeyID (kid, returned in the /.well-known/jwks.jso API response) must also be used as a JWE-protected header so Banked know which Private key to use for decryption. The kid can be retrieved from the JWKS.

The encrypted field value must be a JWE in compact format. The structure being five parts which are separated by dots (.): BASE64URL(JWE Header). BASE64URL(Encrypted Key) . BASE64URL(Initialization Vector) . BASE64URL(Ciphertext) . BASE64URL(Authentication Tag)

Example Request

json
// Original
{
 "source": 
    {
        "account_type" : "plain_bank_account",
        "account_identifier": {
            "identifier_type": "BSBAccountNumber",
            "bsb": "111114",
            "account_number": "010111"
        },
        "account_owner_name": "John Smith"
    }
}

// Encrypted
{
  "encrypted_source": "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwia2..."
}

Key Rotation

To ensure continuous operation, your system must support key rotation. This covers both our periodic scheduled rotations for keys which are about to expire and any urgent, unforeseen rotations.

For Scheduled Rotations:
Our key expiry dates are published in the bnkd.iat field on our well-known/jwks endpoint. Please implement a mechanism to retrieve the new public keys before the current keys expire. There are two methods to do this:

  1. Look at the expiry date and retrieve the new keys at least one day before the old keys expire or
  2. Simply retrieve the keys every day and cache them. This way you will get the most recent keys as soon as they are published. This option might easier to implement and test as it means you don't need to worry about adding functionality based on the expiry date.

For Unforeseen Rotations:
In extremely rare cases, Banked may need to rotate a key before its scheduled expiration. To make your code resilient to these events, we will signal this by returning an HTTP 422 error with a source field of encryption key and a code field of invalid.
Upon receiving this specific error, your system should automatically reload the Banked public keys and then retry the API call that failed.

Notes:

  1. The new keys are always located at index position zero in the keys JSON array from our well-known/jwks endpoint.
  2. Remember to include your API credentials in the Authorization header when retrieving keys to make sure you retrieve the correct key.

API Reference

Request Fields Which Support Encryption

Payment Sessions API

EndpointFieldSensitivity
POST /v2/payment_sessionspayeehigh
POST /v2/payment_sessionspayerhigh
POST /v2/payment_sessionsmandatehigh

Mandates API

EndpointFieldSensitivity
POST /v2/mandatessourcehigh
POST /v2/mandatesdestinationhigh
POST /v2/mandatesactions.#.sourcehigh

Error Responses

Invalid Encryption Key

http
HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
    "errors": [
        {
            "code": "invalid",
            "source": "encryption key",
            "title": "invalid encryption key"
        }
    ]
}

When receiving this error, fetch a new key from the JWKS endpoint using API credentials in the Authorization header field, re-encrypt your payload, and submit a new request.

Code Examples

Please see the example Javascript code that can be used to generate the JWE for adding to encrypted field/s. Please note that this code is provided as an example and is not designed for production use.

javascript
import pkg from 'node-jose';
const {JWE} = pkg;
const payload = `{
"account_type" : "plain_bank_account",
"account_identifier": {
"identifier_type": "BSBAccountNumber",
"account_number": "123456789",
"bsb": "123456"
},
"account_owner_name": "John Smith"
}`;
var jwksUrl = 'https://api.banked.com/.well-known/jwks.json';
var jwks = await fetch(jwksUrl, {
    headers: {
        'Authorization': `<Basic or Bearer> <Auth Token>`
    }
}).then(response => response.json());
var key = jwks.keys[0];
let encrypted = await JWE.createEncrypt({format: 'compact', fields: {alg: 'RSA-OAEP-256', enc: 'A256GCM'}}, key).update(payload).final();
console.log(encrypted);

Note: The new keys are always located at position index zero in the keys JSON array from our well-known/jwks endpoint.

Best Practices

  1. Generate new CEK for each sensitive data object
  2. Do not reuse CEKs between requests
  3. Cache public keys and refresh before expiry
  4. Handle key rotation gracefully
  5. Implement proper error handling for encryption/decryption failures

© 2025 Banked Ltd.

Dark Theme
PrivacyTerms