Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.vultlocal.com/llms.txt

Use this file to discover all available pages before exploring further.

Gateway Authentication

The Gateway supports multiple authentication methods to accommodate different client types and security requirements.

Authentication Methods

MethodUse CaseHeader Format
API KeyThird-party integrationsAuthorization: Bearer olive_live_xxx
JWTAdmin dashboard, internal UIAuthorization: Bearer eyJ...
Service AuthInternal services (Agent-TS)X-Service-Name, X-Service-Timestamp, X-Service-Signature
POS HMACMerchant terminalsX-API-Key-ID, X-Timestamp, X-Signature
Partner HMACPartner integrationsX-API-Key-ID, X-Partner-ID, X-Timestamp, X-Signature

API Key Authentication

For third-party integrations and external clients.

Header Format

Authorization: Bearer olive_live_xxxxxxxxxxxxxxxxxxxxxxxx

API Key Structure

PrefixEnvironment
olive_live_Production
olive_test_Staging/Testing

Creating API Keys

Admin users can create API keys via the admin endpoint:
curl -X POST http://localhost:8080/api/v1/admin/api-keys \
  -H "Authorization: Bearer ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Partner Integration",
    "scopes": ["payments:read", "payments:write", "balance:read"],
    "expires_at": "2025-12-31T23:59:59Z"
  }'

API Key Scopes

ScopeDescription
payments:readRead transaction history
payments:writeCreate payments and transfers
balance:readRead account balances
subscribers:readRead subscriber information
subscribers:writeCreate and update subscribers
cards:readList cards
cards:writeLink/block cards

JWT Authentication

For admin users and internal dashboards.

Obtaining a JWT

curl -X POST http://localhost:8080/api/v1/admin/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@olive.example.com",
    "password": "secure-password"
  }'
Response:
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 86400
}

Using JWT

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

JWT Claims

{
  "sub": "admin-user-id",
  "email": "admin@olive.example.com",
  "role": "system_admin",
  "iat": 1704067200,
  "exp": 1704153600
}

Admin Roles

RolePermissions
system_adminFull access to all operations
compliance_userCompliance alerts and monitoring
support_userRead-only access, basic support ops
finance_userTransaction and reconciliation access

Service Authentication

For internal service-to-service communication (e.g., Agent-TS to Gateway).

Headers

X-Service-Name: gateway
X-Service-Timestamp: 1710072000
X-Service-Signature: <hex-hmac>

Signature Generation

import crypto from 'crypto';

function generateServiceHeaders(
  method: string,
  path: string,
  query: string,
  secret: string,
  timestamp: string,
  serviceName: string
) {
  const payload = `${method}|${path}|${query}|${timestamp}`;
  const signature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  return {
    'X-Service-Name': serviceName,
    'X-Service-Timestamp': timestamp,
    'X-Service-Signature': signature,
  };
}

// Usage
const timestamp = Math.floor(Date.now() / 1000).toString();
const headers = generateServiceHeaders(
  'POST',
  '/api/v1/compliance/alerts',
  '',
  process.env.AGENT_TS_SECRET,
  timestamp,
  'agent-ts'
);

Configuration

In config.yaml:
service_auth:
  agent_ts:
    secret: ${AGENT_TS_SECRET}
    name: "agent-ts"
  pos_service:
    secret: ${POS_SERVICE_SECRET}
    name: "pos-service"

POS HMAC Authentication

Per-client HMAC for POS terminal authentication.

Headers Required

X-API-Key-ID: pos_key_abc123
X-Timestamp: 2026-03-10T12:00:00Z
X-Signature: 5d41402abc4b2a76b9719d911017c592

Signature Calculation

func generatePOSSignature(method, path, timestamp string, body []byte, secret string) string {
    payload := strings.Join([]string{method, path, timestamp, string(body)}, "\n")
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write([]byte(payload))
    return hex.EncodeToString(mac.Sum(nil))
}

Client Implementation

// Client-side (JavaScript)
const crypto = require('crypto');

function signPOSRequest(apiKeyId, secret, method, path, rawBody) {
  const timestamp = new Date().toISOString();
  const payload = `${method}\n${path}\n${timestamp}\n${rawBody}`;
  
  const signature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  
  return {
    'X-API-Key-ID': apiKeyId,
    'X-Timestamp': timestamp,
    'X-Signature': signature
  };
}

Partner HMAC Authentication

Partner routes use the same newline-delimited signature format as POS, with one additional header:
X-API-Key-ID: partner_key_abc123
X-Partner-ID: VULT
X-Timestamp: 2026-03-10T12:00:00Z
X-Signature: <hex-hmac>
The canonical string is:
METHOD
PATH
TIMESTAMP
RAW_BODY

Combined Authentication

Some endpoints accept multiple authentication methods using AllowServiceOrUser middleware:
// Accepts either service auth OR user API key/JWT
api.GET("/subscribers/:id", 
    mw.AllowServiceOrUser(),
    h.GetSubscriber,
)

Webhook Authentication

VULT webhooks use HMAC signature verification:

Configuration

webhook:
  vult_hmac_secret: ${VULT_WEBHOOK_SECRET}

Verification Header

X-Webhook-Signature: <hex-hmac-of-raw-body>

Security Best Practices

  • Store keys securely (never in client-side code)
  • Rotate keys periodically
  • Use scopes to limit access
  • Set expiration dates
  • Use strong secrets (minimum 32 characters)
  • Set appropriate expiration times
  • Implement token refresh flows
  • Validate all claims
  • Include timestamp to prevent replay attacks
  • Validate timestamp is within acceptable window (5 min)
  • Use constant-time comparison
  • Rotate secrets periodically

Troubleshooting

  • Verify header format is correct
  • Check API key or JWT is valid and not expired
  • Ensure key has required scopes
  • Check user has required role
  • Verify endpoint is accessible with current auth method
  • Verify secret matches on both sides
  • Check timestamp format: RFC3339 for POS/Partner, unix seconds for service auth
  • Ensure the exact raw body used for signing is what was sent
  • Verify correct encoding (UTF-8)

Next Steps

Configuration

Full config.yaml reference

API Reference

Endpoint documentation