Skip to main content
Before calling any API, you must sign requests and validate response signatures to ensure message security and integrity.

Request Signing Process

Step 1: Prepare Your Private Key

Ensure your private key is ready. It must be a 2048-bit RSA key.
// Load private key from environment or secure storage
const privateKey = process.env.REBELL_PRIVATE_KEY;
// Or from file
const privateKey = fs.readFileSync('private_key.pem', 'utf-8');
from cryptography.hazmat.primitives import serialization

# Load private key
with open('private_key.pem', 'rb') as f:
    private_key = serialization.load_pem_private_key(f.read(), password=None)

Step 2: Construct Content to Sign

Build a string combining the HTTP method, URI, client identifier, timestamp, and request body:
<HTTP_METHOD> <HTTP_URI>
<Client-Id>.<Request-Time>.<HTTP_BODY>
Components:
ComponentDescriptionExample
HTTP_METHODThe HTTP methodPOST
HTTP_URIThe API endpoint path/api/open/v2/payments/pay
Client-IdYour assigned client IDTEST_5X00000000000000
Request-TimeISO 8601 timestamp2024-01-10T12:12:12+01:00
HTTP_BODYJSON request body{"paymentRequestId":"..."}
Example content to sign:
POST /api/open/v2/payments/pay
TEST_5X00000000000000.2024-01-10T12:12:12+01:00.{"paymentRequestId":"REQ_001","paymentAmount":{"currency":"EUR","value":"1000"}}

Step 3: Generate Signature

Apply RSA with SHA-256 algorithm to generate the signature:
const crypto = require('crypto');

function generateSignature(contentToSign, privateKey) {
  const signer = crypto.createSign('RSA-SHA256');
  signer.update(contentToSign);
  const signature = signer.sign(privateKey, 'base64');
  return signature;
}

// Build content to sign
const method = 'POST';
const uri = '/api/open/v2/payments/pay';
const clientId = 'YOUR_CLIENT_ID';
const requestTime = new Date().toISOString();
const body = JSON.stringify(requestBody);

const contentToSign = `${method} ${uri}\n${clientId}.${requestTime}.${body}`;
const signature = generateSignature(contentToSign, privateKey);

Step 4: Add Signature to Header

Format and add the signature header to your request:
Signature: algorithm=RSA256, keyVersion=1, signature=<generated_signature>
FieldDescription
algorithmAlways RSA256
keyVersionYour key version (provided during onboarding)
signatureBase64-encoded signature from Step 3

Complete Request Example

curl -X POST https://api.rebellapp.com/api/open/v2/payments/pay \
  -H 'Content-Type: application/json' \
  -H 'Client-Id: TEST_5X00000000000000' \
  -H 'Request-Time: 2024-01-10T12:12:12+01:00' \
  -H 'Signature: algorithm=RSA256, keyVersion=1, signature=BASE64_SIGNATURE_HERE' \
  -d '{
    "paymentRequestId": "REQ_001",
    "paymentAmount": {
      "currency": "EUR",
      "value": "1000"
    }
  }'

Response Signature Validation

Always verify the response signature before processing the data.

Construct Content to Validate

Mirror the request signing process using response data:
<HTTP_METHOD> <HTTP_URI>
<Client-Id>.<Response-Time>.<HTTP_BODY>

Verify Signature

function verifySignature(method, uri, clientId, responseTime, body, signature, publicKey) {
  const contentToVerify = `${method} ${uri}\n${clientId}.${responseTime}.${body}`;

  const verifier = crypto.createVerify('RSA-SHA256');
  verifier.update(contentToVerify);

  return verifier.verify(publicKey, signature, 'base64');
}

// Usage
const isValid = verifySignature(
  'POST',
  '/api/open/v2/payments/pay',
  clientId,
  response.headers['response-time'],
  JSON.stringify(response.body),
  extractSignature(response.headers['signature']),
  rebellPublicKey
);

if (!isValid) {
  throw new Error('Invalid response signature');
}

Key Points

Security Alert: Never log or expose the full signature content or private key. If you need to debug signature issues, log only non-sensitive parts like the method and URI.