Ir al contenido

Firma ECDSA-SHA256

Cada request a la API requiere 4 headers firmados con ECDSA-SHA256 (secp256k1). No hay tokens Bearer ni sesiones.

HeaderDescripciónEjemplo
x-client-idID de tu API Keyrivo_abc123xyz
x-timestampFecha/hora actual ISO 8601 (±5 min)2026-03-18T14:00:00.000Z
x-nonceString único aleatorio por requesta3f9b2c1d8e7...
x-signatureFirma ECDSA-SHA256 en Base64MEYCIQDx...

Construye el siguiente objeto JSON y fírmalo con tu clave privada EC secp256k1:

{
"method": "POST",
"path": "/v1/br/payin/pix/instant",
"query": "",
"body": "{\"amount\":10000,\"amountFormat\":\"cents\",...}",
"timestamp": "2026-03-18T14:00:00.000Z",
"nonce": "a3f9b2c1d8e7f4a1b2c3d4e5f6a7b8c9"
}

Pasos:

  1. Serializa el objeto como JSON (sin espacios extra)
  2. Firma el string con ECDSA-SHA256 usando tu clave privada secp256k1
  3. Encode la firma en Base64 → ese es x-signature

Notas importantes:

  • Si el request no tiene body (GET), "body" va como ""
  • Si el request tiene query params, "query" es el string key=value&key2=value2 sin el ?
const crypto = require('crypto');
function buildHeaders(method, path, query = '', body = '', privateKeyPem, keyId) {
const timestamp = new Date().toISOString();
const nonce = crypto.randomBytes(16).toString('hex');
const signedData = JSON.stringify({ method, path, query, body, timestamp, nonce });
const signature = crypto.sign('SHA256', Buffer.from(signedData), privateKeyPem).toString('base64');
return {
'Content-Type': 'application/json',
'x-client-id': keyId,
'x-timestamp': timestamp,
'x-nonce': nonce,
'x-signature': signature,
};
}
import hashlib
import hmac
import json
import os
import secrets
from datetime import datetime, timezone
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec
def build_headers(method, path, query='', body='', private_key_pem=None, key_id=None):
timestamp = datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z')
nonce = secrets.token_hex(16)
signed_data = json.dumps({
'method': method,
'path': path,
'query': query,
'body': body,
'timestamp': timestamp,
'nonce': nonce
}, separators=(',', ':'))
private_key = serialization.load_pem_private_key(private_key_pem, password=None)
signature = private_key.sign(signed_data.encode(), ec.ECDSA(hashes.SHA256()))
signature_b64 = __import__('base64').b64encode(signature).decode()
return {
'Content-Type': 'application/json',
'x-client-id': key_id,
'x-timestamp': timestamp,
'x-nonce': nonce,
'x-signature': signature_b64,
}
Ventana de terminal
# Variables
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
NONCE=$(openssl rand -hex 16)
KEY_ID="rivo_abc123xyz"
BODY='{"amount":10000,"amountFormat":"cents","amountType":"fixed","expirationInSeconds":3600}'
# Construir el string a firmar
SIGNED_DATA=$(printf '{"method":"POST","path":"/v1/br/payin/pix/instant","query":"","body":"%s","timestamp":"%s","nonce":"%s"}' \
"$(echo $BODY | sed 's/"/\\"/g')" "$TIMESTAMP" "$NONCE")
# Firmar con clave privada
SIGNATURE=$(echo -n "$SIGNED_DATA" | openssl dgst -sha256 -sign private.pem | base64 | tr -d '\n')
# Hacer el request
curl -X POST https://api.rivoplay.com/v1/br/payin/pix/instant \
-H "Content-Type: application/json" \
-H "x-client-id: $KEY_ID" \
-H "x-timestamp: $TIMESTAMP" \
-H "x-nonce: $NONCE" \
-H "x-signature: $SIGNATURE" \
-d "$BODY"