Integration Security
Document ID: ACP-001.5 Version: 1.0 Classification: Internal / Regulator-Shareable Effective Date: March 2026 Next Review: September 2026 Parent Document: ACP-001 — Access Control & Permissions
1. Overview
Keshless provides secure API integration capabilities for third-party systems (POS systems, payment gateways, partner platforms) through vendor-specific API keys. This document covers API key lifecycle management, IP whitelisting, access scoping, and security controls for external integrations.
2. Integration Architecture
┌────────────────────────┐
│ Partner System │
│ (e.g., POS, ERP) │
└──────────┬─────────────┘
│
│ X-API-Key: <vendor_api_key>
│ From whitelisted IP
│
▼
┌──────────────────────────────────────────┐
│ API Gateway (Cloud Run) │
│ │
│ ┌────────────────────────────────────┐ │
│ │ validateVendorApiKey() middleware │ │
│ │ │ │
│ │ 1. Extract X-API-Key header │ │
│ │ 2. Look up key in database │ │
│ │ 3. Check key not expired │ │
│ │ 4. Validate IP against whitelist │ │
│ │ 5. Attach vendor + integration │ │
│ │ info to request │ │
│ └────────────────────────────────────┘ │
│ │
│ Request proceeds with vendor context │
│ (scoped to the vendor that owns the key)│
└──────────────────────────────────────────┘3. API Key Lifecycle
3.1 Key Creation
| Step | Detail |
|---|---|
| Who | Vendor owner (JWT authenticated) or system admin |
| Endpoint | POST /api/integrations |
| Authentication | JWT Bearer token required |
| Authorization | Vendor ownership check (must own the vendor account) |
| Output | API key string + integration record ID |
Integration Record Fields:
| Field | Description |
|---|---|
id | Unique integration ID |
vendorId | Owning vendor |
apiKey | The generated key (hashed for storage) |
appName | Partner application name (e.g., "parkmate", "custom") |
ipWhitelist | Array of allowed IP addresses (optional) |
expiresAt | Key expiration date (optional) |
status | ACTIVE, REVOKED, or EXPIRED |
lastUsedAt | Last successful use timestamp |
requestCount | Total API calls made with this key |
createdAt | Creation timestamp |
3.2 Key Rotation
| Step | Detail |
|---|---|
| Endpoint | PATCH /api/integrations/{id}/rotate |
| Authentication | JWT Bearer token |
| Effect | Old key invalidated, new key generated |
| Downtime | Instant — old key stops working immediately |
3.3 Key Revocation
| Step | Detail |
|---|---|
| Endpoint | DELETE /api/integrations/{id} |
| Authentication | JWT Bearer token |
| Effect | Key status set to REVOKED; all subsequent requests rejected |
3.4 Key Listing
| Step | Detail |
|---|---|
| Endpoint | GET /api/integrations?vendorId=X |
| Authentication | JWT Bearer token |
| Scope | Only shows keys for the authenticated vendor (or all if admin) |
4. Validation Process
When a request arrives with an X-API-Key header, the validateVendorApiKey() middleware performs these checks in order:
4.1 Validation Steps
| Step | Check | Failure Response |
|---|---|---|
| 1 | Header present | 401 — API key required |
| 2 | Key exists in database | 401 — Invalid API key |
| 3 | Key status is ACTIVE | 401 — API key revoked or inactive |
| 4 | Key not expired (expiresAt) | 401 — API key expired |
| 5 | IP whitelist check (if configured) | 403 — IP address not authorized |
| 6 | Attach vendor + integration to request | — (proceeds) |
4.2 IP Whitelist
If the integration has an ipWhitelist configured:
- Request IP checked against
x-forwarded-forheader first, thenreq.ip - Supports individual IP addresses
- If no whitelist is configured, all IPs are accepted
- Empty whitelist = no restriction (opt-in security)
4.3 Post-Validation
After successful validation, the middleware attaches:
| Field | Attached To | Description |
|---|---|---|
req.vendor | Request object | Full vendor record |
req.integration | Request object | Integration record (key metadata) |
All subsequent middleware and controllers can use req.vendor to scope operations to the authenticated vendor.
5. Access Scoping
5.1 Vendor Isolation
Integration API keys are scoped to a single vendor. All operations performed through an API key are restricted to:
- The vendor's own transactions
- The vendor's own customers
- The vendor's own financial data
An integration API key cannot:
- Access other vendors' data
- Perform admin operations
- Modify the vendor's own API keys (must use JWT auth for that)
- Access system configuration
5.2 Operation Scope
Integration API access is limited to vendor-facing operations:
| Allowed Operations | Not Allowed |
|---|---|
| Process payments | Admin dashboard access |
| View transaction history | User management |
| Check vendor balance | System configuration |
| Customer operations | AML/compliance operations |
| Emergency control management | |
| Other vendors' data |
6. Security Controls
6.1 Key Storage
| Aspect | Implementation |
|---|---|
| Storage format | SHA-256 hashed in database |
| Display | Full key shown only at creation; never retrievable again |
| Rotation | Old key immediately invalidated on rotation |
6.2 Monitoring
| Metric | Tracked |
|---|---|
lastUsedAt | Updated on every successful API call |
requestCount | Incremented on every successful API call |
| Audit log | Key creation, rotation, and revocation logged |
6.3 Best Practices for Partners
| Practice | Recommendation |
|---|---|
| Key storage | Store in environment variables or secret manager; never in source code |
| IP whitelisting | Configure allowed IPs for production integrations |
| Key rotation | Rotate keys at least every 90 days |
| Expiration | Set expiration dates on keys; request new keys before expiry |
| Monitoring | Monitor requestCount for unusual spikes |
| HTTPS only | All API calls must use HTTPS (enforced by Cloud Run) |
7. Application API Key
7.1 Purpose
Separate from vendor integration keys, the application API key (APP_API_KEY) is a shared secret used by Keshless frontend applications:
| Aspect | Detail |
|---|---|
| Header | X-API-Key |
| Validation | validateApiKey() middleware |
| Scope | Public-facing endpoints requiring basic authentication |
| Storage | Environment variable on server |
7.2 Dual Authentication
Some endpoints accept either JWT Bearer token OR application API key via the validateBearerOrApiKey() middleware. This allows:
- Authenticated users to access with their JWT (full context)
- Frontend apps to access with the shared API key (limited context)
8. Job/Scheduler Authentication
8.1 Purpose
Automated jobs (Cloud Scheduler triggers) authenticate separately from users and integrations:
| Aspect | Detail |
|---|---|
| Header | X-Job-Secret |
| Validation | validateJobSecret() middleware |
| Secret | JOB_SECRET environment variable |
| Scope | Backup jobs, reconciliation, scheduled maintenance |
| User context | None — operates as system |
8.2 Protected Job Endpoints
Job authentication is applied to scheduled task endpoints only:
- Database backup triggers
- Reconciliation jobs
- Cleanup and maintenance tasks
These endpoints are not accessible via JWT or API key authentication — they exclusively require the job secret.
9. Third-Party Service Access
9.1 Outbound Integrations
Keshless connects to external services with the following access controls:
| Service | Authentication | Purpose |
|---|---|---|
| Notification Service | API Key (X-API-KEY header) | SMS/WhatsApp OTP delivery |
| GCP Cloud Storage | Service account credentials | KYC document storage |
| GCP Cloud SQL | Cloud SQL Proxy + IAM | Database access |
| GCP Secret Manager | Service account credentials | Secret retrieval |
9.2 Notification Service
The shared notification service at notifications.eneza.app is authenticated via a dedicated API key:
| Aspect | Detail |
|---|---|
| Header | X-API-KEY |
| Channels | WhatsApp (primary), SMS (fallback) |
| Used for | OTP delivery, authentication codes |
| Access | Server-to-server only (never exposed to clients) |