Authentication
Overview
Section titled “Overview”All communication between Beexar and your operator server is authenticated using HMAC-SHA256 signatures. Every request includes an X-REQUEST-SIGN header containing a hex-encoded signature of the request body.
| Component | Description |
|---|---|
Operator slug (casino_id) | Identifies your operator account. Sent in game launch requests. |
API Secret (AUTH_TOKEN) | Secret key used to compute HMAC-SHA256 signatures. Never expose this publicly. |
| X-REQUEST-SIGN | HTTP header containing the HMAC-SHA256 signature (hex-encoded, 64 characters). |
How Signing Works
Section titled “How Signing Works”signature = HMAC-SHA256(request_body, AUTH_TOKEN)- Take the raw request body (the exact JSON bytes)
- Compute HMAC-SHA256 using your
AUTH_TOKEN(API secret) as the key - Hex-encode the result
- Send it in the
X-REQUEST-SIGNheader
Validating Signatures (Incoming Requests)
Section titled “Validating Signatures (Incoming Requests)”When Beexar sends requests to your wallet endpoints (/balance, /betwin, /rollback, /finish), validate the X-REQUEST-SIGN header. If the signature does not match, respond with HTTP 400 and api_code 403 (the SoftSwiss error format — see Wallet API Overview):
const crypto = require('crypto');
function validateSignature(body, signature, apiSecret) { const expected = crypto .createHmac('sha256', apiSecret) .update(body, 'utf8') .digest('hex'); return crypto.timingSafeEqual( Buffer.from(expected, 'hex'), Buffer.from(signature, 'hex') );}
// Express middlewareapp.use('/wallet', (req, res, next) => { const signature = req.headers['x-request-sign']; const rawBody = req.rawBody; // ensure raw body is preserved if (!validateSignature(rawBody, signature, process.env.AUTH_TOKEN)) { return res.status(400).json({ code: 'invalid_argument', msg: 'Invalid signature', meta: { api_code: '403', api_message: 'Invalid signature' }, }); } next();});import hmacimport hashlib
def validate_signature(body: bytes, signature: str, auth_token: str) -> bool: expected = hmac.new( auth_token.encode('utf-8'), body, hashlib.sha256 ).hexdigest() return hmac.compare_digest(expected, signature)
# Flask examplefrom flask import Flask, request, jsonify
app = Flask(__name__)
@app.before_requestdef verify_signature(): signature = request.headers.get('X-REQUEST-SIGN', '') if not validate_signature(request.data, signature, AUTH_TOKEN): return jsonify( code='invalid_argument', msg='Invalid signature', meta={'api_code': '403', 'api_message': 'Invalid signature'}, ), 400package wallet
import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "io" "net/http")
func ValidateSignature(body []byte, signature, authToken string) bool { mac := hmac.New(sha256.New, []byte(authToken)) mac.Write(body) expected := hex.EncodeToString(mac.Sum(nil)) return hmac.Equal([]byte(expected), []byte(signature))}
// HTTP middlewarefunc SignatureMiddleware(authToken string) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { body, _ := io.ReadAll(r.Body) signature := r.Header.Get("X-REQUEST-SIGN") if !ValidateSignature(body, signature, authToken) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) // 400, Twirp invalid_argument _, _ = w.Write([]byte(`{"code":"invalid_argument","msg":"Invalid signature","meta":{"api_code":"403","api_message":"Invalid signature"}}`)) return } // Re-set body for downstream handlers r.Body = io.NopCloser(bytes.NewReader(body)) next.ServeHTTP(w, r) }) }}<?php
function validateSignature(string $body, string $signature, string $authToken): bool { $expected = hash_hmac('sha256', $body, $authToken); return hash_equals($expected, $signature);}
// Usage$body = file_get_contents('php://input');$signature = $_SERVER['HTTP_X_REQUEST_SIGN'] ?? '';
if (!validateSignature($body, $signature, $authToken)) { http_response_code(400); echo json_encode([ 'code' => 'invalid_argument', 'msg' => 'Invalid signature', 'meta' => ['api_code' => '403', 'api_message' => 'Invalid signature'], ]); exit;}using System.Security.Cryptography;using System.Text;
public static class SignatureValidator{ public static bool Validate(string body, string signature, string authToken) { using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(authToken)); var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(body)); var expected = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); return CryptographicOperations.FixedTimeEquals( Encoding.UTF8.GetBytes(expected), Encoding.UTF8.GetBytes(signature) ); }}
// ASP.NET Core middlewareapp.Use(async (context, next) =>{ context.Request.EnableBuffering(); using var reader = new StreamReader(context.Request.Body, leaveOpen: true); var body = await reader.ReadToEndAsync(); context.Request.Body.Position = 0;
var signature = context.Request.Headers["X-REQUEST-SIGN"].ToString(); if (!SignatureValidator.Validate(body, signature, authToken)) { context.Response.StatusCode = 400; await context.Response.WriteAsJsonAsync(new { code = "invalid_argument", msg = "Invalid signature", meta = new { api_code = "403", api_message = "Invalid signature" }, }); return; } await next();});require 'openssl'
def validate_signature(body, signature, auth_token) expected = OpenSSL::HMAC.hexdigest('sha256', auth_token, body) Rack::Utils.secure_compare(expected, signature)end
# Sinatra examplebefore '/wallet/*' do body = request.body.read signature = request.env['HTTP_X_REQUEST_SIGN'] || '' unless validate_signature(body, signature, ENV['AUTH_TOKEN']) halt 400, { 'Content-Type' => 'application/json' }, '{"code":"invalid_argument","msg":"Invalid signature","meta":{"api_code":"403","api_message":"Invalid signature"}}' end request.body.rewindendSigning Requests (Outgoing)
Section titled “Signing Requests (Outgoing)”When you send requests to the Beexar Gateway API (e.g., POST /api/v1/softswiss/launcher/real), you must sign the request body and include the signature in the X-REQUEST-SIGN header.
# Example: signing a launch requestBODY='{"casino_id":"your-operator-slug","game":"dice","account":{"id":"player_1","currency":"USD"},"locale":"en","urls":{"return_url":"https://casino.example.com"}}'SIGNATURE=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "your_auth_token" | awk '{print $2}')
curl -X POST https://gateway.beexar.com/api/v1/softswiss/launcher/real \ -H "Content-Type: application/json" \ -H "X-REQUEST-SIGN: $SIGNATURE" \ -d "$BODY"Security Best Practices
Section titled “Security Best Practices”- Never expose
AUTH_TOKENin client-side code, logs, or version control - Use timing-safe comparison when validating signatures (see code samples above)
- Validate every request — reject any request with missing or invalid
X-REQUEST-SIGN - Use HTTPS for all callback URLs — Beexar will not send requests to plain HTTP endpoints
- Rotate keys periodically — contact your account manager to rotate API credentials