Skip to content

Security & Privacy

Velo takes a defense-in-depth approach to API security. This page consolidates all security requirements for operators integrating with the Velo platform.

Transport Security

All API communication must use TLS 1.2 or higher. Plain HTTP connections are rejected at the gateway.

RequirementStandard
ProtocolHTTPS only (TLS 1.2+)
CertificateValid CA-signed certificate
Cipher suitesModern AEAD ciphers (AES-256-GCM, ChaCha20-Poly1305)

HMAC-SHA256 Authentication

Every wallet callback includes an X-Sign header containing an HMAC-SHA256 signature of the request body. Operators must verify this signature to ensure request authenticity.

Wallet Callbacks (RGS → Operator)

X-Sign = HMAC-SHA256(API_SECRET, request_body_json)

Your server must:

  1. Read the raw request body before JSON parsing
  2. Compute HMAC-SHA256(your_api_secret, raw_body)
  3. Compare the result to the X-Sign header using a constant-time comparison
  4. Reject the request if they don't match

Game Launch (Operator → RGS)

signature = HMAC-SHA256(API_SECRET, "api_key|player_id|timestamp")

Reconciliation & History (Operator → RGS)

signature = HMAC-SHA256(API_SECRET, "api_key|round_id|timestamp")

Timestamp Replay Protection

All HMAC-authenticated endpoints enforce a ±5 minute timestamp window. Requests with stale timestamps are rejected with TIMESTAMP_EXPIRED.

ParameterValue
Maximum clock drift5 minutes
Error codeTIMESTAMP_EXPIRED
HTTP status401 Unauthorized

TIP

Synchronize your server clock with NTP to avoid false rejections. The timestamp is a Unix epoch second (not milliseconds).

Idempotency

Every financial transaction carries a unique transaction_id (UUID v4). The RGS uses this as an idempotency key:

  • If a duplicate transaction_id is received, the server returns the original response without re-processing
  • The transaction_id remains stable across retries — never regenerate it
  • This prevents double-debits and double-credits in network failure scenarios
Timeout → Retry with SAME transaction_id → Server returns original result

Exponential Backoff with Jitter

The RGS retries failed wallet requests using exponential backoff with randomized jitter:

WaitTime = min(MaxWaitTime, BaseInterval × 2^retryAttempt × Jitter)
Jitter = random(0.85 ... 1.15)
ParameterStandard RetryCritical Retry
Max retries310
Base interval200ms500ms
Max wait1.6s30s
Operationsdebit, authenticate, balancecredit, rollback, end_round

Why jitter? If a server briefly goes offline, all connected clients retry at the same intervals → the server is overwhelmed on recovery (thundering herd). Jitter randomizes the retry timing to smooth the recovery curve.

4xx errors are never retried — these indicate logical errors (insufficient funds, invalid token), not transient failures.

Data Minimization

The Velo API transmits only pseudonymous identifiers:

DataFormatPII Risk
Player identityUUID player_idNone — operator-assigned hash
UsernamesProvided by operator in auth responseOperator-controlled
Financial dataAmounts only — no card/bank detailsNone
IP addressesNot logged by RGSNone

No player names, emails, physical addresses, or payment details pass through the Velo API. GDPR and CCPA compliance burden is minimized by design.

Session Security

PropertyValue
Session TTL1 hour
Session tokenGenerated at game launch, validated on every wallet call
Token formatOpaque string (UUID-like)
InvalidationAutomatic on timeout, explicit on session close

Sessions are created via the Game Launch API and linked to a specific player + operator pair. The session_token is passed on every wallet callback, allowing operators to validate that the request corresponds to an active session.

Operator Security Checklist

  • [ ] Verify X-Sign HMAC on every wallet callback (constant-time comparison)
  • [ ] Validate timestamp freshness (reject if >5 minutes old)
  • [ ] Store API_SECRET in a secure vault (not in code or config files)
  • [ ] Enforce HTTPS (TLS 1.2+) on all wallet endpoints
  • [ ] Implement idempotency on transaction_id (return original result on duplicates)
  • [ ] Validate session_token on debit/credit/rollback
  • [ ] Set response timeout < 2 seconds
  • [ ] Handle INSUFFICIENT_FUNDS on funded accounts (sandbox test scenario)
  • [ ] Never log API_SECRET or raw HMAC signatures
  • [ ] Rotate API credentials periodically

B2B Integration Documentation