Security
Security practices, compliance, and best practices for the Reevit platform
Security Overview
Reevit is built with security as a foundational principle. As a payment orchestration platform handling sensitive financial data, we employ industry-standard security practices to protect your data and your customers' information.
🔐 Data Encryption
Encryption in Transit
All data transmitted to and from Reevit is encrypted using TLS 1.3 (Transport Layer Security). This ensures that:
- All API communications use HTTPS with modern cipher suites
- Webhook deliveries are encrypted end-to-end
- No sensitive data is ever transmitted in plain text
# All Reevit endpoints require TLS 1.2+
curl -https://api.reevit.com/v1/paymentsEncryption at Rest
Sensitive data stored by Reevit is encrypted using AES-256-GCM:
| Operation | Latency | Memory | Allocations |
|---|---|---|---|
| Encrypt | ~957 ns/op | 1.7 KB | 8 allocs |
| Decrypt | ~647 ns/op | 1.5 KB | 5 allocs |
| Round Trip | ~1.5 μs/op | 3.2 KB | 13 allocs |
- PSP Credentials: API keys, secrets, and tokens are encrypted before storage
- Payment Metadata: Customer PII is encrypted at rest
- Database Encryption: All database volumes use full-disk encryption
Credential encryption uses envelope encryption with hardware-backed key management (AWS KMS support).
Performance: AES-256-GCM encryption adds minimal latency (~1.5μs) to credential operations, ensuring security without impacting payment processing speed.
🔑 Credential Management (BYOK)
Reevit operates on a Bring Your Own Key (BYOK) model. Your payment provider credentials are:
- Never shared with other organizations
- Encrypted at rest using AES-256
- Accessed only during payment processing
- Never logged in plain text
Credential Storage
When you create a Connection, your credentials are:
- Transmitted over TLS to Reevit
- Encrypted immediately upon receipt using your organization's encryption key
- Stored in a dedicated secrets vault with hardware security module (HSM) protection
- Decrypted only when processing payments for your organization
Supported Credential Formats
| Provider | Required Credentials |
|---|---|
| Paystack | secret_key |
| Hubtel | client_id, client_secret, merchant_account |
| Flutterwave | secret_key |
| Monnify | apiKey, contractCode |
| M-Pesa | consumer_key, consumer_secret, passkey, short_code |
| Stripe | secret_key (or sk_live, sk_test) |
Credential Aliases: Reevit accepts multiple key names for flexibility (e.g., secretKey or secret_key for Paystack).
🛡️ Webhook Security
Reevit verifies all incoming webhooks from payment providers to prevent spoofing attacks.
Signature Verification
Each provider uses its own signature mechanism:
| Provider | Verification Method | Algorithm |
|---|---|---|
| Paystack | HMAC-SHA512 signature in x-paystack-signature header | SHA-512 |
| Hubtel | HMAC-SHA256 signature in hubtel-signature header | SHA-256 |
| Flutterwave | HMAC-SHA256 signature in verifier-hash header | SHA-256 |
| Stripe | Ed25519 signature in Stripe-Signature header | Ed25519 |
| M-Pesa | OAuth token + signature verification | SHA-256 |
Webhook Secrets
For Stripe, store your webhook signing secret in connection credentials:
await reevit.connections.create({
provider: "stripe",
credentials: {
secret_key: "sk_live_...",
stripe_webhook_secret: "whsec_..." // Required for webhook verification
}
});Always verify webhook signatures: Never process a webhook without signature verification. Reevit rejects all unverified webhooks.
🛡️ HTTP Security Headers
All Reevit API responses include security headers to protect against common web vulnerabilities:
| Header | Value | Purpose |
|---|---|---|
Strict-Transport-Security | max-age=31536000; includeSubDomains; preload | Enforces HTTPS for 1 year |
X-Content-Type-Options | nosniff | Prevents MIME type sniffing |
X-Frame-Options | DENY | Prevents clickjacking attacks |
X-XSS-Protection | 1; mode=block | XSS filter for older browsers |
Referrer-Policy | strict-origin-when-cross-origin | Controls referrer information |
Content-Security-Policy | default-src 'none'; frame-ancestors 'none' | API response CSP |
Permissions-Policy | geolocation=(), microphone=(), camera=() | Restricts browser features |
Performance: Security headers add negligible overhead to all responses.
🔒 API Authentication
API Keys
Reevit uses API keys for authentication. Keys are scoped to organizations and can have specific permission scopes.
| Key Type | Purpose | Scope |
|---|---|---|
Live Keys (pfk_live_...) | Production payments | All operations |
Test Keys (pfk_test_...) | Development & testing | Read-only for some endpoints |
Authentication Scopes
API keys can be restricted to specific scopes:
| Scope | Description |
|---|---|
payments:read | View payment history |
payments:write | Create and manage payments |
connections:read | View PSP connections |
connections:write | Create/update connections |
webhooks:read | View webhook logs |
webhooks:write | Configure webhooks |
Password Hashing
User passwords are hashed using Argon2id (winner of the Password Hashing Competition):
| Operation | Time | Memory |
|---|---|---|
| Hash | ~11.4 ms | 16.8 MB |
| Verify | ~11.2 ms | 16.8 MB |
Argon2id provides strong resistance against GPU-based and ASIC attacks while maintaining reasonable performance for authentication flows.
Security: Argon2id with 16.8 MB memory usage provides excellent protection against brute-force attacks, even on hardware with significant computational power.
Rate Limiting
Reevit implements rate limiting to prevent abuse:
| Plan | Requests/minute | Burst | Latency |
|---|---|---|---|
| Free | 60 | 10 | ~2 μs |
| Pro | 300 | 50 | ~2 μs |
| Enterprise | 1000+ | Custom | ~2 μs |
Performance: In-memory rate limiting adds only ~2μs overhead per request. Redis-based distributed rate limiting is available for multi-instance deployments.
📋 Audit Logging
All sensitive operations are logged with:
- Timestamp: ISO 8601 formatted
- Actor: User/service that performed the action
- Action: What operation was performed
- Resource: Affected entity (e.g., connection ID)
- Result: Success/failure with error details
Logged Events
| Category | Events |
|---|---|
| Connections | Create, update, delete, test |
| Payments | Create, confirm, refund, cancel |
| Webhooks | Delivery attempts, failures |
| Authentication | Login, key creation, key revocation |
Audit logs are retained for 24 months and are immutable.
Audit Access: Enterprise plans can export audit logs via API for compliance reporting.
🏢 Compliance
PCI DSS
Reevit is designed to help you maintain PCI DSS compliance:
- SAQ A Eligible: If you use Reevit Checkout or Payment Links, you may be eligible for SAQ A
- No Card Storage: Reevit never stores raw card numbers
- Tokenized Data: Card references are PSP-managed tokens
Your Responsibility: You must ensure your integration follows PCI guidelines. Use our hosted payment pages when possible to minimize scope.
Data Residency
By default, data is processed in EU-West (Ireland). Enterprise customers can request data residency in:
- EU: Ireland (default)
- US: Virginia
- APAC: Singapore
Data Retention
| Data Type | Retention Period |
|---|---|
| Payment records | 7 years (regulatory requirement) |
| Audit logs | 24 months |
| Webhook logs | 90 days |
| Temporary logs | 7 days |
🛠️ Security Best Practices
For Your Application
-
Never expose API keys in client-side code
// ❌ Wrong - exposes key to browser const client = new Reevit('pk_live_xxx'); // ✅ Correct - use server-side only const client = new Reevit(process.env.REEVIT_SECRET_KEY); -
Use webhooks for payment confirmation
// ❌ Never trust client-side success if (payment.status === 'succeeded') fulfillOrder(); // ✅ Always verify via webhook app.post('/webhooks/reevit', async (req, res) => { if (verifySignature(req)) { if (req.body.event === 'payment.succeeded') { fulfillOrder(req.body.data.payment_id); } } }); -
Implement idempotency
const payment = await reevit.payments.create({ idempotency_key: 'order_12345', // Prevents duplicate charges amount: 5000, currency: 'GHS' }); -
Validate webhooks on your server
const signature = req.headers['x-reevit-signature']; if (!verifyWebhookSignature(signature, body, webhookSecret)) { return res.status(401).send('Invalid signature'); }
For Your PSP Connections
-
Use separate credentials per environment
// Development await reevit.connections.create({ provider: 'paystack', mode: 'sandbox', credentials: { secret_key: 'sk_test_...' } }); // Production await reevit.connections.create({ provider: 'paystack', mode: 'live', credentials: { secret_key: 'sk_live_...' } }); -
Enable connection health monitoring
- Reevit automatically tracks success rates and latency
- Configure alerts for degraded connections
-
Use labels for organization
await reevit.connections.create({ provider: 'stripe', labels: ['production', 'cards-primary', 'eu'], routing_hints: { priority: 'primary' } });
🚨 Incident Response
Security Monitoring
Reevit maintains 24/7 security monitoring with:
- Intrusion Detection: Automated anomaly detection
- DDoS Protection: Cloudflare-based mitigation
- Vulnerability Scanning: Regular automated scans
Reporting Security Issues
If you discover a security vulnerability:
- Do not disclose publicly
- Email security@reevit.io with details
- Expect response within 24 hours
Responsible Disclosure: We appreciate responsible vulnerability reporting and will work with you to resolve issues quickly.
📚 Benchmark Methodology
Security benchmarks were run on Apple M1 Max (arm64) with the following configuration:
- Encryption: AES-256-GCM with 32-byte keys
- Password Hashing: Argon2id with 16.8 MB memory, 1 iteration
- Rate Limiting: Sliding window algorithm with in-memory storage
- HTTPS Headers: Chi middleware with Go 1.25
All benchmarks represent median performance over 10+ runs.
Note: Actual performance may vary based on hardware, load, and network conditions. Benchmarks are indicative of security implementation efficiency.