Service API
Architecture
A comprehensive guide for implementing the instruction-based Service API Architecture as standalone, independent servers. Each Service API follows the nuvion-core structural patterns.
3-Layer
Architecture
Multi-Provider
Support
Versioned
Instructions
Type-Safe
VSL Validation
Idempotent
Operations
Architecture Overview
Understanding the core concepts and deployment model
The architecture decouples the Core Service from third-party provider implementations through a unified, versioned instruction protocol.
// Critical Architectural Points
- 1. One Service API = One Server
- 2. Provider-Specific VSL Specs
- 3. Versioned Instructions (v1, v2)
Three-Layer Architecture
Click on each layer to explore its responsibilities
Core Service → Instruction Request
Layer 1: Instruction Handler
Endpoint Layer
Layer 2: Service Orchestrator
Service Layer
Layer 3: Provider Executor
Provider Adapter
External Provider (Flutterwave, Stripe, etc.)
Instruction Protocol
The unified interface for all Service APIs through a single /instructions endpoint
instructionThe action to perform (verb.noun format)
versionAPI version for backward compatibility (v1, v2)
unique_referencev1.1Client-generated unique identifier for idempotency
provider3-char provider code + optional routing hints
payloadProvider-specific data validated against spec
Idempotency via unique_reference
The composite key provider.id + unique_reference ensures duplicate requests return cached responses instead of re-executing. This prevents issues from network retries or client errors.
Common Instructions
Idempotency Flow
See how duplicate requests are handled using the unique_reference field
// Instruction Request
0
Requests Sent
0
Cached Responses
Provider System
Each provider has different requirements. Select a provider to see its specific specs.
Flutterwave
Provider Integration
Regions
Currencies
Supported Instructions
create.accountlist.accountsget.accountupdate.accountVSL Spec: FLW/specs/v1/create-account.vsl.js
root { // Flutterwave create account v1
bvn string<length:11> email string<isEmail> currency string(NGN|KES|GHS)
...
}
Key insight: Each provider's create.account spec is different! FLW requires BVN, STR requires SSN/routing, THR requires NIN.
Cross-Provider Field Mapping
How the same unified payload gets transformed differently for each provider
| Unified Field | FLW | STR | THR |
|---|---|---|---|
| customer_name | account_name | account_holder_name | name |
| kyc_reference | bvn | ssn | nin |
| phone | mobilenumber | phone_number | mobile |
| entity_id | tx_ref | metadata.entity_id | reference |
| currency | currency | currency | currency |
Provider Failover Responsibility
Service APIs are pure delivery mechanisms - failover logic lives in Core Service
- Provider failover logic
- Automatic provider switching
- Retry logic for failed providers
- Provider selection decisions
- Instruction execution for specified provider
- Payload transformation to provider format
- Provider API communication
- Response normalization
Core Service sends instruction to Account Issuing API with provider=FLW
FLW fails (timeout, error, etc.) - Service API returns error to Core Service
Core Service decides: retry FLW or switch to STR (based on business logic)
Core Service sends new instruction with provider=STR
Why This Design?
Central Knowledge
Core Service knows all available providers across all Service APIs
Business Logic
Core Service has provider selection logic (cost, features, reliability)
Health Metrics
Core Service maintains provider health metrics and routing decisions
Simple Executors
Service APIs stay focused on execution, not orchestration
Directory Structure
Each Service API is a standalone application with this structure. Click folders to expand.
Key Difference from nuvion-core
- • Single
/instructionsendpoint - • Provider-specific specs with versioning
- • Service-focused domain only
Repository Examples
- • nuvion-core
- • nuvion-account-issuing-api
- • nuvion-payouts-api
- • nuvion-card-issuing-api
Versioning Strategy
How instruction versions enable backward compatibility
Version Evolution Example
bvn: required
nin: optional
date_of_birth: —
bvn: required
nin: required
date_of_birth: required
Reject
Return error saying v1 is deprecated
Auto-upgrade
Transform v1 payload to v2 (if possible)
Support Both
Maintain backward compatibility
// Spec resolution path
providers/[PROVIDER_ID]/specs/[VERSION]/[instruction].vsl.js
// Example: providers/FLW/specs/v2/create-account.vsl.js
Inter-Service Communication
How services communicate via HTTP with service keys
Core Service (nuvion-core)
Creates instruction payload, adds X-Service-Key header
Account Issuing API
Validates key, executes instruction, returns response
Service Authentication
// Request Header
X-Service-Key: sk_account_issuing_xxxxx
Service Discovery
ACCOUNT_ISSUING_API_URL=:3001
PAYOUTS_API_URL=:3002
CARD_ISSUING_API_URL=:3003
Webhook / Callback Architecture
How inbound provider webhooks are received, routed, and processed securely
External Provider
Flutterwave, Stripe, etc.
Callback Server
AWS EC2 + Elastic IP
Service API
Account Issuing API
Static IP Requirement
Providers require whitelisted IPs for webhook delivery
AWS EC2 + Elastic IP
Dedicated server with static IP that can be whitelisted
Raw Payload Forwarding
Preserves original body for signature verification
Retry Logic
3 retries with exponential backoff, then dead letter queue
// callback-server/routes/webhook-receiver.js
const PROVIDER_ROUTES = {
FLW: { serviceUrl: ACCOUNT_ISSUING_API, path: '/webhooks/flutterwave' },
STR: { serviceUrl: ACCOUNT_ISSUING_API, path: '/webhooks/stripe' },
PSP: { serviceUrl: PAYOUTS_API, path: '/webhooks/paystack' },
}
Transaction Consistency
MongoDB transactions with automatic rollback and Slack alerting for failures
Choose a scenario to see how the system handles transaction consistency:
Go-Live Strategy
Best Practices
Conventions and guidelines for consistent implementation
| Component | Convention |
|---|---|
| Service API Repo | nuvion-[domain]-api |
| Instruction | verb.noun |
| Version | v[number] |
| Provider ID | 3 uppercase letters |
| Model Name | PROVIDER_resource |
| Spec File | [instruction].vsl.js |