Initialize payment
Initialize a payment transaction with HMAC signature verification and idempotency protection.
🔐 HMAC Signing (REQUIRED)
All payment initialization requests MUST include HMAC-SHA256 signature:
- Generate Timestamp: Get current Unix timestamp in seconds
- Create Payload: Concatenate
timestamp + "." + JSON_body - Sign Payload:
HMAC-SHA256(hmac_secret, payload)→ base64 encode - Include Headers:
X-Timestamp: Unix timestamp (must be within 5 minutes)X-Signature: Base64-encoded HMAC signatureIdempotency-Key: Unique key to prevent duplicate payments
🔄 Idempotency Protection (REQUIRED)
Include Idempotency-Key header to prevent duplicate payment initialization.
If the same key is used, the original payment initialization is returned.
- Recommended format:
payment-{timestamp}-{random} - Must be unique per payment attempt
- Prevents duplicate charges on network retries
- Returns existing payment if key already used
🛡️ Amount validation (anti-tampering)
When you pass an order_id, the server validates amount against that order’s authoritative
total — a amount that doesn’t match the order total is rejected with 400 amount_mismatch.
The order total was itself validated against the catalog + the shopper’s real promotions/gift card
at order creation (see the order endpoint’s server-side price validation), so you cannot charge
less than the order is worth. Pass the order’s real total_amount; don’t compute or alter it
client-side.
Provider-Specific Flows:
Stripe (redirect):
- Initialize payment with amount, currency, email
- Redirect customer to
checkout_url - Customer completes payment on Stripe
- Stripe redirects to success/cancel URL
- Verify payment status with
/v1/payments/verify
PayPal (popup):
- Initialize payment with amount and currency
- Use the returned
client_idandpaypal_order_idto render the PayPal Buttons popup in your frontend - Customer approves the payment in the PayPal window
- Verify payment status with
/v1/payments/verify— this captures the approved order
Paystack (popup):
- Initialize payment with amount, currency, email
- Use returned
public_keyandreferenceto open Paystack popup - Customer completes payment in popup
- Verify payment status with
/v1/payments/verify
M-Pesa (STK Push):
- Initialize payment with amount and phone (254XXXXXXXXX format)
- Customer receives STK Push prompt on their phone
- Customer enters M-Pesa PIN
- Verify payment status with
/v1/payments/verify
Security Notes:
- HMAC secret is displayed in the Integrations page (Developer section)
- Never expose HMAC secret in client-side code
- Regenerate secret immediately if compromised
- Requests with invalid/missing signatures return 401 Unauthorized
- Timestamps older than 5 minutes are rejected (prevents replay attacks)
Rate Limiting:
- Additional 100 requests/hour limit for payment initialization
- Separate from global API rate limits
Key Type Support:
- ✅ Secret keys (full access)
- ❌ Publishable keys (forbidden - returns 403)
Authorizations
API Key Authentication
Use your API key in the Authorization header:
Key Types:
Secret Keys (Server-Side Only):
- Format:
tybrite_sk_live_*(production) ortybrite_sk_test_*(sandbox) - Full read/write access to all endpoints
- ⚠️ NEVER expose in client-side code or public repositories
- Required for: write operations, authentication, payment verification, AI recommendations
Publishable Keys (Client-Safe):
- Format:
tybrite_pk_live_*(production) ortybrite_pk_test_*(sandbox) - Read-only access (GET requests only, plus POST semantic search)
- ✅ Safe for client-side JavaScript, mobile apps, and public code
- Allowed for: browsing products, search, CMS content, pricing queries
Endpoint-Specific Requirements:
- Authentication endpoints (
/v1/auth/*): Secret key required - Payment verification (
POST /v1/payments/verify): Secret key required - AI Recommendations (
POST /v1/recommendations): Secret key required - Semantic Search (
POST /v1/search): Both key types allowed (read-only operation) - All write operations: Secret key required
- All read operations: Both key types allowed
Using a publishable key for restricted operations returns 403 Forbidden.
Headers
Unique key to prevent duplicate payment initialization (e.g., payment-{timestamp}-{random}). If you retry a request with the same key, the original payment initialization is returned.
Unix timestamp in seconds (current time). Must be within 5 minutes of server time. Used to prevent replay attacks.
HMAC-SHA256 signature of the payload (timestamp + "." + request_body), base64-encoded. Sign using your HMAC secret from the Integrations page (Developer section).
Body
Payment provider to use
stripe, paypal, paystack, mpesa "stripe"
Payment amount (must be greater than 0)
x >= 0.01100
Currency code (ISO 4217). Required for Stripe and Paystack.
- Stripe: Defaults to store's default currency
- PayPal: Defaults to store's default currency
- Paystack: Must be one of NGN, GHS, ZAR, KES, USD
- M-Pesa: Always KES (ignored)
"usd"
Customer email (required for Stripe and Paystack)
Customer phone number (required for M-Pesa)
- M-Pesa: Format 254XXXXXXXXX (Kenya)
"254712345678"
Optional order ID to link payment to an order
"880e8400-e29b-41d4-a716-446655440003"
Optional idempotency key to prevent duplicate payments
"pay-2026-02-10-abc123"
Optional metadata to attach to the payment
Redirect URL after successful payment (Stripe only)
"https://example.com/payment-success"
Redirect URL after cancelled payment (Stripe only)
"https://example.com/payment-cancelled"
Webhook callback URL (Paystack only)
"https://example.com/webhooks/paystack"
Response
Payment initialized successfully
- Option 1
- Option 2
- Option 3
- Option 4
true
"stripe"
"redirect"
"PAY-12345678-ABC123"
"https://checkout.stripe.com/c/pay/..."
"cs_test_..."
"test"

