Developer

Partner Docs

Merchant Docs

Request Signatures

Request signing adds an extra layer of security to your API calls, ensuring that requests haven't been tampered with in transit. Request signing is currently optional for all endpoints.

Banked supports request signing using RSA private keys. Here's how to implement it step by step.

Overview

The process involves:

  1. Generate an RSA key pair
  2. Share your public key with Banked
  3. Sign each request using your private key
  4. Send the signature in your request headers
  5. Troubleshoot any signature validation errors

Prerequisites:

  • Valid Banked account with API access
  • OpenSSL or SSH keygen available for key generation
  • Email access to contact Banked support
  • Development environment with cryptographic libraries
  • Understanding of RSA signatures and JWS (JSON Web Signatures)

Let's walk through each step.

Implementation Steps


Step 1. Generating RSA Key Pair

You can generate the key pair using any method that suits your environment. Banked supports any RSA key length, though we recommend following NIST guidelines with a minimum key length of 2048 bits.

Here is an example approach:

Using OpenSSL (recommended):

bash
# Generate private key (2048-bit minimum, 4096-bit recommended)
openssl genrsa -out private_key.pem 4096

# Extract public key
openssl rsa -in private_key.pem -RSAPublicKey_out -out public_key.pem

Using SSH keygen:

bash
ssh-keygen -t rsa -b 4096 -m PEM -f banked_key

Store your private key securely and never share it. Only the public key gets shared with Banked.


Step 2. Share Your Public Key with Banked

Email your public key to support@banked.com with the following details:

Email template:

json
Subject: Public Key for Request Signing - [Your Company Name]

Hi Banked Team,

Please add the attached public key for request signing on our account.

Account details:
- Company: [Your Company Name]
- Account ID: [Your Account ID if known]

The public key is in PKCS#1 PEM format as required.

Thanks,
[Your Name]

Requirement: The public key must be in PKCS#1 PEM format.

What PKCS#1 PEM format looks like:

json
-----BEGIN RSA PUBLIC KEY-----
MIICCgKCAgEA...
[base64 encoded key data]
...
-----END RSA PUBLIC KEY-----

Step 3. Generate Request Signatures

Each request must be signed using JWS with PS512.

What Gets Signed

The signed string is a concatenation of these components in this exact order:

text
request_url_with_query_params + request_method + request_body + idempotency_key_value

Important: No separators between components - they are concatenated directly.

Signature Formula

text
base64_encode(JWS_PS512_Sign(request_url_with_query_params + request_method + request_body + idempotency_header))

The resulting JWS is then base64-encoded. We expect the compact form JWS to be base64 encoded.

Examples

Example: GET Request

For the following request:

bash
curl --request GET \
     --url https://api.banked.com/v2/payments/?mode=live \
     --header 'X-Banked-Idempotency-Key: 1'

Signed string is:

text
"https://api.banked.com/v2/payments/?mode=liveGET1"

Example: POST Request

For the following request:

bash
curl --request POST \
     --url https://api.banked.com/v2/payments/?mode=live \
     --header 'X-Banked-Idempotency-Key: 1' \
     --data-raw '{"k":"v"}'

Signed string is:

text
"https://api.banked.com/v2/payments/?mode=livePOST{\"k\":\"v\"}1"

Step 4. Send the Request with Signature

Include the base64-encoded signature in the Signature HTTP header:

text
Signature: <base64_signature>

Complete example using the GET request from Step 3:

bash
curl --request GET \
     --url https://api.banked.com/v2/payments/?mode=live \
     --header 'X-Banked-Idempotency-Key: 1' \
     --header 'Signature: eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9...'

Complete example using the POST request from Step 3:

bash
curl --request POST \
     --url https://api.banked.com/v2/payments/?mode=live \
     --header 'X-Banked-Idempotency-Key: 1' \
     --header 'Signature: eyJhbGciOiJQUzUxMiIsInR5cCI6IkpXVCJ9...' \
     --data-raw '{"k":"v"}'

The signature value shown is truncated for readability. Your actual signature will be much longer.

Step 5. Troubleshooting Signature Issues

When implementing request signing, you might encounter validation errors. Here's how to handle and debug them:

Common Error Response

If signature validation fails, the Banked API responds with:

  • HTTP Status: 401 Unauthorized
  • Response Body:
json
{
  "errors": [
    {
      "code": "unauthorized",
      "source": {
        "parameter": "invalid"
      },
      "title": "Request Verification Failed"
    }
  ]
}

Debugging Checklist

If you receive this error, check the following:

1. String Construction

  • [ ] URL includes query parameters exactly as sent
  • [ ] HTTP method is uppercase (GET, POST, etc.)
  • [ ] Request body matches exactly (including whitespace)
  • [ ] Idempotency key value is correct
  • [ ] No separators between concatenated components

2. Signature Generation

  • [ ] Using JWS with PS512 algorithm
  • [ ] Private key is valid RSA format
  • [ ] JWS is in compact form
  • [ ] Final result is base64 encoded

3. Request Headers

  • [ ] Signature header contains the base64-encoded JWS
  • [ ] X-Banked-Idempotency-Key header matches the value used in signing
  • [ ] No extra whitespace in header values

Testing Your Implementation

Start with a simple GET request to verify your signing logic:

bash
# Test with minimal GET request
curl --request GET \
     --url https://api.banked.com/v2/payments/ \
     --header 'X-Banked-Idempotency-Key: test123' \
     --header 'Signature: [your_generated_signature]' \
     --verbose

Use --verbose flag to see the exact request headers being sent.


Code Examples

Go Implementation

Here's a complete Go example that demonstrates the full signing process:

go
package main

import (
    "crypto/rand"
    "crypto/rsa"
    "encoding/base64"
    "fmt"

    "github.com/lestrrat-go/jwx/v2/jwa"
    "github.com/lestrrat-go/jwx/v2/jws"
)

func main() {
	privateKey, err := rsa.GenerateKey(rand.Reader, 4096)
	if err != nil {
		panic(err)
	}

	msg := []byte("string to sign")

	jws, err := jws.Sign([]byte(msg), jws.WithKey(jwa.PS512, privateKey))
	if err != nil {
		panic(err)
	}

	fmt.Println(base64.StdEncoding.EncodeToString(jws))
}


Signing Key Rotation

API Clients are responsible for managing their key lifecycles. To rotate keys:

  1. Generate a new RSA key pair
  2. Share the new public key with Banked via support@banked.com
  3. Wait for confirmation that both keys are active
  4. Switch your application to use the new private key
  5. Notify Banked to deprecate the old key

Banked temporarily supports both old and new keys during the transition period to ensure zero downtime.

© 2025 Banked Ltd.

Dark Theme
PrivacyTerms