Integrate your POS with
Two API contracts and a step-by-step guide. Your POS receives orders via HMAC-signed webhooks, confirms them via REST, and advances the status until delivery.
API contracts
Languages supported
HMAC-SHA bits
Three resources, one integration
Integrating with BipBip is made up of two complementary API contracts and a step-by-step guide that ties them together.
Webhook spec
BipBip sends every new order to your POS via POST /v1/order/{remoteId}. Verify the HMAC signature and respond with 200 OK.
REST API reference
Your POS calls BipBip to accept, reject, advance the status and query orders. Authenticate with X-Bipbip-Api-Key and send an Idempotency-Key on every mutation.
Integration guide
Step-by-step quickstart with real code in 4 languages, HMAC verification with tested samples, troubleshooting and a complete glossary of contract terms.
Read the guide →Designed for reliable integrations
HMAC-SHA256 signature
Every webhook is signed with HMAC-SHA256 over {timestamp}.{rawBody}. Reject requests older than 5 minutes to block replays.
At-least-once delivery
Every attempt carries the same X-Bipbip-Delivery-Id. Dedupe on that UUID and tolerate retries without creating duplicate orders.
Idempotency-Key required
Send a unique UUID per logical attempt on every REST mutation. 24h cache, safe retries without side effects.
Samples in 4 languages
Node.js, Python, C# and PHP. All use stdlib only — no external dependencies. Copy-paste and go.
Clear state machine
Pending → Accepted → Preparing → Ready → HandedOver. Rejected and Cancelled are terminal. No ambiguity.
Path-based versioning
Everything runs under /v1/. When v2 lands you can run both in parallel while you migrate — no surprise breaking changes.
Verify every webhook with HMAC
BipBip signs every request with HMAC-SHA256 over {timestamp}.{rawBody}. Capture the raw bytes, validate the timestamp (max. 300s skew) and compare in constant time.
- Standard library only — no external dependencies
-
timingSafeEqual/compare_digest/hash_equals - Capture the raw body before
JSON.parse
// HMAC-SHA256 verification — Node.js (built-in crypto) const crypto = require('crypto'); function verifyBipBipSignature(secret, timestamp, rawBody, signature) { // Reject requests older than 5 minutes (replay protection) const now = Math.floor(Date.now() / 1000); if (Math.abs(now - parseInt(timestamp, 10)) > 300) return false; // Sign the RAW body — never JSON.parse + re-serialize const message = `${timestamp}.${rawBody}`; const computed = crypto .createHmac('sha256', secret) .update(message, 'utf8') .digest('hex'); const expected = `sha256=${computed}`; // Timing-safe comparison (never use === on signatures) const a = Buffer.from(expected, 'utf8'); const b = Buffer.from(signature, 'utf8'); if (a.length !== b.length) return false; return crypto.timingSafeEqual(a, b); }
# HMAC-SHA256 verification — Python (stdlib only) import hmac, hashlib, time def verify_bipbip_signature(secret: str, timestamp: str, raw_body: bytes, signature: str) -> bool: # Reject requests older than 5 minutes if abs(int(time.time()) - int(timestamp)) > 300: return False # Build the exact message BipBip signed: "{ts}.{rawBody}" message = f"{timestamp}.".encode("utf-8") + raw_body computed = hmac.new(secret.encode("utf-8"), message, hashlib.sha256).hexdigest() expected = f"sha256={computed}" # Timing-safe comparison return hmac.compare_digest(expected, signature)
// HMAC-SHA256 verification — C# (.NET 6+) using System.Security.Cryptography; using System.Text; public static bool VerifyBipBipSignature(string secret, string timestamp, byte[] rawBody, string signature) { // Reject requests older than 5 minutes var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); if (Math.Abs(now - long.Parse(timestamp)) > 300) return false; var prefix = Encoding.UTF8.GetBytes($"{timestamp}."); var message = prefix.Concat(rawBody).ToArray(); using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret)); var computed = Convert.ToHexString(hmac.ComputeHash(message)).ToLowerInvariant(); var expected = Encoding.UTF8.GetBytes($"sha256={computed}"); var received = Encoding.UTF8.GetBytes(signature); return CryptographicOperations.FixedTimeEquals(expected, received); }
// HMAC-SHA256 verification — PHP 7.2+ function verify_bipbip_signature(string $secret, string $timestamp, string $rawBody, string $signature): bool { // Reject requests older than 5 minutes if (abs(time() - (int)$timestamp) > 300) return false; // Sign the raw body — never re-serialize the parsed JSON $message = $timestamp . '.' . $rawBody; $computed = hash_hmac('sha256', $message, $secret); $expected = 'sha256=' . $computed; // Constant-time comparison to avoid timing oracles return hash_equals($expected, $signature); }
The 4 steps to go live
From "I have my credentials" to "I received and confirmed my first order" without help from the BipBip team.
Implement the webhook
Expose POST /v1/order/{remoteId} on your POS. Capture the raw body before parsing the JSON.
Verify the HMAC signature
Recompute HMAC-SHA256 over {timestamp}.{rawBody} and compare in constant time.
Respond with remoteOrderId
Return HTTP 200 with { "remoteOrderId": "..." }. Without that field BipBip will retry.
Accept via REST API
Call POST /api/v1/Orders/{orderKey}/accept with X-Bipbip-Api-Key and Idempotency-Key.
Before you start
BipBip hands you these during onboarding
- HMAC Secret (one per account)
- API Key (
X-Bipbip-Api-Key) - remoteId (one per store)
- Registered base URL (public)
Ready to integrate your POS with BipBip?
Coordinate with the team to get your credentials and kick off the pilot in production.