forked from llinsss/payCrypt_v2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathopenapi.json
More file actions
1 lines (1 loc) · 104 KB
/
Copy pathopenapi.json
File metadata and controls
1 lines (1 loc) · 104 KB
1
{"openapi":"3.0.0","info":{"title":"Tagg@d API","version":"1.0.0","description":"API documentation for the Tagg@d backend — a crypto payment platform for Africa."},"servers":[{"url":"http://localhost:5002/api/v2","description":"Current version (v2)"},{"url":"http://localhost:5002/api/v1","description":"Deprecated version (v1)"},{"url":"http://localhost:5002","description":"Development Server (unversioned root)"},{"url":"https://taggedpay.xyz/api/v2","description":"Production (v2)"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key"}},"schemas":{"AnalyticsVolumePoint":{"type":"object","properties":{"date":{"type":"string","example":"2024-02-20"},"volume":{"type":"number","example":45000},"count":{"type":"integer","example":120}}},"AnalyticsTokenStat":{"type":"object","properties":{"symbol":{"type":"string","example":"XLM"},"volume":{"type":"number","example":500000},"count":{"type":"integer","example":2500}}},"AnalyticsChainStat":{"type":"object","properties":{"chainId":{"type":"string","example":"1"},"chainName":{"type":"string","example":"Stellar"},"count":{"type":"integer","example":3000},"volume":{"type":"number","example":750000}}},"Transaction":{"type":"object","properties":{"id":{"type":"integer","example":42},"user_id":{"type":"string"},"type":{"type":"string","enum":["credit","debit","payment","swap"],"example":"payment"},"status":{"type":"string","enum":["pending","completed","failed"],"example":"completed"},"amount":{"type":"number","example":50},"usd_value":{"type":"number","example":50},"chain":{"type":"string","example":"stellar"},"token":{"type":"string","example":"USDC"},"sender_tag":{"type":"string","example":"alice"},"receiver_tag":{"type":"string","example":"bob"},"tx_hash":{"type":"string","example":"0xabc123..."},"note":{"type":"string","example":"Monthly rent"},"created_at":{"type":"string","format":"date-time"}}},"ProcessPaymentRequest":{"type":"object","required":["senderTag","recipientTag","amount"],"properties":{"senderTag":{"type":"string","pattern":"^[a-zA-Z0-9_]{3,20}$","example":"alice"},"recipientTag":{"type":"string","pattern":"^[a-zA-Z0-9_]{3,20}$","example":"bob"},"amount":{"type":"number","example":25},"asset":{"type":"string","default":"XLM","example":"USDC"},"assetIssuer":{"type":"string","description":"Stellar asset issuer (required for non-native assets)"},"memo":{"type":"string","maxLength":28,"example":"Lunch money"},"notes":{"type":"string","maxLength":500},"idempotencyKey":{"type":"string","maxLength":255}}},"WebhookEventType":{"type":"string","enum":["payment.completed","payment.failed","payment.pending","payment.refunded","wallet.credited","wallet.debited","kyc.approved","kyc.rejected","transaction.status_changed"]},"WebhookRegistration":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri","example":"https://yourapp.com/api/webhooks/tagged"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"},"example":["payment.completed","wallet.credited"]},"secret":{"type":"string","example":"whsec_abc123def456...","description":"Optional custom signing secret. If omitted, one will be generated."}}},"WebhookDelivery":{"type":"object","properties":{"id":{"type":"integer"},"webhook_id":{"type":"integer"},"event_type":{"type":"string"},"payload":{"type":"object"},"status":{"type":"string","enum":["pending","delivered","failed"]},"attempts":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}},"WebhookEventPayload":{"type":"object","description":"Payload delivered to webhook URL on each event","properties":{"event":{"type":"string","example":"payment.completed"},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"transaction_id":{"type":"integer","example":42},"user_id":{"type":"string"},"amount":{"type":"number","example":50},"asset":{"type":"string","example":"USDC"},"status":{"type":"string","example":"completed"}}},"signature":{"type":"string","description":"HMAC-SHA256 signature for verifying payload authenticity"}}}}},"paths":{"/api/analytics/volume":{"get":{"summary":"Transaction volume aggregated by period","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","enum":["daily","weekly","monthly"],"default":"daily"}},{"in":"query","name":"from","schema":{"type":"string","format":"date","example":"2024-01-01"}},{"in":"query","name":"to","schema":{"type":"string","format":"date","example":"2024-12-31"}},{"in":"query","name":"userId","schema":{"type":"string"}}],"responses":{"200":{"description":"Volume by period","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsVolumePoint"}}}}}}},"403":{"description":"Admin access required"}}}},"/api/analytics/average-size":{"get":{"summary":"Average transaction size","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","enum":["all","daily","weekly","monthly"],"default":"all"}}],"responses":{"200":{"description":"Average transaction size"},"403":{"description":"Admin access required"}}}},"/api/analytics/success-rate":{"get":{"summary":"Transaction success/failure rate","tags":["Analytics"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Transaction success rate"},"403":{"description":"Admin access required"}}}},"/api/analytics/user-growth":{"get":{"summary":"New and cumulative user growth by period","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"period","schema":{"type":"string","enum":["daily","weekly","monthly"],"default":"daily"}}],"responses":{"200":{"description":"User growth series"},"403":{"description":"Admin access required"}}}},"/api/analytics/time-series":{"get":{"summary":"Transaction count and volume time series","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"startDate","schema":{"type":"string","format":"date"}},{"in":"query","name":"endDate","schema":{"type":"string","format":"date"}},{"in":"query","name":"period","schema":{"type":"string","enum":["daily","weekly","monthly"],"default":"daily"}}],"responses":{"200":{"description":"Time series data"},"403":{"description":"Admin access required"}}}},"/api/analytics/dashboard-summary":{"get":{"summary":"High-level dashboard summary (volume, success rate, users)","tags":["Analytics"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Dashboard summary"},"403":{"description":"Admin access required"}}}},"/api/analytics/overview":{"get":{"summary":"Full analytics overview (summary + volume trend + top tokens/chains)","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date","example":"2024-01-01"}},{"in":"query","name":"to","schema":{"type":"string","format":"date","example":"2024-12-31"}},{"in":"query","name":"userId","schema":{"type":"string"}}],"responses":{"200":{"description":"Aggregated overview statistics"},"403":{"description":"Admin access required"}}}},"/api/analytics/tokens":{"get":{"summary":"Top tokens by volume and transaction count","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date"}},{"in":"query","name":"to","schema":{"type":"string","format":"date"}},{"in":"query","name":"userId","schema":{"type":"string"}}],"responses":{"200":{"description":"Top tokens","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsTokenStat"}}}}}}},"403":{"description":"Admin access required"}}}},"/api/analytics/chains":{"get":{"summary":"Top chains by transaction count and volume","tags":["Analytics"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"from","schema":{"type":"string","format":"date"}},{"in":"query","name":"to","schema":{"type":"string","format":"date"}},{"in":"query","name":"userId","schema":{"type":"string"}}],"responses":{"200":{"description":"Top chains","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/AnalyticsChainStat"}}}}}}},"403":{"description":"Admin access required"}}}},"/api/api-keys":{"post":{"summary":"Create a new API key","description":"Generate an API key with specified scopes for third-party access. The key is returned only once — store it securely.","tags":["API Keys"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":3,"maxLength":100,"example":"Partner Integration Key"},"scopes":{"type":"string","default":"read,write","description":"Comma-separated scopes (transactions:read, transactions:write, payments:send, webhooks:read, webhooks:write)","example":"transactions:read,webhooks:read"},"ipWhitelist":{"type":"string","description":"Comma-separated IP addresses or CIDR ranges","example":"203.0.113.0/24,192.168.1.1"},"expiresIn":{"type":"number","minimum":1,"maximum":365,"description":"Number of days until the key expires","example":90},"rotationIntervalDays":{"type":"number","minimum":1,"maximum":365,"description":"Automatic rotation interval in days","example":30}}}}}},"responses":{"201":{"description":"API key created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"id":{"type":"integer","example":1},"name":{"type":"string","example":"Partner Integration Key"},"key":{"type":"string","example":"tagged_live_sk_a1b2c3d4e5f6..."},"scopes":{"type":"string","example":"transactions:read,webhooks:read"},"expires_at":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"get":{"summary":"List all API keys for the authenticated user","tags":["API Keys"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of API keys","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"scopes":{"type":"string"},"is_active":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/api-keys/{keyId}":{"get":{"summary":"Get a specific API key by ID","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"integer"},"description":"API key ID"}],"responses":{"200":{"description":"API key details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"scopes":{"type":"string"},"is_active":{"type":"boolean"},"last_used_at":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"API key not found"}}},"patch":{"summary":"Update an API key","description":"Update the name, scopes, IP whitelist, or rotation interval of an existing API key.","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":3,"maxLength":100},"scopes":{"type":"string"},"ipWhitelist":{"type":"string"},"rotationIntervalDays":{"type":"number","minimum":0,"maximum":365}}}}}},"responses":{"200":{"description":"API key updated successfully"},"400":{"description":"Validation error"},"404":{"description":"API key not found"}}},"delete":{"summary":"Revoke an API key","description":"Permanently revoke an API key. All requests using this key will be rejected.","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"API key revoked successfully"},"404":{"description":"API key not found"}}}},"/api/api-keys/{keyId}/stats":{"get":{"summary":"Get usage statistics for an API key","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"API key usage statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"total_requests":{"type":"integer"},"last_used_at":{"type":"string","format":"date-time"},"requests_by_scope":{"type":"object"}}}}}}}},"404":{"description":"API key not found"}}}},"/api/api-keys/{keyId}/rotation-logs":{"get":{"summary":"Get rotation logs for an API key","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Rotation audit logs"},"404":{"description":"API key not found"}}}},"/api/api-keys/{keyId}/rotate":{"post":{"summary":"Rotate an API key","description":"Creates a new key and revokes the old one. The new key is returned only once.","tags":["API Keys"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Key rotated successfully — new key returned","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"new_key":{"type":"string"},"old_key_revoked_at":{"type":"string","format":"date-time"}}}}}}}},"404":{"description":"API key not found"},"429":{"description":"Rate limit exceeded"}}}},"/api/audit-logs/stats":{"get":{"summary":"Get audit log statistics","tags":["Audit Logs"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Audit log statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"total_logs":{"type":"integer"},"by_action":{"type":"object"},"by_resource":{"type":"object"}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/audit-logs/cleanup":{"delete":{"summary":"Clean up old audit logs","description":"Remove audit logs older than a specified retention period.","tags":["Audit Logs"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Cleanup completed","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"deleted_count":{"type":"integer"}}}}}},"401":{"description":"Unauthorized"}}}},"/api/audit-logs":{"get":{"summary":"List audit logs with filtering and pagination","tags":["Audit Logs"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"action","schema":{"type":"string","enum":["CREATE","READ","UPDATE","DELETE","LOGIN","LOGOUT"]},"description":"Filter by action type"},{"in":"query","name":"resource","schema":{"type":"string"},"description":"Filter by resource name"},{"in":"query","name":"userId","schema":{"type":"string"},"description":"Filter by user ID"},{"in":"query","name":"from","schema":{"type":"string","format":"date"},"description":"Start date (ISO format)"},{"in":"query","name":"to","schema":{"type":"string","format":"date"},"description":"End date (ISO format)"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"default":0}},{"in":"query","name":"sortBy","schema":{"type":"string","enum":["created_at","action","resource","status_code"],"default":"created_at"}},{"in":"query","name":"sortOrder","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}}],"responses":{"200":{"description":"Paginated list of audit logs","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"action":{"type":"string","example":"CREATE"},"resource":{"type":"string","example":"transactions"},"user_id":{"type":"string"},"status_code":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/audit-logs/{id}":{"get":{"summary":"Get a specific audit log entry","tags":["Audit Logs"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Audit log ID"}],"responses":{"200":{"description":"Audit log entry details"},"401":{"description":"Unauthorized"},"404":{"description":"Audit log not found"}}}},"/api/auth/register":{"post":{"summary":"Register a new user","description":"Create a new Tagg@d account. Requires email and password. Returns a JWT token on success.","tags":["Authentication"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"john.lagos@example.com"},"password":{"type":"string","format":"password","minLength":8,"example":"StrongP@ssw0rd!"},"firstName":{"type":"string","example":"John"},"lastName":{"type":"string","example":"Adebayo"}}}}}},"responses":{"201":{"description":"User registered successfully","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"success"},"data":{"type":"object","properties":{"id":{"type":"string","example":"usr_abc123"},"email":{"type":"string","example":"john.lagos@example.com"},"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}}}}}}}},"400":{"description":"Validation error"}}}},"/api/auth/login":{"post":{"summary":"Login user and get JWT token","description":"Authenticate with email/password. If 2FA is enabled, include the `twoFactorToken`. Returns a JWT bearer token.","tags":["Authentication"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"john.lagos@example.com"},"password":{"type":"string","format":"password","example":"StrongP@ssw0rd!"},"twoFactorToken":{"type":"string","example":"123456","description":"6-digit OTP from authenticator app (required if 2FA is enabled)"}}}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"success"},"data":{"type":"object","properties":{"token":{"type":"string","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"user":{"type":"object","properties":{"id":{"type":"string"},"email":{"type":"string"},"role":{"type":"string","example":"user"}}}}}}}}}},"400":{"description":"Invalid credentials"},"401":{"description":"Unauthorized or 2FA token required"}}}},"/api/auth/google":{"post":{"summary":"Login with Google OAuth","description":"Authenticate using a Google OAuth token. The token is verified against Google's OAuth API and a Tagg@d JWT is returned.","tags":["Authentication"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["googleToken"],"properties":{"googleToken":{"type":"string","example":"ya29.a0AfH6SMB...","description":"Google OAuth access token obtained from the frontend Google Sign-In flow"}}}}}},"responses":{"200":{"description":"Google login successful","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"success"},"data":{"type":"object","properties":{"token":{"type":"string"},"user":{"type":"object"}}}}}}}},"400":{"description":"Invalid Google token"},"401":{"description":"Google authentication failed"}}}},"/api/auth/2fa/setup":{"post":{"summary":"Set up two-factor authentication","description":"Generate a TOTP secret and QR code for enabling 2FA. Returns a base32 secret and a QR code URL for the authenticator app.","tags":["Authentication"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"2FA setup initialized","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"object","properties":{"secret":{"type":"string","example":"JBSWY3DPEHPK3PXP"},"qrCodeUrl":{"type":"string","example":"otpauth://totp/Tagged:john@example.com?secret=JBSWY3DPEHPK3PXP..."}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/auth/2fa/enable":{"post":{"summary":"Enable two-factor authentication","description":"Confirm 2FA setup by providing the first TOTP code from your authenticator app. After enabling, the `twoFactorToken` will be required for all future logins.","tags":["Authentication"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["twoFactorToken"],"properties":{"twoFactorToken":{"type":"string","example":"123456","description":"6-digit OTP from the authenticator app"}}}}}},"responses":{"200":{"description":"2FA enabled successfully"},"400":{"description":"Invalid 2FA token"},"401":{"description":"Unauthorized"}}}},"/api/auth/2fa/verify":{"post":{"summary":"Verify a 2FA token","description":"Verify a TOTP token from the authenticator app. Used to validate 2FA during sensitive operations like withdrawals.","tags":["Authentication"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["twoFactorToken"],"properties":{"twoFactorToken":{"type":"string","example":"654321"}}}}}},"responses":{"200":{"description":"2FA token verified","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string","example":"2FA token verified"}}}}}},"400":{"description":"Invalid 2FA token"},"401":{"description":"Unauthorized"}}}},"/api/admin/backups":{"get":{"summary":"List recent database backups","description":"Returns a list of recent database backups including local and S3 storage, encryption status, and file sizes. Admin access required.","tags":["Backup Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of backups","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"filename":{"type":"string","example":"backup_2025_01_15_0300.sql.gz"},"size":{"type":"number","example":5242880,"description":"File size in bytes"},"encrypted":{"type":"boolean","example":true},"location":{"type":"string","enum":["local","s3"],"example":"s3"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Admin access required"}}}},"/api/balances":{"post":{"summary":"Create a balance record","tags":["Balances"],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Balance created"}}},"get":{"summary":"Get user balances","tags":["Balances"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of balances"}}}},"/api/balances/all":{"get":{"summary":"Get all balances (admin only)","description":"Returns a minimal paginated projection of every customer balances. Requires an authenticated admin user.","tags":["Balances"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"page","required":false,"schema":{"type":"integer","default":1},"description":"Page number (1-based)"},{"in":"query","name":"limit","required":false,"schema":{"type":"integer","default":10,"maximum":100},"description":"Number of records per page"}],"responses":{"200":{"description":"Paginated list of all balances"},"401":{"description":"Unauthorized - access token required or invalid"},"403":{"description":"Forbidden - admin access required"}}}},"/api/balances/sync":{"get":{"summary":"Sync user balance","tags":["Balances"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Balance synced"}}}},"/api/balances/summary":{"get":{"summary":"Get cross-chain balance summary","tags":["Balances"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Portfolio summary with aggregated USD and NGN values"}}}},"/api/balances/{id}":{"get":{"summary":"Get balance by ID","tags":["Balances"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Balance details"}}},"put":{"summary":"Update balance","tags":["Balances"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Balance updated"}}},"delete":{"summary":"Delete balance","tags":["Balances"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Balance deleted"}}}},"/api/balances/tag/{tag}":{"get":{"summary":"Get balance by tag","tags":["Balances"],"parameters":[{"in":"path","name":"tag","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Tag balance"}}}},"/api/bank-accounts":{"get":{"summary":"Get the authenticated user's linked bank accounts","tags":["Bank Accounts"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of user's bank accounts","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1},"bank_name":{"type":"string","example":"GTBank"},"account_number":{"type":"string","example":"0123456789"},"account_name":{"type":"string","example":"John Doe"},"bank_code":{"type":"string","example":"058"}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/bank-accounts/{id}":{"get":{"summary":"Get a specific bank account by ID","tags":["Bank Accounts"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Bank account ID"}],"responses":{"200":{"description":"Bank account details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"bank_name":{"type":"string"},"account_number":{"type":"string"},"account_name":{"type":"string"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Bank account not found"}}},"put":{"summary":"Update a bank account","tags":["Bank Accounts"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"bank_name":{"type":"string","example":"GTBank"},"account_number":{"type":"string","example":"0123456789"},"account_name":{"type":"string","example":"John Doe"},"bank_code":{"type":"string","example":"058"}}}}}},"responses":{"200":{"description":"Bank account updated"},"401":{"description":"Unauthorized"},"404":{"description":"Bank account not found"}}},"delete":{"summary":"Delete a bank account","tags":["Bank Accounts"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Bank account deleted"},"401":{"description":"Unauthorized"},"404":{"description":"Bank account not found"}}}},"/api/batches":{"post":{"summary":"Create a batch payment","description":"Send payments to multiple recipients in a single atomic or non-atomic batch. Max 100 payments per batch.","tags":["Batch Payments"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["senderTag","payments"],"properties":{"senderTag":{"type":"string","example":"alice","description":"Sender's @tag (3-20 alphanumeric/underscore)"},"payments":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"object","required":["recipientTag","amount"],"properties":{"recipientTag":{"type":"string","example":"bob"},"amount":{"type":"number","example":5},"notes":{"type":"string","example":"Monthly salary"}}}},"atomic":{"type":"boolean","default":true,"description":"If true, the entire batch succeeds or fails together"},"asset":{"type":"string","default":"XLM","example":"USDC"},"assetIssuer":{"type":"string","description":"Stellar asset issuer (required for custom assets)"},"memo":{"type":"string","maxLength":28}}}}}},"responses":{"201":{"description":"Batch payment created and queued","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"batchId":{"type":"string","example":"batch_abc123"},"status":{"type":"string","example":"pending"},"totalPayments":{"type":"integer","example":3}}}}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}}},"/api/batches/{id}":{"get":{"summary":"Get batch payment status","description":"Check the processing status and results of a batch payment.","tags":["Batch Payments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Batch payment ID"}],"responses":{"200":{"description":"Batch payment status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"batchId":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","partially_completed","failed"]},"completedPayments":{"type":"integer"},"failedPayments":{"type":"integer"},"totalPayments":{"type":"integer"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Batch payment not found"}}}},"/api/bills/categories":{"get":{"summary":"List all bill payment categories","description":"Returns all available bill payment categories (airtime, data, TV, electricity, betting).","tags":["Bill Payments"],"responses":{"200":{"description":"List of bill categories","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","example":"airtime"},"name":{"type":"string","example":"Airtime Top-Up"},"description":{"type":"string","example":"Recharge your mobile phone"}}}}}}}}}}}},"/api/bills/providers/{category}":{"get":{"summary":"List providers for a bill category","description":"Returns all available service providers for a specific category (e.g., MTN, Airtel for airtime; DSTV, GOTV for TV).","tags":["Bill Payments"],"parameters":[{"in":"path","name":"category","required":true,"schema":{"type":"string","enum":["airtime","data","tv","electricity","betting"]},"description":"Bill payment category"}],"responses":{"200":{"description":"List of providers for the category","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"logo":{"type":"string"}}}}}}}}},"404":{"description":"Category not found"}}}},"/api/bills/pay":{"post":{"summary":"Pay a bill","description":"Initiate a bill payment. Requires authentication and rate-limited to 5 requests per minute.","tags":["Bill Payments"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["category","provider","amount"],"properties":{"category":{"type":"string","example":"airtime"},"provider":{"type":"string","example":"mtn"},"amount":{"type":"number","example":500},"phone":{"type":"string","example":"08012345678"},"smartCardNumber":{"type":"string","description":"Required for TV/electricity payments"},"variation":{"type":"string","description":"Specific plan/variation code"}}}}}},"responses":{"200":{"description":"Bill payment initiated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"reference":{"type":"string","example":"BILL_ref_abc123"},"status":{"type":"string","example":"processing"}}}}}}}},"400":{"description":"Invalid request or missing fields"},"401":{"description":"Unauthorized"},"429":{"description":"Too many bill payment requests"}}}},"/api/chains":{"post":{"summary":"Create a new chain configuration","description":"Add a new supported blockchain chain to the platform.","tags":["Chains"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","chainId"],"properties":{"name":{"type":"string","example":"Stellar"},"chainId":{"type":"string","example":"xlm"},"rpcUrl":{"type":"string","example":"https://horizon.stellar.org"},"symbol":{"type":"string","example":"XLM"},"is_active":{"type":"boolean","default":true}}}}}},"responses":{"201":{"description":"Chain created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"chainId":{"type":"string"}}}}}}}},"400":{"description":"Validation error"}}},"get":{"summary":"List all supported blockchain chains","description":"Returns all supported chains with their configuration. Cached for 1 hour.","tags":["Chains"],"responses":{"200":{"description":"List of supported chains","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1},"name":{"type":"string","example":"Stellar"},"chainId":{"type":"string","example":"xlm"},"symbol":{"type":"string","example":"XLM"},"is_active":{"type":"boolean","example":true}}}}}}}}}}}},"/api/chains/{id}":{"get":{"summary":"Get a specific chain by ID","tags":["Chains"],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Chain ID"}],"responses":{"200":{"description":"Chain details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"},"chainId":{"type":"string"},"rpcUrl":{"type":"string"},"symbol":{"type":"string"}}}}}}}},"404":{"description":"Chain not found"}}},"put":{"summary":"Update a chain configuration","tags":["Chains"],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"rpcUrl":{"type":"string"},"is_active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Chain updated"},"404":{"description":"Chain not found"}}},"delete":{"summary":"Delete a chain configuration","tags":["Chains"],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Chain deleted"},"404":{"description":"Chain not found"}}}},"/api/circuit-breaker/stats":{"get":{"summary":"Get circuit breaker statistics for all services","description":"Returns the current state (open, half-open, closed) and failure counts for each monitored blockchain service.","tags":["Circuit Breaker"],"responses":{"200":{"description":"Circuit breaker statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"serviceKey":{"type":"string","example":"stellar_payment"},"state":{"type":"string","enum":["open","half-open","closed"],"example":"closed"},"failures":{"type":"integer","example":0},"lastFailure":{"type":"string","format":"date-time"}}}}}}}}}}}},"/api/circuit-breaker/reset/{serviceKey}":{"post":{"summary":"Reset a circuit breaker for a specific service","description":"Manually reset a circuit breaker from open/half-open state back to closed. Use with caution.","tags":["Circuit Breaker"],"parameters":[{"in":"path","name":"serviceKey","required":true,"schema":{"type":"string"},"description":"Service key to reset (e.g., stellar_payment, evm_transfer)"}],"responses":{"200":{"description":"Circuit breaker reset successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string","example":"Circuit breaker for stellar_payment has been reset"}}}}}},"404":{"description":"Service key not found"}}}},"/api/disputes/statistics":{"get":{"summary":"Get dispute statistics","description":"Returns aggregate statistics on dispute counts, resolution times, and category breakdown.","tags":["Disputes"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Dispute statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"total_disputes":{"type":"integer"},"open_disputes":{"type":"integer"},"resolved_disputes":{"type":"integer"},"avg_resolution_time_hours":{"type":"number"}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/disputes":{"post":{"summary":"Create a new dispute","description":"Open a dispute for a specific transaction. Requires the transaction ID, reason, and category.","tags":["Disputes"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["transaction_id","reason","description","category"],"properties":{"transaction_id":{"type":"integer","example":42,"description":"The transaction ID to dispute"},"reason":{"type":"string","maxLength":255,"example":"Payment not received"},"description":{"type":"string","example":"I sent 50 USDC to @bob but the funds never arrived in their wallet"},"category":{"type":"string","enum":["unauthorized","duplicate","wrong_amount","not_received","fraud","other"],"example":"not_received"},"priority":{"type":"string","enum":["low","medium","high","critical"],"default":"medium"},"evidence_url":{"type":"string","format":"uri","example":"https://example.com/evidence.pdf"}}}}}},"responses":{"201":{"description":"Dispute created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","example":"open"}}}}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"}}},"get":{"summary":"List disputes","description":"Users see their own disputes; admins see all disputes. Supports filtering and pagination.","tags":["Disputes"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"status","schema":{"type":"string","enum":["open","under_review","escalated","resolved","closed"]}},{"in":"query","name":"priority","schema":{"type":"string","enum":["low","medium","high","critical"]}},{"in":"query","name":"category","schema":{"type":"string","enum":["unauthorized","duplicate","wrong_amount","not_received","fraud","other"]}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"Paginated list of disputes"},"401":{"description":"Unauthorized"}}}},"/api/disputes/{id}":{"get":{"summary":"Get a specific dispute by ID","tags":["Disputes"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Dispute ID"}],"responses":{"200":{"description":"Dispute details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"transaction_id":{"type":"integer"},"status":{"type":"string"},"reason":{"type":"string"},"category":{"type":"string"},"priority":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Dispute not found"}}}},"/api/disputes/{id}/status":{"patch":{"summary":"Update dispute status (Admin only)","description":"Change the dispute status and optionally add a resolution note.","tags":["Disputes"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["under_review","escalated","resolved","closed"],"example":"resolved"},"resolution_note":{"type":"string","example":"Payment was delayed due to network congestion; funds have now been delivered."},"assigned_admin_id":{"type":"integer"}}}}}},"responses":{"200":{"description":"Dispute status updated"},"403":{"description":"Admin access required"},"404":{"description":"Dispute not found"}}}},"/api/disputes/{id}/escalate":{"post":{"summary":"Escalate a dispute","description":"Escalate an open dispute to a higher priority level with a detailed reason.","tags":["Disputes"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reason"],"properties":{"reason":{"type":"string","minLength":10,"maxLength":1000,"example":"The recipient has not responded in 48 hours and the funds appear stuck on-chain."}}}}}},"responses":{"200":{"description":"Dispute escalated"},"404":{"description":"Dispute not found"}}}},"/api/disputes/{id}/assign":{"patch":{"summary":"Assign a dispute to an admin","description":"Assign an open or under-review dispute to a specific admin for resolution.","tags":["Disputes"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["admin_id"],"properties":{"admin_id":{"type":"integer","example":5}}}}}},"responses":{"200":{"description":"Dispute assigned"},"403":{"description":"Admin access required"},"404":{"description":"Dispute not found"}}}},"/api/disputes/{id}/comments":{"post":{"summary":"Add a comment to a dispute","tags":["Disputes"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["comment"],"properties":{"comment":{"type":"string","minLength":1,"maxLength":2000,"example":"I've checked the on-chain transaction and the funds were indeed sent but haven't been credited."}}}}}},"responses":{"201":{"description":"Comment added"}}},"get":{"summary":"Get comments for a dispute","tags":["Disputes"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"List of dispute comments"},"404":{"description":"Dispute not found"}}}},"/api/exports/request":{"post":{"summary":"Request transaction export","tags":["Exports"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["format"],"properties":{"format":{"type":"string","enum":["csv","pdf"]},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"type":{"type":"string","enum":["send","receive","swap"]},"status":{"type":"string","enum":["pending","completed","failed"]},"tokenId":{"type":"number"},"minAmount":{"type":"number"},"maxAmount":{"type":"number"}}}}}},"responses":{"200":{"description":"Export generated successfully"},"202":{"description":"Export queued for processing"}}}},"/api/exports/download/{fileName}":{"get":{"summary":"Download exported file","tags":["Exports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"fileName","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File download"}}}},"/api/exports/status/{jobId}":{"get":{"summary":"Get export job status","tags":["Exports"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"jobId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Job status information"}}}},"/api/fees":{"get":{"summary":"Calculate fees for a withdrawal","description":"Calculate the fee breakdown for a bank, crypto, or tag withdrawal based on the type, chain, token, and amount.","tags":["Fees"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"type","required":true,"schema":{"type":"string","enum":["bank","crypto","tag"]},"description":"Withdrawal type"},{"in":"query","name":"chain","required":true,"schema":{"type":"string"},"description":"Blockchain chain (e.g., base, xlm, lisk, flow, u2u, starknet)"},{"in":"query","name":"token","required":true,"schema":{"type":"string"},"description":"Token symbol (e.g., USDC, USDT, XLM)"},{"in":"query","name":"amount","required":true,"schema":{"type":"number"},"description":"Withdrawal amount"}],"responses":{"200":{"description":"Fee breakdown","content":{"application/json":{"schema":{"type":"object","properties":{"platformFee":{"type":"number","example":50,"description":"Platform fee in the withdrawal currency"},"networkFee":{"type":"number","example":0.01,"description":"Blockchain network fee"},"totalFee":{"type":"number","example":50.01},"feePercentage":{"type":"number","example":0.5,"description":"Fee as percentage of withdrawal amount"},"withdrawalAmount":{"type":"number","example":10000},"netAmount":{"type":"number","example":9949.99}}}}}},"400":{"description":"Missing or invalid parameters"},"401":{"description":"Unauthorized"}}}},"/api/fees/structures":{"get":{"summary":"List all available fee structures","description":"Returns all configured fee structures for each withdrawal type, chain, and token combination.","tags":["Fees"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Fee structures","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","example":"bank"},"chain":{"type":"string","example":"base"},"token":{"type":"string","example":"USDC"},"baseFeePercentage":{"type":"number","example":0.5},"minFee":{"type":"number","example":50},"maxAmount":{"type":"number"},"minAmount":{"type":"number"}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/upload-file":{"post":{"summary":"Upload a file (KYC document, profile image, etc.)","tags":["General"],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}}}}},"responses":{"200":{"description":"File uploaded successfully"}}}},"/api/register-tag":{"post":{"summary":"Register a @tag for an address","description":"Register a unique @tag and associate it with a blockchain wallet address.","tags":["General"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tag","address"],"properties":{"tag":{"type":"string","example":"john_lagos"},"address":{"type":"string","example":"0x1234567890abcdef"},"chain":{"type":"string","example":"base"}}}}}},"responses":{"200":{"description":"Tag registered"}}}},"/api/get-tag-address":{"post":{"summary":"Resolve a @tag to its wallet address","tags":["General"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tag"],"properties":{"tag":{"type":"string","example":"alice"}}}}}},"responses":{"200":{"description":"Tag address resolved","content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string"},"chain":{"type":"string"}}}}}}}}},"/api/get-tag-balance":{"post":{"summary":"Get balance for a @tag","tags":["General"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tag"],"properties":{"tag":{"type":"string","example":"alice"}}}}}},"responses":{"200":{"description":"Tag balance"}}}},"/api/send-to-tag":{"post":{"summary":"Send funds to a @tag","tags":["General"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sender_tag","receiver_tag","amount"],"properties":{"sender_tag":{"type":"string","example":"alice"},"receiver_tag":{"type":"string","example":"bob"},"amount":{"type":"number","example":5}}}}}},"responses":{"200":{"description":"Transfer initiated"}}}},"/api/send-to-wallet":{"post":{"summary":"Send funds to a wallet address","tags":["General"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["sender_tag","receiver_address","amount"],"properties":{"sender_tag":{"type":"string"},"receiver_address":{"type":"string"},"amount":{"type":"number"}}}}}},"responses":{"200":{"description":"Transfer initiated"}}}},"/api/bill/balance":{"get":{"summary":"Check bill payment wallet balance","tags":["General"],"responses":{"200":{"description":"Bill balance"}}}},"/api/bill/data-variations":{"get":{"summary":"List available data bundle variations","tags":["General"],"responses":{"200":{"description":"Data variations list"}}}},"/api/bill/tv-variations":{"get":{"summary":"List available TV subscription variations","tags":["General"],"responses":{"200":{"description":"TV variations list"}}}},"/api/bill/tv-services":{"get":{"summary":"List available TV service providers","tags":["General"],"responses":{"200":{"description":"TV services list"}}}},"/api/bill/betting-services":{"get":{"summary":"List available betting service providers","tags":["General"],"responses":{"200":{"description":"Betting services list"}}}},"/api/bill/electricity-services":{"get":{"summary":"List available electricity service providers","tags":["General"],"responses":{"200":{"description":"Electricity services list"}}}},"/api/bill/airtime-services":{"get":{"summary":"List available airtime service providers","tags":["General"],"responses":{"200":{"description":"Airtime services list"}}}},"/api/bill/data-services":{"get":{"summary":"List available data service providers","tags":["General"],"responses":{"200":{"description":"Data services list"}}}},"/api/bill/requery":{"post":{"summary":"Requery a bill payment transaction","tags":["General"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reference":{"type":"string","example":"BILL_ref_abc123"}}}}}},"responses":{"200":{"description":"Bill transaction status"}}}},"/api/bill/verify-customer":{"post":{"summary":"Verify a bill payment customer","description":"Verify a customer's details before processing a bill payment (e.g., smart card number for TV, meter number for electricity).","tags":["General"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"service_type":{"type":"string","example":"electricity"},"customer_id":{"type":"string","example":"1234567890"}}}}}},"responses":{"200":{"description":"Customer verified"}}}},"/api/exchange-rates":{"get":{"summary":"Get current exchange rates","description":"Returns current crypto-to-fiat exchange rates. Cached for 15 minutes.","tags":["General"],"responses":{"200":{"description":"Exchange rates","content":{"application/json":{"schema":{"type":"object","properties":{"XLM_USD":{"type":"number","example":0.11},"USDC_USD":{"type":"number","example":1},"USD_NGN":{"type":"number","example":1550}}}}}}}}},"/api/convert":{"get":{"summary":"Convert between currencies","description":"Convert an amount between any supported currencies (crypto or fiat).","tags":["General"],"parameters":[{"in":"query","name":"from","required":true,"schema":{"type":"string"},"description":"Source currency"},{"in":"query","name":"to","required":true,"schema":{"type":"string"},"description":"Target currency"},{"in":"query","name":"amount","required":true,"schema":{"type":"number"},"description":"Amount to convert"}],"responses":{"200":{"description":"Converted amount"}}}},"/api/health":{"get":{"summary":"Get overall system health","tags":["Health"],"responses":{"200":{"description":"System is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"OK"}}}}}},"500":{"description":"System is unhealthy"}}}},"/api/api/crypto-rate":{"get":{"summary":"Get cryptocurrency rate","tags":["General"],"parameters":[{"in":"query","name":"token","required":true,"schema":{"type":"string"},"description":"Token symbol"}],"responses":{"200":{"description":"Crypto rate data"}}}},"/api/api/fiat-rate":{"get":{"summary":"Get fiat currency rate","tags":["General"],"parameters":[{"in":"query","name":"currency","required":true,"schema":{"type":"string"},"description":"Currency code (e.g., NGN, USD)"}],"responses":{"200":{"description":"Fiat rate data"}}}},"/api/api/rates/ngn":{"get":{"summary":"Get NGN exchange rate","description":"Returns the current USD-to-NGN exchange rate from cache.","tags":["General"],"responses":{"200":{"description":"NGN rate","content":{"application/json":{"schema":{"type":"object","properties":{"USD":{"type":"number","example":1},"NGN":{"type":"number","example":1550}}}}}},"500":{"description":"Failed to fetch NGN rate"}}}},"/api/health/ready":{"get":{"summary":"Readiness probe","tags":["Health"],"responses":{"200":{"description":"System is ready to accept traffic"},"503":{"description":"System is not ready"}}}},"/api/health/live":{"get":{"summary":"Liveness probe","tags":["Health"],"responses":{"200":{"description":"System is alive"},"503":{"description":"System is not alive"}}}},"/api/versions":{"get":{"summary":"List available API versions and their deprecation status","tags":["Versioning"],"responses":{"200":{"description":"Version metadata"}}}},"/api/keys":{"post":{"summary":"Register signing keys for a blockchain wallet","description":"Register cryptographic signing keys needed for on-chain transactions on supported chains (Stellar, EVM, Starknet).","tags":["Signing Keys"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"stellarPublicKey":{"type":"string","example":"GABCDXYZ1234567890ABCDEF...","description":"Stellar public key for signing transactions"},"evmPublicKey":{"type":"string","example":"0x1234567890abcdef1234567890abcdef12345678","description":"EVM-compatible chain public key"},"starknetPublicKey":{"type":"string","example":"0x028add5d29f4aa3e4144ba1a85d509de6719e58c...","description":"Starknet public key"}}}}}},"responses":{"200":{"description":"Signing keys registered successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"registeredChains":{"type":"array","items":{"type":"string"},"example":["stellar","evm","starknet"]}}}}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}}},"/api/kycs":{"post":{"summary":"Submit KYC verification documents","description":"Submit identity verification documents (passport, selfie, address proof) for KYC review. Required for withdrawals and higher transaction limits.","tags":["KYC"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["idType","idNumber"],"properties":{"idType":{"type":"string","example":"passport","description":"Type of ID document (passport, drivers_license, national_id)"},"idNumber":{"type":"string","example":"A12345678"},"idImage":{"type":"string","format":"uri","example":"https://cdn.example.com/john_passport.jpg"},"selfieImage":{"type":"string","format":"uri"},"addressProof":{"type":"string","format":"uri"},"country":{"type":"string","example":"NG"},"dateOfBirth":{"type":"string","format":"date","example":"1990-05-15"}}}}}},"responses":{"201":{"description":"KYC submitted for review","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","example":"pending"}}}}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"}}},"get":{"summary":"Get current user's KYC record","tags":["KYC"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"KYC record for the authenticated user","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","enum":["pending","approved","rejected"]},"idType":{"type":"string"}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/kycs/status":{"get":{"summary":"Get KYC verification status","description":"Returns whether the user's KYC is pending, approved, or rejected. Approved KYC is required for bank withdrawals.","tags":["KYC"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"KYC status","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"status":{"type":"string","enum":["pending","approved","rejected"],"example":"approved"},"message":{"type":"string","example":"KYC verification approved"}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/kycs/{id}":{"get":{"summary":"Get KYC record by ID","tags":["KYC"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"KYC record details"},"404":{"description":"KYC record not found"}}},"put":{"summary":"Update KYC record","description":"Update or resubmit KYC documents after rejection.","tags":["KYC"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"idType":{"type":"string"},"idNumber":{"type":"string"},"idImage":{"type":"string"},"selfieImage":{"type":"string"},"addressProof":{"type":"string"}}}}}},"responses":{"200":{"description":"KYC updated"}}},"delete":{"summary":"Delete a KYC record","tags":["KYC"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"KYC deleted"}}}},"/api/kycs/{id}/approve":{"post":{"summary":"Approve a KYC submission (Admin only)","description":"Admin-only endpoint to approve a pending KYC submission, enabling the user to access withdrawals and higher transaction limits.","tags":["KYC"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"KYC record ID to approve"}],"responses":{"200":{"description":"KYC approved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","example":"approved"}}}}}}}},"403":{"description":"Admin access required"},"404":{"description":"KYC record not found"}}}},"/api/kycs/{id}/reject":{"post":{"summary":"Reject a KYC submission (Admin only)","description":"Admin-only endpoint to reject a KYC submission with a reason. The user will be notified and can resubmit.","tags":["KYC"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"KYC record ID to reject"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["reason"],"properties":{"reason":{"type":"string","example":"Document image is blurry. Please resubmit with a clearer photo."}}}}}},"responses":{"200":{"description":"KYC rejected","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","example":"rejected"},"reason":{"type":"string"}}}}}}}},"403":{"description":"Admin access required"},"404":{"description":"KYC record not found"}}}},"/api/notifications":{"get":{"summary":"Get user notifications","description":"List all notifications for the authenticated user, sorted by newest first.","tags":["Notifications"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of notifications","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1},"title":{"type":"string","example":"Payment Received"},"body":{"type":"string","example":"You received 50 USDC from @alice"},"type":{"type":"string","example":"payment"},"is_read":{"type":"boolean","example":false},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/notifications/unread":{"get":{"summary":"Get unread notifications","tags":["Notifications"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of unread notifications","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"body":{"type":"string"}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/notifications/preferences":{"get":{"summary":"Get notification preferences","description":"Retrieve the user's current notification preferences (push, email, in-app).","tags":["Notifications"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Notification preferences","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"push_enabled":{"type":"boolean","example":true},"email_enabled":{"type":"boolean","example":true},"in_app_enabled":{"type":"boolean","example":true}}}}}}}},"401":{"description":"Unauthorized"}}},"put":{"summary":"Update notification preferences","description":"Toggle push, email, or in-app notification channels.","tags":["Notifications"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"push_enabled":{"type":"boolean","example":true},"email_enabled":{"type":"boolean","example":false},"in_app_enabled":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"Preferences updated"},"401":{"description":"Unauthorized"}}}},"/api/notifications/device-token":{"post":{"summary":"Register a push notification device token","description":"Register a Firebase Cloud Messaging (FCM) device token for receiving push notifications.","tags":["Notifications"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string","example":"fcm_device_token_abc123..."},"platform":{"type":"string","enum":["android","ios","web"],"example":"android"}}}}}},"responses":{"200":{"description":"Device token registered"},"401":{"description":"Unauthorized"}}},"delete":{"summary":"Unregister a push notification device token","description":"Remove a device token to stop sending push notifications to that device.","tags":["Notifications"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Device token removed"},"401":{"description":"Unauthorized"}}}},"/api/notifications/{id}":{"get":{"summary":"Get a specific notification","tags":["Notifications"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Notification details"},"401":{"description":"Unauthorized"},"404":{"description":"Notification not found"}}},"put":{"summary":"Mark a notification as read","tags":["Notifications"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Notification updated"},"404":{"description":"Notification not found"}}},"delete":{"summary":"Delete a notification","tags":["Notifications"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Notification deleted"},"404":{"description":"Notification not found"}}}},"/api/performance":{"get":{"summary":"Get system performance metrics","description":"Returns response time averages, request counts, error rates, and resource utilization metrics. Admin access required.","tags":["Performance"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Performance metrics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"avgResponseTime":{"type":"number","example":145.3,"description":"Average response time in milliseconds"},"totalRequests":{"type":"integer","example":15234},"errorRate":{"type":"number","example":0.02,"description":"Error rate as percentage"},"p95ResponseTime":{"type":"number","example":350}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Admin access required"}}}},"/api/performance/reset":{"post":{"summary":"Reset performance metrics counters","description":"Reset all accumulated performance counters to zero. Admin access required.","tags":["Performance"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Performance metrics reset successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string","example":"Performance metrics reset successfully"}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Admin access required"}}}},"/admin/rate-limits/settings":{"get":{"summary":"Get current rate limit settings","description":"Returns the configured rate limit thresholds for each endpoint tier.","tags":["Rate Limit Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Rate limit configuration","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","description":"Rate limit settings per endpoint"}}}}}},"401":{"description":"Unauthorized"}}}},"/admin/rate-limits/users/{userId}":{"get":{"summary":"Get a user's rate limit status","description":"Returns the current rate limit counters and remaining quota for a specific user.","tags":["Rate Limit Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"userId","required":true,"schema":{"type":"string"},"description":"User ID"}],"responses":{"200":{"description":"User rate limit status"},"401":{"description":"Unauthorized"}}}},"/admin/rate-limits/users/{userId}/tier":{"put":{"summary":"Update a user's rate limit tier","description":"Change a user's rate limit tier (e.g., from free to premium) to adjust their quota.","tags":["Rate Limit Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"userId","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tier"],"properties":{"tier":{"type":"string","enum":["free","basic","premium","enterprise"],"example":"premium"}}}}}},"responses":{"200":{"description":"User tier updated"},"401":{"description":"Unauthorized"}}}},"/admin/rate-limits/api-keys/{keyId}":{"get":{"summary":"Get an API key's rate limit status","tags":["Rate Limit Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"API key rate limit status"},"401":{"description":"Unauthorized"}}}},"/admin/rate-limits/api-keys/{keyId}/rate-limit":{"put":{"summary":"Update an API key's rate limit configuration","tags":["Rate Limit Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"keyId","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"maxRequests":{"type":"integer","example":5000},"windowMs":{"type":"integer","example":3600000}}}}}},"responses":{"200":{"description":"API key rate limit updated"},"401":{"description":"Unauthorized"}}}},"/admin/rate-limits/violations":{"get":{"summary":"Get rate limit violations log","description":"Returns a log of recent rate limit violations across all users and API keys.","tags":["Rate Limit Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Violations log"},"401":{"description":"Unauthorized"}}}},"/api/scheduled-payments":{"post":{"summary":"Create a scheduled payment","description":"Schedule a payment to be executed at a future date. The scheduled date must be within 30 days from now.","tags":["Scheduled Payments"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["recipientTag","amount","scheduledAt"],"properties":{"recipientTag":{"type":"string","pattern":"^[a-zA-Z0-9_]{3,20}$","example":"bob","description":"Recipient's @tag"},"amount":{"type":"number","example":25,"description":"Amount to send"},"asset":{"type":"string","default":"XLM","example":"USDC","description":"Asset code (1-12 uppercase alphanumeric)"},"assetIssuer":{"type":"string","description":"Stellar asset issuer address (required for custom assets)"},"memo":{"type":"string","maxLength":28,"example":"Monthly rent"},"scheduledAt":{"type":"string","format":"date-time","example":"2025-01-15T09:00:00Z","description":"ISO datetime when payment should execute (must be in the future, max 30 days)"}}}}}},"responses":{"201":{"description":"Scheduled payment created","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer","example":1},"status":{"type":"string","example":"pending"},"scheduledAt":{"type":"string","format":"date-time"}}}}}}}},"400":{"description":"Validation error (e.g., scheduled date in past)"},"401":{"description":"Unauthorized"},"429":{"description":"Rate limit exceeded"}}},"get":{"summary":"List user's scheduled payments","description":"Returns all scheduled payments for the authenticated user, with optional status filtering.","tags":["Scheduled Payments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"status","schema":{"type":"string","enum":["pending","processing","completed","failed","cancelled"]}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"in":"query","name":"offset","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"List of scheduled payments"},"401":{"description":"Unauthorized"}}}},"/api/scheduled-payments/upcoming":{"get":{"summary":"Get upcoming pending scheduled payments","description":"Returns scheduled payments that are due to execute soon.","tags":["Scheduled Payments"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Upcoming scheduled payments","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/scheduled-payments/{id}":{"get":{"summary":"Get a specific scheduled payment","tags":["Scheduled Payments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Scheduled payment ID"}],"responses":{"200":{"description":"Scheduled payment details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"recipientTag":{"type":"string"},"amount":{"type":"number"},"status":{"type":"string"},"scheduledAt":{"type":"string"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Scheduled payment not found"}}}},"/api/scheduled-payments/{id}/cancel":{"patch":{"summary":"Cancel a scheduled payment","description":"Cancel a pending scheduled payment. Only payments with status \"pending\" can be cancelled.","tags":["Scheduled Payments"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Scheduled payment cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"status":{"type":"string","example":"cancelled"}}}}}}}},"400":{"description":"Cannot cancel a payment that is not pending"},"404":{"description":"Scheduled payment not found"}}}},"/api/tags/search":{"get":{"summary":"Search for tags","description":"Search registered tags by name. Rate-limited to 10 requests per minute per IP.","tags":["Tags"],"parameters":[{"in":"query","name":"q","required":true,"schema":{"type":"string"},"description":"Search query string"}],"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"tag":{"type":"string","example":"alice"},"walletAddress":{"type":"string"},"chain":{"type":"string"}}}}}}}}},"429":{"description":"Rate limit exceeded"}}}},"/api/tags":{"post":{"summary":"Register a new tag","description":"Create and register a unique @tag for a user. The tag must be 3-20 alphanumeric characters (underscores allowed).","tags":["Tags"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["tag"],"properties":{"tag":{"type":"string","pattern":"^[a-zA-Z0-9_]{3,20}$","example":"john_lagos"},"userId":{"type":"string","description":"User ID to associate with the tag"}}}}}},"responses":{"201":{"description":"Tag registered successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"tag":{"type":"string","example":"john_lagos"},"walletAddress":{"type":"string"}}}}}}}},"400":{"description":"Validation error or tag already taken"}}}},"/api/tags/check/{tag}":{"get":{"summary":"Check if a tag is available for registration","description":"Returns whether a specific tag name is available (not yet registered).","tags":["Tags"],"parameters":[{"in":"path","name":"tag","required":true,"schema":{"type":"string"},"description":"Tag name to check"}],"responses":{"200":{"description":"Tag availability status","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean","example":true},"tag":{"type":"string"}}}}}},"429":{"description":"Rate limit exceeded"}}}},"/api/tags/{tag}":{"get":{"summary":"Resolve a tag to its wallet address","description":"Given a @tag, return the associated wallet address and chain information.","tags":["Tags"],"parameters":[{"in":"path","name":"tag","required":true,"schema":{"type":"string"},"description":"Tag name to resolve"}],"responses":{"200":{"description":"Tag resolved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"tag":{"type":"string","example":"alice"},"walletAddress":{"type":"string","example":"0x1234567890abcdef"},"chain":{"type":"string","example":"flow"}}}}}}}},"404":{"description":"Tag not found"}}}},"/api/tags/{tag}/transfer":{"put":{"summary":"Transfer a tag to another user","description":"Transfer ownership of a @tag to a different user. Requires authentication as the current tag owner.","tags":["Tags"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"tag","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["newOwnerId"],"properties":{"newOwnerId":{"type":"string","example":"user_uuid_456"}}}}}},"responses":{"200":{"description":"Tag transferred successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Not the current tag owner"},"404":{"description":"Tag not found"}}}},"/api/tokens":{"get":{"summary":"Get all tokens","tags":["Tokens"],"responses":{"200":{"description":"List of tokens"}}},"post":{"summary":"Create a new token","tags":["Tokens"],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Token created"}}}},"/api/tokens/{id}":{"get":{"summary":"Get token by ID","tags":["Tokens"],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Token details"}}},"put":{"summary":"Update token","tags":["Tokens"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Token updated"}}},"delete":{"summary":"Delete token","tags":["Tokens"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Token deleted"}}}},"/api/transactions/search":{"get":{"summary":"Search transactions with filters","tags":["Transaction Search"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"q","schema":{"type":"string"},"description":"Full-text search string"},{"in":"query","name":"status","schema":{"type":"string","enum":["completed","pending","failed"]}},{"in":"query","name":"type","schema":{"type":"string","enum":["credit","debit","payment","swap"]}},{"in":"query","name":"chain","schema":{"type":"string","default":20,"enum":["XLM","BASE","LSK","FLOW","U2U","STRK"]}},{"in":"query","name":"token","schema":{"type":"string"}},{"in":"query","name":"from","schema":{"type":"string","format":"date"},"description":"Start date (ISO format)"},{"in":"query","name":"to","schema":{"type":"string","format":"date"},"description":"End date (ISO format)"},{"in":"query","name":"minAmount","schema":{"type":"number"},"description":"Minimum USD value"},{"in":"query","name":"maxAmount","schema":{"type":"number"},"description":"Maximum USD value"},{"in":"query","name":"sortBy","schema":{"type":"string","enum":["date","amount","relevance"],"default":"relevance"}},{"in":"query","name":"sortDir","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"in":"query","name":"cursor","schema":{"type":"string"},"description":"Opaque cursor for next page"}],"responses":{"200":{"description":"Search results with pagination","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"type":{"type":"string"},"status":{"type":"string"},"amount":{"type":"number"},"usd_value":{"type":"number"},"chain":{"type":"string"},"token":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","properties":{"next_cursor":{"type":"string"},"has_more":{"type":"boolean"}}}}}}}},"401":{"description":"Unauthorized"},"429":{"description":"Search rate limit exceeded (30 per minute)"}},"description":"Full-text and filtered search across transaction history. Supports keyword search, status/chain/token filters, amount ranges, and date ranges. Returns cursor-based paginated results."}},"/api/transactions":{"get":{"summary":"Get user's transaction history","description":"Returns paginated transaction history for the authenticated user. Supports `transactions:read` scope for API keys.","tags":["Transactions"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Transaction list","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Transaction"}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/transactions/tag/{tag}":{"get":{"summary":"Get transactions associated with a @tag","tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"tag","required":true,"schema":{"type":"string"},"description":"Tag name to query transactions for"}],"responses":{"200":{"description":"Transactions for the tag"},"401":{"description":"Unauthorized"}}}},"/api/transactions/{id}":{"get":{"summary":"Get a specific transaction by ID","tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Transaction ID"}],"responses":{"200":{"description":"Transaction details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Transaction not found"}}},"put":{"summary":"Update a transaction (e.g., add a note)","tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Transaction"}}}},"responses":{"200":{"description":"Transaction updated"},"404":{"description":"Transaction not found"}}},"delete":{"summary":"Soft-delete a transaction","tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Transaction deleted"},"404":{"description":"Transaction not found"}}}},"/api/transactions/payment":{"post":{"summary":"Process a @tag payment","description":"Send a payment from one @tag to another. Supports XLM and custom Stellar assets. Requires `transactions:write` or `payments:send` scope.","tags":["Transactions"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessPaymentRequest"}}}},"responses":{"200":{"description":"Payment processed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"transaction_id":{"type":"integer","example":42},"tx_hash":{"type":"string","example":"0xabc123..."},"status":{"type":"string","example":"completed"}}}}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"422":{"description":"Insufficient balance or transfer failed"}}}},"/api/transactions/payment/limits":{"get":{"summary":"Get payment limits","description":"Returns the minimum and maximum payment amounts, fee percentages, and other limit configurations.","tags":["Transactions"],"responses":{"200":{"description":"Payment limits","content":{"application/json":{"schema":{"type":"object","properties":{"maxAmount":{"type":"number","example":1000000},"minAmount":{"type":"number","example":1},"baseFeePercentage":{"type":"number","example":0.5},"minFee":{"type":"number","example":50}}}}}}}}},"/api/transactions/tag/{tag}/history":{"get":{"summary":"Get payment history for a @tag","tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"tag","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Payment history"},"401":{"description":"Unauthorized"}}}},"/api/transactions/search/export":{"get":{"summary":"Export search results as CSV","description":"Same filter parameters as search, but returns all matching results as a downloadable CSV file instead of paginated JSON.","tags":["Transaction Search"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"query","name":"q","schema":{"type":"string"}},{"in":"query","name":"status","schema":{"type":"string","enum":["completed","pending","failed"]}},{"in":"query","name":"type","schema":{"type":"string","enum":["credit","debit","payment","swap"]}},{"in":"query","name":"chain","schema":{"type":"string"}},{"in":"query","name":"token","schema":{"type":"string"}},{"in":"query","name":"from","schema":{"type":"string","format":"date"}},{"in":"query","name":"to","schema":{"type":"string","format":"date"}},{"in":"query","name":"minAmount","schema":{"type":"number"}},{"in":"query","name":"maxAmount","schema":{"type":"number"}}],"responses":{"200":{"description":"CSV file download","content":{"text/csv":{"schema":{"type":"string"}}}},"401":{"description":"Unauthorized"},"429":{"description":"Search rate limit exceeded"}}}},"/api/users/profile":{"get":{"summary":"Get user profile","tags":["Users"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User profile retrieved successfully"},"401":{"description":"Unauthorized"}}},"post":{"summary":"Update user profile","tags":["Users"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":"string"}}}}}},"responses":{"200":{"description":"Profile updated"},"401":{"description":"Unauthorized"}}}},"/api/users/dashboard-summary":{"get":{"summary":"Get user dashboard summary","tags":["Users"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Dashboard summary retrieved successfully"},"401":{"description":"Unauthorized"}}}},"/api/ussd/callback":{"post":{"summary":"USSD gateway callback","description":"Public endpoint that receives USSD session data from the mobile network gateway. Handles menu navigation, balance checks, and payment initiation via USSD codes.","tags":["USSD"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","example":"session_123456"},"serviceCode":{"type":"string","example":"*737*42#"},"phoneNumber":{"type":"string","example":"08012345678"},"text":{"type":"string","example":"1*50*alice","description":"USSD input text from the user's menu selections"}}}}}},"responses":{"200":{"description":"USSD menu response","content":{"application/json":{"schema":{"type":"object","properties":{"response":{"type":"string","example":"CON Enter amount to send:\n"},"action":{"type":"string","example":"prompt"}}}}}}}}},"/api/ussd/stats":{"get":{"summary":"Get USSD usage statistics","description":"Returns session counts, active users, and transaction volume via USSD. Admin access required.","tags":["USSD"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"USSD statistics","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"totalSessions":{"type":"integer","example":5000},"activeUsers":{"type":"integer","example":250},"transactionVolume":{"type":"number","example":150000}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Admin access required"}}}},"/api/wallets":{"get":{"summary":"Get the authenticated user's wallets","description":"Returns all wallets and balances associated with the authenticated user across all supported chains.","tags":["Wallets"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User wallets","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer","example":1},"chain":{"type":"string","example":"stellar"},"address":{"type":"string","example":"GABCDXYZ1234567890..."},"balances":{"type":"array","items":{"type":"object","properties":{"token":{"type":"string","example":"USDC"},"amount":{"type":"number","example":500}}}}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/wallets/send-to-tag":{"post":{"summary":"Send funds to another user via @tag","description":"Transfer tokens to another registered user's @tag on any supported chain (base, lisk, flow, u2u, starknet). For Flow, uses Flow EVM (0x + 16 hex chars).\n","tags":["Wallets"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["receiver_tag","amount","balance_id"],"properties":{"receiver_tag":{"type":"string","example":"alice","description":"Recipient's @tag (3-20 alphanumeric/underscore)"},"amount":{"type":"number","example":1.5,"description":"Amount to send (positive, up to 18 decimal places)"},"balance_id":{"type":"integer","example":42,"description":"Sender's balance record ID (determines chain + token)"}}}}}},"responses":{"200":{"description":"Transfer initiated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","example":"success"},"txHash":{"type":"string","example":"0xabc123..."}}}}}},"400":{"description":"Validation error or missing fields"},"422":{"description":"Insufficient balance or transfer failed"},"429":{"description":"Another transaction already in progress"}}}},"/api/wallets/send-to-wallet":{"post":{"summary":"Send funds to an external blockchain address","description":"Withdraw tokens to an external wallet address on any supported chain. Flow EVM addresses must be 0x followed by exactly 16 hex characters (e.g. 0x1234567890abcdef). Requires 2FA.\n","tags":["Wallets"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["receiver_address","amount","balance_id"],"properties":{"receiver_address":{"type":"string","example":"0x1234567890abcdef","description":"Destination blockchain address. Format depends on chain: Flow EVM: 0x + 16 hex chars, EVM chains: 0x + 40 hex chars, Starknet: 0x + up to 64 hex chars\n"},"amount":{"type":"number","example":0.5},"balance_id":{"type":"integer","example":42}}}}}},"responses":{"200":{"description":"Withdrawal initiated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"string","example":"success"},"txHash":{"type":"string"}}}}}},"400":{"description":"Invalid address format or missing fields"},"422":{"description":"Insufficient balance or transfer failed"}}}},"/api/wallets/{id}":{"get":{"summary":"Get a specific wallet by ID","tags":["Wallets"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Wallet ID"}],"responses":{"200":{"description":"Wallet details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"chain":{"type":"string"},"address":{"type":"string"},"balances":{"type":"array"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Wallet not found"}}},"put":{"summary":"Update wallet settings","tags":["Wallets"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"label":{"type":"string","example":"My Stellar Wallet"},"is_active":{"type":"boolean","example":true}}}}}},"responses":{"200":{"description":"Wallet updated"},"404":{"description":"Wallet not found"}}},"delete":{"summary":"Delete a wallet","tags":["Wallets"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Wallet deleted"},"404":{"description":"Wallet not found"}}}},"/api/admin/webhooks/dlq":{"get":{"summary":"View dead-letter queue entries","description":"Returns all webhook events that failed delivery and exhausted retry attempts. Admin access required.","tags":["Webhook Admin"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Dead-letter queue entries","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"webhook_id":{"type":"integer"},"event_type":{"type":"string"},"payload":{"type":"object"},"last_error":{"type":"string"},"attempts":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Unauthorized"},"403":{"description":"Admin access required"}}}},"/api/admin/webhooks/dlq/{event_id}/retry":{"post":{"summary":"Retry a dead-letter queue event","description":"Manually retry a failed webhook delivery event from the DLQ. Admin access required.","tags":["Webhook Admin"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"event_id","required":true,"schema":{"type":"integer"},"description":"Dead-letter event ID to retry"}],"responses":{"200":{"description":"Retry initiated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string","example":"DLQ event retried successfully"}}}}}},"403":{"description":"Admin access required"},"404":{"description":"DLQ event not found"}}}},"/api/webhooks/events":{"get":{"summary":"List available webhook event types","description":"Public endpoint returning all event types that can be subscribed to via webhooks.","tags":["Webhooks"],"responses":{"200":{"description":"List of event types","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","example":true},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"}}}}}}}}}},"/api/webhooks/verify":{"post":{"summary":"Verify a webhook payload signature","description":"Public utility endpoint to verify that a webhook payload was signed with the correct secret. Useful for debugging webhook integrations.","tags":["Webhooks"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["payload","signature","secret"],"properties":{"payload":{"type":"object","description":"The webhook payload body to verify"},"signature":{"type":"string","description":"The HMAC-SHA256 signature received in the webhook header"},"secret":{"type":"string","description":"The webhook signing secret"}}}}}},"responses":{"200":{"description":"Signature verification result","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"valid":{"type":"boolean","example":true}}}}}}}}},"/api/webhooks":{"post":{"summary":"Register a new webhook","description":"Create a webhook subscription to receive event notifications at a specified URL. Requires `webhooks:write` scope for API key authentication.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookRegistration"}}}},"responses":{"201":{"description":"Webhook registered successfully. The secret is returned only once.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string","example":"Webhook registered. Store the secret — it will not be shown again."},"data":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"secret":{"type":"string"}}}}}}}},"400":{"description":"Validation error or invalid URL"}}},"get":{"summary":"List user's webhooks","description":"Returns all webhook subscriptions for the authenticated user. Requires `webhooks:read` scope for API keys.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"List of webhooks","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"url":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"is_active":{"type":"boolean"}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/webhooks/{id}":{"get":{"summary":"Get a specific webhook by ID","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Webhook ID"}],"responses":{"200":{"description":"Webhook details"},"403":{"description":"Forbidden — not the webhook owner"},"404":{"description":"Webhook not found"}}},"put":{"summary":"Update a webhook","description":"Update the URL, events, or active status of an existing webhook. Requires `webhooks:write` scope.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventType"}},"is_active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Webhook updated"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"}}},"delete":{"summary":"Delete a webhook","description":"Permanently remove a webhook subscription. Requires `webhooks:write` scope.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Webhook deleted"},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"}}}},"/api/webhooks/{id}/rotate-secret":{"post":{"summary":"Rotate a webhook's signing secret","description":"Generate a new signing secret for a webhook. The old secret will no longer be valid. Requires `webhooks:write` scope.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Secret rotated successfully. New secret returned only once.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"new_secret":{"type":"string"}}}}}}}},"403":{"description":"Forbidden"},"404":{"description":"Webhook not found"}}}},"/api/webhooks/{id}/deliveries":{"get":{"summary":"Get webhook delivery history","description":"Returns the delivery history (status, attempts, timestamps) for a webhook. Requires `webhooks:read` scope.","tags":["Webhooks"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Delivery history","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDelivery"}}}}}}},"404":{"description":"Webhook not found"}}}},"/api/withdrawals/initiate":{"post":{"summary":"Initiate a bank withdrawal","description":"Start a fiat withdrawal from crypto balance to a linked Nigerian bank account. Creates a withdrawal request that will be processed via Paystack or Monnify.","tags":["Withdrawals"],"security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amount","bankAccountId"],"properties":{"amount":{"type":"number","example":50000,"description":"Amount in NGN to withdraw"},"bankAccountId":{"type":"integer","example":1,"description":"ID of the linked bank account to receive funds"},"reference":{"type":"string","description":"Optional custom reference for tracking"}}}}}},"responses":{"200":{"description":"Withdrawal initiated","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"reference":{"type":"string","example":"WD_ref_abc123"},"status":{"type":"string","example":"pending"},"amount":{"type":"number"}}}}}}}},"400":{"description":"Validation error or insufficient balance"},"401":{"description":"Unauthorized"}}}},"/api/withdrawals/my":{"get":{"summary":"Get user's withdrawal history","description":"List all withdrawal requests for the authenticated user.","tags":["Withdrawals"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Withdrawal history","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"integer"},"reference":{"type":"string"},"amount":{"type":"number"},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"created_at":{"type":"string","format":"date-time"}}}}}}}}},"401":{"description":"Unauthorized"}}}},"/api/withdrawals/{id}":{"get":{"summary":"Get withdrawal details by ID","tags":["Withdrawals"],"security":[{"bearerAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Withdrawal ID"}],"responses":{"200":{"description":"Withdrawal details","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"integer"},"reference":{"type":"string"},"amount":{"type":"number"},"fee":{"type":"number"},"status":{"type":"string"},"provider":{"type":"string","example":"paystack"},"bank_details":{"type":"object"},"created_at":{"type":"string"}}}}}}}},"401":{"description":"Unauthorized"},"404":{"description":"Withdrawal not found"}}}},"/api/withdrawals/webhooks/paystack":{"post":{"summary":"Paystack withdrawal webhook callback","description":"Webhook endpoint for Paystack to notify the platform about withdrawal status changes. This endpoint is public (no auth required) and validates the Paystack signature.","tags":["Withdrawals"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Paystack webhook event payload","properties":{"event":{"type":"string","example":"transfer.success"},"data":{"type":"object","properties":{"reference":{"type":"string"},"amount":{"type":"number"},"status":{"type":"string"}}}}}}}},"responses":{"200":{"description":"Webhook processed"}}}},"/api/withdrawals/webhooks/monnify":{"post":{"summary":"Monnify withdrawal webhook callback","description":"Webhook endpoint for Monnify to notify the platform about withdrawal status changes. This endpoint is public (no auth required) and validates the Monnify signature.","tags":["Withdrawals"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Monnify webhook event payload"}}}},"responses":{"200":{"description":"Webhook processed"}}}}},"tags":[{"name":"Analytics","description":"Admin-only analytics and reporting endpoints (Redis-cached, 5 min TTL)"},{"name":"API Keys","description":"API key management for third-party integrations"},{"name":"Audit Logs","description":"Audit trail for all user and admin actions"},{"name":"Authentication","description":"User registration, login, and two-factor authentication (2FA)"},{"name":"Backup Admin","description":"Database backup management for administrators"},{"name":"Balances","description":"User balance management"},{"name":"Bank Accounts","description":"Nigerian bank account management for fiat withdrawals"},{"name":"Batch Payments","description":"Batch payment processing for multiple recipients at once"},{"name":"Bill Payments","description":"Nigerian bill payments (airtime, data, TV, electricity, betting)"},{"name":"Chains","description":"Blockchain chain configuration and metadata"},{"name":"Circuit Breaker","description":"Circuit breaker status monitoring for blockchain service calls"},{"name":"Disputes","description":"Transaction dispute management and resolution"},{"name":"Exports","description":"Transaction export management"},{"name":"Fees","description":"Fee calculation and fee structure queries"},{"name":"General","description":"General utility endpoints — tag registration, balance lookup, transfers, exchange rates, and bill services"},{"name":"Health","description":"System health and readiness checks"},{"name":"Signing Keys","description":"Blockchain signing key registration for wallet operations"},{"name":"KYC","description":"Know Your Customer (KYC) verification and admin review"},{"name":"Notifications","description":"Push notification management and preferences"},{"name":"Performance","description":"System performance metrics and monitoring (Admin only)"},{"name":"Rate Limit Admin","description":"Rate limit configuration and monitoring (Admin dashboard)"},{"name":"Scheduled Payments","description":"Schedule future payments (recurring or one-time)"},{"name":"Tags","description":"Tag (@Tag) resolution, registration, and transfer"},{"name":"Tokens","description":"Crypto token management"},{"name":"Transactions","description":"Transaction history, payment processing, and receipt management"},{"name":"Transaction Search","description":"Full-text and filtered search across transaction history"},{"name":"Users","description":"User profile and dashboard management"},{"name":"USSD","description":"USSD gateway integration for mobile-based transactions"},{"name":"Wallets","description":"Wallet management, @tag transfers, and external withdrawals"},{"name":"Webhook Admin","description":"Webhook dead-letter queue (DLQ) management for administrators"},{"name":"Webhooks","description":"Webhook registration, management, and event delivery tracking"},{"name":"Withdrawals","description":"Bank withdrawal initiation and webhook callbacks"}]}