{
"openapi": "3.0.3",
"info": {
"title": "Cedros Login API",
"description": "Authentication and authorization service supporting JWT tokens, API keys, Solana wallet auth, and organization management.",
"version": "1.0.0",
"contact": {
"name": "Cedros"
}
},
"servers": [
{
"url": "/auth",
"description": "Default mount path (adjust based on your deployment)"
}
],
"tags": [
{"name": "discovery", "description": "Service discovery and documentation"},
{"name": "auth", "description": "Authentication (login, register, tokens)"},
{"name": "solana", "description": "Solana wallet authentication (recommended for agents)"},
{"name": "api-keys", "description": "API key management"},
{"name": "user", "description": "Current user operations"},
{"name": "organizations", "description": "Organization management"},
{"name": "members", "description": "Organization member management"},
{"name": "roles", "description": "Custom role management"},
{"name": "policies", "description": "ABAC policy management"},
{"name": "invites", "description": "Organization invitations"},
{"name": "mfa", "description": "Multi-factor authentication"},
{"name": "sessions", "description": "Session management"},
{"name": "admin", "description": "System administration"},
{"name": "wallet", "description": "Embedded Solana wallet operations"},
{"name": "setup", "description": "First-run setup (no auth required)"},
{"name": "kyc", "description": "KYC identity verification"},
{"name": "accreditation", "description": "Accredited investor verification"},
{"name": "referrals", "description": "Referral rewards and payouts"},
{"name": "access-codes", "description": "Signup access code management"},
{"name": "webhooks", "description": "External service webhook callbacks"}
],
"paths": {
"/discovery": {
"get": {
"tags": ["discovery"],
"summary": "Get authentication discovery info",
"description": "Returns available authentication methods and usage instructions. Designed for AI agents to discover how to authenticate.",
"operationId": "getAuthConfig",
"responses": {
"200": {
"description": "Discovery information",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AuthConfigResponse"}
}
}
}
}
}
},
"/openapi.json": {
"get": {
"tags": ["discovery"],
"summary": "Get OpenAPI specification",
"operationId": "getOpenApiSpec",
"responses": {
"200": {
"description": "OpenAPI 3.0 specification",
"content": {"application/json": {}}
}
}
}
},
"/health": {
"get": {
"tags": ["discovery"],
"summary": "Health check",
"operationId": "healthCheck",
"responses": {
"200": {"description": "Service is healthy"}
}
}
},
"/register": {
"post": {
"tags": ["auth"],
"summary": "Register new user",
"operationId": "register",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/RegisterRequest"}
}
}
},
"responses": {
"200": {
"description": "Registration successful",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AuthResponse"}
}
}
}
}
}
},
"/login": {
"post": {
"tags": ["auth"],
"summary": "Login with email/password",
"operationId": "login",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/LoginRequest"}
}
}
},
"responses": {
"200": {
"description": "Login successful",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AuthResponse"}
}
}
}
}
}
},
"/refresh": {
"post": {
"tags": ["auth"],
"summary": "Refresh access token",
"operationId": "refresh",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/RefreshRequest"}
}
}
},
"responses": {
"200": {
"description": "Token refreshed",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AuthResponse"}
}
}
}
}
}
},
"/logout": {
"post": {
"tags": ["auth"],
"summary": "Logout (revoke session)",
"operationId": "logout",
"security": [{"bearerAuth": []}],
"responses": {
"200": {"description": "Logged out successfully"}
}
}
},
"/instant-link": {
"post": {
"tags": ["auth"],
"summary": "Send instant sign-in link",
"description": "Requests a passwordless sign-in link by email. Always returns a generic success message to prevent email enumeration.",
"operationId": "sendInstantLink",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/InstantLinkRequest"}
}
}
},
"responses": {
"200": {
"description": "Request accepted",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/MessageResponse"}
}
}
}
}
}
},
"/instant-link/verify": {
"post": {
"tags": ["auth"],
"summary": "Verify instant sign-in link and login",
"description": "Verifies a one-time token from an instant sign-in email. On success returns an authenticated session (cookies) and/or tokens. If the user has MFA enabled, returns an MFA-required response.",
"operationId": "verifyInstantLink",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/VerifyInstantLinkRequest"}
}
}
},
"responses": {
"200": {
"description": "Verification result",
"content": {
"application/json": {
"schema": {
"oneOf": [
{"$ref": "#/components/schemas/AuthResponse"},
{"$ref": "#/components/schemas/MfaRequiredResponse"}
]
}
}
}
}
}
}
},
"/solana/challenge": {
"post": {
"tags": ["solana"],
"summary": "Get Solana auth challenge",
"description": "Request a challenge nonce to sign with your Solana wallet. This is the first step in Solana wallet authentication.",
"operationId": "solanaChallenge",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SolanaChallengeRequest"}
}
}
},
"responses": {
"200": {
"description": "Challenge created",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SolanaChallengeResponse"}
}
}
}
}
}
},
"/solana": {
"post": {
"tags": ["solana"],
"summary": "Authenticate with Solana wallet",
"description": "Complete authentication by submitting the signed challenge. Returns JWT tokens and API key for new users.",
"operationId": "solanaAuth",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SolanaAuthRequest"}
}
}
},
"responses": {
"200": {
"description": "Authentication successful",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AuthResponse"}
}
}
}
}
}
},
"/api-key/validate": {
"post": {
"tags": ["api-keys"],
"summary": "Validate an API key",
"operationId": "validateApiKey",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ValidateApiKeyRequest"}
}
}
},
"responses": {
"200": {
"description": "Validation result",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ValidateApiKeyResponse"}
}
}
}
}
}
},
"/user": {
"get": {
"tags": ["user"],
"summary": "Get current user",
"operationId": "getUser",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Current user info",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/UserResponse"}
}
}
}
}
}
},
"/user/api-key": {
"get": {
"tags": ["api-keys"],
"summary": "Get current API key info",
"operationId": "getApiKey",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "API key info (masked)",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ApiKeyResponse"}
}
}
}
}
}
},
"/user/api-key/regenerate": {
"post": {
"tags": ["api-keys"],
"summary": "Regenerate API key",
"description": "Invalidates the current API key and generates a new one. The new key is returned in full only once.",
"operationId": "regenerateApiKey",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "New API key generated",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/RegenerateApiKeyResponse"}
}
}
}
}
}
},
"/user/api-keys": {
"get": {
"tags": ["api-keys"],
"summary": "List all API keys",
"description": "Returns metadata for all API keys belonging to the current user.",
"operationId": "listApiKeys",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "List of API keys",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ApiKeyListResponse"}
}
}
}
}
},
"post": {
"tags": ["api-keys"],
"summary": "Create a new API key",
"description": "Creates a new API key with a label. The full key is returned only once.",
"operationId": "createApiKey",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/CreateApiKeyRequest"}
}
}
},
"responses": {
"200": {
"description": "API key created",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/CreateApiKeyResponse"}
}
}
}
}
}
},
"/user/api-keys/{key_id}": {
"delete": {
"tags": ["api-keys"],
"summary": "Delete an API key",
"description": "Deletes a specific API key. If a wallet was linked to this key, it becomes orphaned.",
"operationId": "deleteApiKey",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "key_id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
],
"responses": {
"200": {
"description": "API key deleted",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/MessageResponse"}
}
}
}
}
}
},
"/wallet/list": {
"get": {
"tags": ["wallet"],
"summary": "List all wallets",
"description": "Returns all wallets for the current user, including the default wallet and per-API-key wallets.",
"operationId": "listWallets",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "List of wallets",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/WalletListResponse"}
}
}
}
}
}
},
"/wallet/rotate": {
"post": {
"tags": ["wallet"],
"summary": "Rotate wallet",
"description": "Deletes the current wallet and creates a new one with a new keypair. This is irreversible — any funds at the old address are NOT migrated.",
"operationId": "walletRotate",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/WalletRotateRequest"}
}
}
},
"responses": {
"200": {
"description": "Wallet rotated",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/MessageResponse"}
}
}
}
}
}
},
"/orgs": {
"get": {
"tags": ["organizations"],
"summary": "List user's organizations",
"operationId": "listOrgs",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "limit",
"in": "query",
"schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 50}
},
{
"name": "offset",
"in": "query",
"schema": {"type": "integer", "minimum": 0, "default": 0}
}
],
"responses": {
"200": {"description": "List of organizations"}
}
},
"post": {
"tags": ["organizations"],
"summary": "Create organization",
"operationId": "createOrg",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/CreateOrgRequest"}
}
}
},
"responses": {
"200": {"description": "Organization created"}
}
}
},
"/orgs/{org_id}": {
"get": {
"tags": ["organizations"],
"summary": "Get organization",
"operationId": "getOrg",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "Organization details"}
}
},
"patch": {
"tags": ["organizations"],
"summary": "Update organization",
"operationId": "updateOrg",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "Organization updated"}
}
},
"delete": {
"tags": ["organizations"],
"summary": "Delete organization",
"operationId": "deleteOrg",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "Organization deleted"}
}
}
},
"/orgs/{org_id}/switch": {
"post": {
"tags": ["organizations"],
"summary": "Switch to organization context",
"operationId": "switchOrg",
"security": [{"bearerAuth": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "Context switched"}
}
}
},
"/orgs/{org_id}/members": {
"get": {
"tags": ["members"],
"summary": "List organization members",
"operationId": "listMembers",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "List of members"}
}
}
},
"/orgs/{org_id}/members/{user_id}": {
"patch": {
"tags": ["members"],
"summary": "Update member role",
"operationId": "updateMemberRole",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{"$ref": "#/components/parameters/orgId"},
{"$ref": "#/components/parameters/userId"}
],
"responses": {
"200": {"description": "Role updated"}
}
},
"delete": {
"tags": ["members"],
"summary": "Remove member",
"operationId": "removeMember",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{"$ref": "#/components/parameters/orgId"},
{"$ref": "#/components/parameters/userId"}
],
"responses": {
"200": {"description": "Member removed"}
}
}
},
"/orgs/{org_id}/roles": {
"get": {
"tags": ["roles"],
"summary": "List custom roles",
"operationId": "listCustomRoles",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "List of roles"}
}
},
"post": {
"tags": ["roles"],
"summary": "Create custom role",
"operationId": "createCustomRole",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "Role created"}
}
}
},
"/orgs/{org_id}/policies": {
"get": {
"tags": ["policies"],
"summary": "List ABAC policies",
"operationId": "listPolicies",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "List of policies"}
}
},
"post": {
"tags": ["policies"],
"summary": "Create ABAC policy",
"operationId": "createPolicy",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "Policy created"}
}
}
},
"/orgs/{org_id}/invites": {
"get": {
"tags": ["invites"],
"summary": "List pending invites",
"operationId": "listInvites",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "List of invites"}
}
},
"post": {
"tags": ["invites"],
"summary": "Create invite",
"operationId": "createInvite",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/orgId"}],
"responses": {
"200": {"description": "Invite created"}
}
}
},
"/invites/accept": {
"post": {
"tags": ["invites"],
"summary": "Accept invite",
"operationId": "acceptInvite",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "Invite accepted"}
}
}
},
"/authorize": {
"post": {
"tags": ["user"],
"summary": "Check authorization",
"operationId": "authorize",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "Authorization result"}
}
}
},
"/permissions": {
"post": {
"tags": ["user"],
"summary": "Get user permissions",
"operationId": "getPermissions",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "User permissions"}
}
}
},
"/sessions": {
"get": {
"tags": ["sessions"],
"summary": "List active sessions",
"operationId": "listSessions",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 200}},
{"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0}}
],
"responses": {
"200": {"description": "List of sessions"}
}
},
"delete": {
"tags": ["sessions"],
"summary": "Revoke all sessions",
"operationId": "revokeAllSessions",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "Sessions revoked"}
}
}
},
"/mfa/setup": {
"post": {
"tags": ["mfa"],
"summary": "Setup MFA",
"operationId": "setupMfa",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "MFA setup initiated"}
}
}
},
"/mfa/enable": {
"post": {
"tags": ["mfa"],
"summary": "Enable MFA",
"operationId": "enableMfa",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "MFA enabled"}
}
}
},
"/mfa/disable": {
"post": {
"tags": ["mfa"],
"summary": "Disable MFA",
"operationId": "disableMfa",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "MFA disabled"}
}
}
},
"/mfa/status": {
"get": {
"tags": ["mfa"],
"summary": "Get MFA status",
"operationId": "mfaStatus",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "MFA status"}
}
}
},
"/mfa/verify": {
"post": {
"tags": ["mfa"],
"summary": "Verify MFA code (authenticated step-up)",
"operationId": "verifyMfa",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "MFA verified"}
}
}
},
"/mfa/recovery": {
"post": {
"tags": ["mfa"],
"summary": "Use recovery code (authenticated step-up)",
"operationId": "useRecoveryCode",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {"description": "Recovery code accepted"}
}
}
},
"/setup/status": {
"get": {
"tags": ["setup"],
"summary": "Check if initial setup is required",
"description": "Returns whether the system needs first-run setup (no admin exists). No authentication required.",
"operationId": "getSetupStatus",
"responses": {
"200": {
"description": "Setup status",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SetupStatusResponse"}
}
}
}
}
}
},
"/setup/admin": {
"post": {
"tags": ["setup"],
"summary": "Create first admin user",
"description": "Creates the initial admin account. Only works when no admin users exist; returns 403 afterwards.",
"operationId": "createFirstAdmin",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/CreateFirstAdminRequest"}
}
}
},
"responses": {
"201": {
"description": "Admin created",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/CreateFirstAdminResponse"}
}
}
},
"403": {"description": "Setup already completed"}
}
}
},
"/kyc/start": {
"post": {
"tags": ["kyc"],
"summary": "Start a KYC verification session",
"description": "Creates a new Stripe Identity session and returns a redirect URL for the user.",
"operationId": "startKyc",
"security": [{"bearerAuth": []}],
"responses": {
"200": {
"description": "KYC session created",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/StartKycResponse"}
}
}
},
"401": {"description": "Unauthorized"},
"404": {"description": "KYC service not configured"}
}
}
},
"/kyc/status": {
"get": {
"tags": ["kyc"],
"summary": "Get current KYC status",
"description": "Returns the authenticated user's current KYC verification status.",
"operationId": "getKycStatus",
"security": [{"bearerAuth": []}],
"responses": {
"200": {
"description": "KYC status",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/KycStatusResponse"}
}
}
},
"401": {"description": "Unauthorized"},
"404": {"description": "KYC service not configured"}
}
}
},
"/accreditation/status": {
"get": {
"tags": ["accreditation"],
"summary": "Get accreditation status",
"description": "Returns the authenticated user's current accredited investor status.",
"operationId": "getAccreditationStatus",
"security": [{"bearerAuth": []}],
"responses": {
"200": {
"description": "Accreditation status",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AccreditationStatusResponse"}
}
}
},
"401": {"description": "Unauthorized"},
"404": {"description": "Accreditation service not configured"}
}
}
},
"/accreditation/submit": {
"post": {
"tags": ["accreditation"],
"summary": "Submit an accreditation request",
"description": "Creates a new accreditation submission for admin review.",
"operationId": "submitAccreditation",
"security": [{"bearerAuth": []}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SubmitAccreditationRequest"}
}
}
},
"responses": {
"200": {
"description": "Submission created",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SubmitAccreditationResponse"}
}
}
},
"401": {"description": "Unauthorized"},
"404": {"description": "Accreditation service not configured"}
}
}
},
"/accreditation/upload": {
"post": {
"tags": ["accreditation"],
"summary": "Upload an accreditation supporting document",
"description": "Accepts multipart/form-data with fields: submissionId, documentType, file. Max 10 MB.",
"operationId": "uploadAccreditationDocument",
"security": [{"bearerAuth": []}],
"requestBody": {
"required": true,
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"required": ["submissionId", "documentType", "file"],
"properties": {
"submissionId": {"type": "string", "format": "uuid"},
"documentType": {"type": "string", "example": "tax_w2"},
"file": {"type": "string", "format": "binary"}
}
}
}
}
},
"responses": {
"200": {
"description": "Document uploaded",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/DocumentUploadResponse"}
}
}
},
"400": {"description": "Missing fields or unsupported file type"},
"401": {"description": "Unauthorized"}
}
}
},
"/accreditation/submissions": {
"get": {
"tags": ["accreditation"],
"summary": "List own accreditation submissions",
"description": "Returns the authenticated user's submission history, paginated.",
"operationId": "listAccreditationSubmissions",
"security": [{"bearerAuth": []}],
"parameters": [
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 50}},
{"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}}
],
"responses": {
"200": {
"description": "Submissions list",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SubmissionsListResponse"}
}
}
},
"401": {"description": "Unauthorized"}
}
}
},
"/referral/rewards": {
"get": {
"tags": ["referrals"],
"summary": "Get referral rewards summary",
"description": "Returns aggregated rewards earned, pending amounts, and payout wallet for the authenticated user.",
"operationId": "getReferralRewards",
"security": [{"bearerAuth": []}],
"responses": {
"200": {
"description": "Rewards summary",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/RewardsInfoResponse"}
}
}
},
"401": {"description": "Unauthorized"},
"404": {"description": "Referrals not enabled"}
}
}
},
"/referral/rewards/history": {
"get": {
"tags": ["referrals"],
"summary": "Get referral rewards history",
"description": "Returns paginated history of referral rewards (payouts or credit transactions).",
"operationId": "getReferralRewardsHistory",
"security": [{"bearerAuth": []}],
"parameters": [
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20}},
{"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}}
],
"responses": {
"200": {
"description": "Rewards history",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/RewardsHistoryResponse"}
}
}
},
"401": {"description": "Unauthorized"},
"404": {"description": "Referrals not enabled"}
}
}
},
"/referral/payout-wallet": {
"post": {
"tags": ["referrals"],
"summary": "Set or clear payout wallet address",
"description": "Sets the Solana wallet address for receiving direct referral payouts. Pass null to clear.",
"operationId": "setPayoutWallet",
"security": [{"bearerAuth": []}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SetPayoutWalletRequest"}
}
}
},
"responses": {
"200": {
"description": "Wallet address updated",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SetPayoutWalletResponse"}
}
}
},
"400": {"description": "Invalid wallet address"},
"401": {"description": "Unauthorized"}
}
}
},
"/access-codes/generate": {
"post": {
"tags": ["access-codes"],
"summary": "Generate a personal invite code",
"description": "Generates a single-use invite code for the authenticated user to share.",
"operationId": "generateAccessCode",
"security": [{"bearerAuth": []}],
"responses": {
"200": {
"description": "Invite code created",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AccessCodeResponse"}
}
}
},
"401": {"description": "Unauthorized"}
}
}
},
"/access-codes/mine": {
"get": {
"tags": ["access-codes"],
"summary": "List own access codes",
"description": "Returns all access codes generated by the authenticated user.",
"operationId": "listMyAccessCodes",
"security": [{"bearerAuth": []}],
"parameters": [
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20}},
{"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}}
],
"responses": {
"200": {
"description": "Access codes list",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AccessCodeListResponse"}
}
}
},
"401": {"description": "Unauthorized"}
}
}
},
"/webhook/kyc": {
"post": {
"tags": ["webhooks"],
"summary": "Receive KYC webhook from Stripe",
"description": "Processes Stripe Identity webhook events. Requires a valid Stripe-Signature header.",
"operationId": "handleKycWebhook",
"parameters": [
{
"name": "Stripe-Signature",
"in": "header",
"required": true,
"schema": {"type": "string"},
"description": "Stripe webhook signature for request verification"
}
],
"responses": {
"200": {"description": "Webhook processed"},
"400": {"description": "Missing or invalid signature"},
"404": {"description": "KYC service not configured"}
}
}
},
"/admin/users/{user_id}/kyc": {
"get": {
"tags": ["admin"],
"summary": "Get KYC status and session history for a user",
"operationId": "getAdminUserKyc",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/userId"}],
"responses": {
"200": {
"description": "User KYC record",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AdminUserKycResponse"}
}
}
},
"403": {"description": "Not a system admin"},
"404": {"description": "User or KYC service not found"}
}
}
},
"/admin/users/{user_id}/kyc/override": {
"post": {
"tags": ["admin"],
"summary": "Override a user's KYC status",
"description": "Manually sets the KYC status for a user, bypassing the normal verification flow.",
"operationId": "overrideUserKycStatus",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/userId"}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/KycOverrideRequest"}
}
}
},
"responses": {
"200": {
"description": "Status overridden",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/OkResponse"}
}
}
},
"400": {"description": "Invalid status value"},
"403": {"description": "Not a system admin"},
"404": {"description": "User not found"}
}
}
},
"/admin/accreditation/pending": {
"get": {
"tags": ["admin"],
"summary": "List pending accreditation submissions",
"description": "Returns all submissions in 'pending' status (oldest first) for admin review.",
"operationId": "listPendingAccreditations",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 200, "default": 50}},
{"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}}
],
"responses": {
"200": {
"description": "Pending submissions",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/PendingListResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/users/{user_id}/accreditation": {
"get": {
"tags": ["admin"],
"summary": "Get accreditation record for a user",
"description": "Returns aggregate accreditation status and submission history for a user.",
"operationId": "getAdminUserAccreditation",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/userId"}],
"responses": {
"200": {
"description": "User accreditation record",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AdminUserAccreditationResponse"}
}
}
},
"403": {"description": "Not a system admin"},
"404": {"description": "User not found"}
}
}
},
"/admin/accreditation/{submission_id}": {
"get": {
"tags": ["admin"],
"summary": "Get accreditation submission detail",
"description": "Returns full submission detail including documents.",
"operationId": "getAccreditationSubmission",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "submission_id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
],
"responses": {
"200": {
"description": "Submission detail",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AdminSubmissionDetailResponse"}
}
}
},
"403": {"description": "Not a system admin"},
"404": {"description": "Submission not found"}
}
}
},
"/admin/accreditation/documents/{doc_id}/url": {
"get": {
"tags": ["admin"],
"summary": "Get presigned URL for an accreditation document",
"description": "Returns a short-lived presigned S3 URL (15 minutes) for downloading the document.",
"operationId": "getAccreditationDocumentUrl",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "doc_id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
],
"responses": {
"200": {
"description": "Presigned URL",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/DocumentPresignedUrlResponse"}
}
}
},
"403": {"description": "Not a system admin"},
"404": {"description": "Document not found"}
}
}
},
"/admin/accreditation/{submission_id}/review": {
"post": {
"tags": ["admin"],
"summary": "Approve or reject an accreditation submission",
"operationId": "reviewAccreditation",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "submission_id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ReviewAccreditationRequest"}
}
}
},
"responses": {
"200": {
"description": "Review recorded",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/OkResponse"}
}
}
},
"403": {"description": "Not a system admin"},
"404": {"description": "Submission not found"}
}
}
},
"/admin/users/{user_id}/accreditation/override": {
"post": {
"tags": ["admin"],
"summary": "Override a user's accreditation status",
"description": "Manually sets the accreditation status for a user, bypassing the review flow.",
"operationId": "overrideUserAccreditationStatus",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/userId"}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AccreditationOverrideRequest"}
}
}
},
"responses": {
"200": {
"description": "Status overridden",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/OkResponse"}
}
}
},
"400": {"description": "Invalid status value"},
"403": {"description": "Not a system admin"},
"404": {"description": "User not found"}
}
}
},
"/admin/sanctions/stats": {
"get": {
"tags": ["admin"],
"summary": "Get sanctions cache statistics",
"description": "Returns the number of sanctioned addresses/countries cached and the cache age.",
"operationId": "getSanctionsStats",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Sanctions cache stats",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SanctionsStatsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/sanctions/refresh": {
"post": {
"tags": ["admin"],
"summary": "Force a sanctions list refresh",
"description": "Forces an immediate refresh of the sanctions cache from the configured API.",
"operationId": "refreshSanctions",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Cache refreshed; returns updated stats",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SanctionsStatsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/users/{user_id}/compliance": {
"get": {
"tags": ["admin"],
"summary": "Get compliance status for a user",
"description": "Returns KYC status, accredited investor flag, and token gate result. Designed for service-to-service calls.",
"operationId": "getUserCompliance",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [{"$ref": "#/components/parameters/userId"}],
"responses": {
"200": {
"description": "Compliance status",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ComplianceStatusResponse"}
}
}
},
"403": {"description": "Not a system admin"},
"404": {"description": "User not found"}
}
}
},
"/admin/access-codes": {
"get": {
"tags": ["admin"],
"summary": "List all access codes",
"description": "Returns all access codes with optional type filter.",
"operationId": "adminListAccessCodes",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20}},
{"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}},
{"name": "code_type", "in": "query", "schema": {"type": "string"}, "description": "Filter by code type (e.g. limited, user)"}
],
"responses": {
"200": {
"description": "Access codes list",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AccessCodeListResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
},
"post": {
"tags": ["admin"],
"summary": "Create an admin-managed access code",
"description": "Creates a new limited-use code. The code string must not be empty.",
"operationId": "adminCreateAccessCode",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/CreateAccessCodeRequest"}
}
}
},
"responses": {
"200": {
"description": "Access code created",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/AccessCodeResponse"}
}
}
},
"400": {"description": "Invalid request"},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/access-codes/{id}": {
"delete": {
"tags": ["admin"],
"summary": "Delete an access code",
"operationId": "adminDeleteAccessCode",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
],
"responses": {
"200": {
"description": "Deleted",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/OkResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/signup-stats": {
"get": {
"tags": ["admin"],
"summary": "Get signup statistics for the current period",
"description": "Returns the number of registrations in the current period vs the configured limit.",
"operationId": "adminSignupStats",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Signup stats",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/SignupStatsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/referral-stats": {
"get": {
"tags": ["admin"],
"summary": "Get referral analytics",
"description": "Returns aggregate referral counts, payout totals, and top affiliates.",
"operationId": "getReferralStats",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Referral stats",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ReferralStatsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/referral-payouts": {
"get": {
"tags": ["admin"],
"summary": "List pending referral payouts grouped by referrer",
"operationId": "listReferralPayouts",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Pending payouts by referrer",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ListReferralPayoutsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/referral-payouts/process": {
"post": {
"tags": ["admin"],
"summary": "Execute all pending referral payouts on-chain",
"description": "Aggregates and transfers pending referral rewards to each referrer's payout wallet.",
"operationId": "processReferralPayouts",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Payout batch result",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ProcessReferralPayoutsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/referral-payouts/retry-failed": {
"post": {
"tags": ["admin"],
"summary": "Reset failed referral payouts to pending",
"operationId": "retryFailedPayouts",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"responses": {
"200": {
"description": "Reset count",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/RetryFailedPayoutsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/referral-payouts/list": {
"get": {
"tags": ["admin"],
"summary": "List individual referral payouts",
"description": "Paginated list of all individual payout records with optional status filter.",
"operationId": "listAllPayouts",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{"name": "status", "in": "query", "schema": {"type": "string"}, "description": "Filter by status: pending, processing, completed, failed, cancelled"},
{"name": "limit", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20}},
{"name": "offset", "in": "query", "schema": {"type": "integer", "minimum": 0, "default": 0}}
],
"responses": {
"200": {
"description": "Payouts list",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ListPayoutsResponse"}
}
}
},
"403": {"description": "Not a system admin"}
}
}
},
"/admin/referral-payouts/{id}/process": {
"post": {
"tags": ["admin"],
"summary": "Process a single referral payout",
"description": "Executes an individual pending or failed payout on-chain.",
"operationId": "processSinglePayout",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
],
"responses": {
"200": {
"description": "Payout processed",
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/ProcessSingleResponse"}
}
}
},
"400": {"description": "Payout not in processable state"},
"403": {"description": "Not a system admin"},
"404": {"description": "Payout not found"}
}
}
},
"/admin/referral-payouts/{id}/cancel": {
"post": {
"tags": ["admin"],
"summary": "Cancel a pending referral payout",
"operationId": "cancelPayout",
"security": [{"bearerAuth": []}, {"apiKey": []}],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
],
"responses": {
"200": {
"description": "Payout cancelled",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"cancelled": {"type": "boolean"}
}
}
}
}
},
"400": {"description": "Payout cannot be cancelled in current state"},
"403": {"description": "Not a system admin"},
"404": {"description": "Payout not found"}
}
}
}
},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT",
"description": "JWT access token"
},
"apiKey": {
"type": "http",
"scheme": "bearer",
"description": "API key (prefix: ck_)"
}
},
"parameters": {
"orgId": {
"name": "org_id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
},
"userId": {
"name": "user_id",
"in": "path",
"required": true,
"schema": {"type": "string", "format": "uuid"}
}
},
"schemas": {
"AuthConfigResponse": {
"type": "object",
"properties": {
"version": {"type": "string"},
"basePath": {"type": "string"},
"authMethods": {"type": "array"},
"apiKeyUsage": {"type": "object"},
"links": {"type": "object"}
}
},
"RegisterRequest": {
"type": "object",
"required": ["email", "password"],
"properties": {
"email": {"type": "string", "format": "email"},
"password": {"type": "string", "minLength": 8}
}
},
"LoginRequest": {
"type": "object",
"required": ["email", "password"],
"properties": {
"email": {"type": "string", "format": "email"},
"password": {"type": "string"}
}
},
"RefreshRequest": {
"type": "object",
"required": ["refreshToken"],
"properties": {
"refreshToken": {"type": "string"}
}
},
"InstantLinkRequest": {
"type": "object",
"required": ["email"],
"properties": {
"email": {"type": "string", "format": "email"}
}
},
"VerifyInstantLinkRequest": {
"type": "object",
"required": ["token"],
"properties": {
"token": {"type": "string"}
}
},
"MessageResponse": {
"type": "object",
"required": ["message"],
"properties": {
"message": {"type": "string"}
}
},
"MfaRequiredResponse": {
"type": "object",
"required": ["mfaRequired", "mfaToken", "userId"],
"properties": {
"mfaRequired": {"type": "boolean"},
"mfaToken": {"type": "string"},
"userId": {"type": "string", "format": "uuid"}
}
},
"SolanaChallengeRequest": {
"type": "object",
"required": ["publicKey"],
"properties": {
"publicKey": {
"type": "string",
"description": "Base58-encoded Solana public key"
}
}
},
"SolanaChallengeResponse": {
"type": "object",
"properties": {
"nonce": {
"type": "string",
"description": "Challenge nonce to sign"
},
"expiresAt": {
"type": "string",
"format": "date-time"
}
}
},
"SolanaAuthRequest": {
"type": "object",
"required": ["publicKey", "signature"],
"properties": {
"publicKey": {
"type": "string",
"description": "Base58-encoded Solana public key"
},
"signature": {
"type": "string",
"description": "Base58-encoded Ed25519 signature of the nonce"
}
}
},
"AuthResponse": {
"type": "object",
"properties": {
"user": {"$ref": "#/components/schemas/AuthUser"},
"tokens": {"$ref": "#/components/schemas/TokenPair"},
"isNewUser": {"type": "boolean"},
"apiKey": {
"type": "string",
"description": "API key (only returned for new users)"
}
}
},
"AuthUser": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"email": {"type": "string"},
"emailVerified": {"type": "boolean"},
"solanaPublicKey": {"type": "string"}
}
},
"TokenPair": {
"type": "object",
"properties": {
"accessToken": {"type": "string"},
"refreshToken": {"type": "string"},
"expiresIn": {"type": "integer"}
}
},
"ValidateApiKeyRequest": {
"type": "object",
"required": ["apiKey"],
"properties": {
"apiKey": {"type": "string"}
}
},
"ValidateApiKeyResponse": {
"type": "object",
"properties": {
"valid": {"type": "boolean"},
"userId": {"type": "string", "format": "uuid"}
}
},
"UserResponse": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"email": {"type": "string"},
"emailVerified": {"type": "boolean"},
"solanaPublicKey": {"type": "string"},
"createdAt": {"type": "string", "format": "date-time"}
}
},
"ApiKeyResponse": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"keyPrefix": {"type": "string", "description": "First 8 chars of key"},
"label": {"type": "string", "description": "Human-readable label (e.g. 'default', 'bot-alpha')"},
"createdAt": {"type": "string", "format": "date-time"},
"lastUsedAt": {"type": "string", "format": "date-time"}
}
},
"RegenerateApiKeyResponse": {
"type": "object",
"properties": {
"apiKey": {"type": "string", "description": "New API key (shown only once)"},
"keyPrefix": {"type": "string"},
"label": {"type": "string"},
"createdAt": {"type": "string", "format": "date-time"},
"message": {"type": "string"}
}
},
"ApiKeyListResponse": {
"type": "object",
"properties": {
"keys": {
"type": "array",
"items": {"$ref": "#/components/schemas/ApiKeyResponse"}
}
}
},
"CreateApiKeyRequest": {
"type": "object",
"required": ["label"],
"properties": {
"label": {"type": "string", "minLength": 1, "maxLength": 100, "description": "Human-readable label for the key"}
}
},
"CreateApiKeyResponse": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"apiKey": {"type": "string", "description": "New API key (shown only once)"},
"keyPrefix": {"type": "string"},
"label": {"type": "string"},
"createdAt": {"type": "string", "format": "date-time"},
"message": {"type": "string"}
}
},
"WalletListResponse": {
"type": "object",
"properties": {
"wallets": {
"type": "array",
"items": {"$ref": "#/components/schemas/WalletSummary"}
}
}
},
"WalletSummary": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"walletPubkey": {"type": "string", "description": "Base58-encoded Solana public key"},
"authMethod": {"type": "string", "enum": ["password", "pin", "passkey", "api_key"]},
"apiKeyLabel": {"type": "string", "description": "Label of linked API key, or null for default wallet"},
"isDefault": {"type": "boolean"},
"createdAt": {"type": "string", "format": "date-time"}
}
},
"WalletRotateRequest": {
"type": "object",
"description": "Same structure as WalletEnrollRequest — provides new wallet material for the rotated wallet.",
"required": ["authMethod", "walletPubkey"],
"properties": {
"authMethod": {"type": "string", "enum": ["password", "pin", "passkey", "api_key"]},
"walletPubkey": {"type": "string"},
"encryptedShareA": {"type": "string"},
"encryptedShareB": {"type": "string"},
"shareAKdfSalt": {"type": "string"},
"shareAKdfParams": {"type": "string"},
"prfSalt": {"type": "string"}
}
},
"CreateOrgRequest": {
"type": "object",
"required": ["name"],
"properties": {
"name": {"type": "string"}
}
},
"SetupStatusResponse": {
"type": "object",
"properties": {
"needsSetup": {"type": "boolean", "description": "True when no admin user exists yet"},
"hasAdmin": {"type": "boolean"},
"serverVersion": {"type": "string"}
}
},
"CreateFirstAdminRequest": {
"type": "object",
"required": ["email", "password"],
"properties": {
"email": {"type": "string", "format": "email"},
"password": {"type": "string", "minLength": 8},
"name": {"type": "string", "description": "Optional display name"},
"orgName": {"type": "string", "description": "Organization name (defaults to 'My Organization')"}
}
},
"CreateFirstAdminResponse": {
"type": "object",
"properties": {
"success": {"type": "boolean"},
"userId": {"type": "string", "format": "uuid"},
"message": {"type": "string"}
}
},
"StartKycResponse": {
"type": "object",
"properties": {
"sessionId": {"type": "string", "format": "uuid"},
"redirectUrl": {"type": "string", "format": "uri", "description": "URL to redirect the user to for identity verification"}
}
},
"KycStatusResponse": {
"type": "object",
"properties": {
"status": {"type": "string", "enum": ["none", "pending", "verified", "failed", "canceled"]},
"verifiedAt": {"type": "string", "format": "date-time"},
"expiresAt": {"type": "string", "format": "date-time"},
"enforcementMode": {"type": "string", "enum": ["none", "optional", "withdrawals", "deposits", "all"]}
}
},
"KycSessionItem": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"provider": {"type": "string"},
"providerSessionId": {"type": "string"},
"status": {"type": "string", "enum": ["pending", "verified", "failed", "canceled"]},
"errorCode": {"type": "string"},
"errorReason": {"type": "string"},
"createdAt": {"type": "string", "format": "date-time"},
"updatedAt": {"type": "string", "format": "date-time"},
"completedAt": {"type": "string", "format": "date-time"}
}
},
"AdminUserKycResponse": {
"type": "object",
"properties": {
"userId": {"type": "string", "format": "uuid"},
"status": {"type": "string"},
"verifiedAt": {"type": "string", "format": "date-time"},
"expiresAt": {"type": "string", "format": "date-time"},
"sessions": {"type": "array", "items": {"$ref": "#/components/schemas/KycSessionItem"}},
"totalSessions": {"type": "integer", "format": "int64"}
}
},
"KycOverrideRequest": {
"type": "object",
"required": ["status"],
"properties": {
"status": {"type": "string", "enum": ["none", "pending", "verified", "failed", "canceled"]},
"expiresAt": {"type": "string", "format": "date-time", "description": "Optional expiry for 'verified' status (ISO 8601)"}
}
},
"AccreditationStatusResponse": {
"type": "object",
"properties": {
"status": {"type": "string", "enum": ["none", "pending", "approved", "rejected", "expired"]},
"verifiedAt": {"type": "string", "format": "date-time"},
"expiresAt": {"type": "string", "format": "date-time"},
"enforcementMode": {"type": "string"}
}
},
"SubmitAccreditationRequest": {
"type": "object",
"required": ["method"],
"properties": {
"method": {"type": "string", "enum": ["income", "net_worth", "credential", "third_party_letter", "insider", "investment_threshold"]},
"incomeType": {"type": "string", "enum": ["individual", "joint"]},
"statedAmountUsd": {"type": "number", "format": "double"},
"crdNumber": {"type": "string"},
"licenseType": {"type": "string", "enum": ["series_7", "series_65", "series_82"]},
"investmentCommitmentUsd": {"type": "number", "format": "double"},
"entityType": {"type": "string", "enum": ["individual", "entity"]},
"userStatement": {"type": "string"}
}
},
"SubmitAccreditationResponse": {
"type": "object",
"properties": {
"submissionId": {"type": "string", "format": "uuid"}
}
},
"DocumentUploadResponse": {
"type": "object",
"properties": {
"documentId": {"type": "string", "format": "uuid"},
"submissionId": {"type": "string", "format": "uuid"},
"s3Key": {"type": "string"}
}
},
"DocumentPresignedUrlResponse": {
"type": "object",
"properties": {
"url": {"type": "string", "format": "uri", "description": "Presigned S3 GET URL"},
"expiresIn": {"type": "integer", "description": "Seconds until URL expiry"}
}
},
"AccreditationSubmissionItem": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"userId": {"type": "string", "format": "uuid"},
"method": {"type": "string"},
"status": {"type": "string"},
"incomeType": {"type": "string"},
"statedAmountUsd": {"type": "number"},
"crdNumber": {"type": "string"},
"licenseType": {"type": "string"},
"investmentCommitmentUsd": {"type": "number"},
"entityType": {"type": "string"},
"userStatement": {"type": "string"},
"reviewedBy": {"type": "string", "format": "uuid"},
"reviewedAt": {"type": "string", "format": "date-time"},
"reviewerNotes": {"type": "string"},
"rejectionReason": {"type": "string"},
"expiresAt": {"type": "string", "format": "date-time"},
"createdAt": {"type": "string", "format": "date-time"},
"updatedAt": {"type": "string", "format": "date-time"}
}
},
"SubmissionsListResponse": {
"type": "object",
"properties": {
"submissions": {"type": "array", "items": {"$ref": "#/components/schemas/AccreditationSubmissionItem"}},
"total": {"type": "integer", "format": "int64"},
"limit": {"type": "integer"},
"offset": {"type": "integer"}
}
},
"PendingListResponse": {
"type": "object",
"properties": {
"submissions": {"type": "array", "items": {"$ref": "#/components/schemas/AccreditationSubmissionItem"}},
"total": {"type": "integer", "format": "int64"},
"limit": {"type": "integer"},
"offset": {"type": "integer"}
}
},
"AdminUserAccreditationResponse": {
"type": "object",
"properties": {
"userId": {"type": "string", "format": "uuid"},
"status": {"type": "string"},
"verifiedAt": {"type": "string", "format": "date-time"},
"expiresAt": {"type": "string", "format": "date-time"},
"submissions": {"type": "array", "items": {"$ref": "#/components/schemas/AccreditationSubmissionItem"}},
"totalSubmissions": {"type": "integer", "format": "int64"}
}
},
"AccreditationDocumentItem": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"submissionId": {"type": "string", "format": "uuid"},
"documentType": {"type": "string"},
"s3Key": {"type": "string"},
"originalFilename": {"type": "string"},
"contentType": {"type": "string"},
"fileSizeBytes": {"type": "integer", "format": "int64"},
"uploadedAt": {"type": "string", "format": "date-time"}
}
},
"AdminSubmissionDetailResponse": {
"type": "object",
"properties": {
"submission": {"$ref": "#/components/schemas/AccreditationSubmissionItem"},
"documents": {"type": "array", "items": {"$ref": "#/components/schemas/AccreditationDocumentItem"}}
}
},
"ReviewAccreditationRequest": {
"type": "object",
"required": ["approved"],
"properties": {
"approved": {"type": "boolean"},
"reviewerNotes": {"type": "string"},
"rejectionReason": {"type": "string"},
"expiryDays": {"type": "integer", "format": "int64", "description": "Custom expiry in days from now (overrides default setting)"}
}
},
"AccreditationOverrideRequest": {
"type": "object",
"required": ["status"],
"properties": {
"status": {"type": "string", "enum": ["none", "pending", "approved", "rejected", "expired"]},
"expiresAt": {"type": "string", "format": "date-time", "description": "Optional expiry for 'approved' status (ISO 8601)"}
}
},
"RewardsInfoResponse": {
"type": "object",
"properties": {
"totalEarned": {"type": "integer", "format": "int64", "description": "Total rewards earned in smallest unit"},
"pendingAmount": {"type": "integer", "format": "int64", "description": "Pending direct payouts"},
"pendingCount": {"type": "integer", "format": "int64"},
"currency": {"type": "string"},
"rewardType": {"type": "string", "enum": ["credits", "direct_payout"]},
"payoutWalletAddress": {"type": "string", "description": "User's configured Solana payout wallet"},
"referralCount": {"type": "integer", "format": "int64"}
}
},
"RewardHistoryItem": {
"type": "object",
"properties": {
"id": {"type": "string"},
"triggerType": {"type": "string", "description": "e.g. 'signup', 'first_spend'"},
"amount": {"type": "integer", "format": "int64"},
"currency": {"type": "string"},
"status": {"type": "string", "enum": ["pending", "processing", "completed", "failed", "cancelled", "credited"]},
"txSignature": {"type": "string"},
"createdAt": {"type": "string", "format": "date-time"},
"completedAt": {"type": "string", "format": "date-time"}
}
},
"RewardsHistoryResponse": {
"type": "object",
"properties": {
"items": {"type": "array", "items": {"$ref": "#/components/schemas/RewardHistoryItem"}},
"total": {"type": "integer", "format": "int64"}
}
},
"SetPayoutWalletRequest": {
"type": "object",
"properties": {
"walletAddress": {"type": "string", "description": "Base58-encoded 32-byte Solana public key, or null to clear", "nullable": true}
}
},
"SetPayoutWalletResponse": {
"type": "object",
"properties": {
"ok": {"type": "boolean"},
"walletAddress": {"type": "string", "nullable": true}
}
},
"AccessCodeResponse": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"code": {"type": "string"},
"codeType": {"type": "string", "enum": ["limited", "user"]},
"maxUses": {"type": "integer", "nullable": true},
"currentUses": {"type": "integer"},
"createdBy": {"type": "string", "format": "uuid", "nullable": true},
"expiresAt": {"type": "string", "format": "date-time", "nullable": true},
"createdAt": {"type": "string", "format": "date-time"}
}
},
"AccessCodeListResponse": {
"type": "object",
"properties": {
"items": {"type": "array", "items": {"$ref": "#/components/schemas/AccessCodeResponse"}},
"total": {"type": "integer", "format": "int64"}
}
},
"CreateAccessCodeRequest": {
"type": "object",
"required": ["code"],
"properties": {
"code": {"type": "string", "minLength": 1, "description": "The invite code string"},
"maxUses": {"type": "integer", "nullable": true, "description": "Maximum number of uses (null = unlimited)"},
"expiresAt": {"type": "string", "format": "date-time", "nullable": true}
}
},
"SignupStatsResponse": {
"type": "object",
"properties": {
"count": {"type": "integer", "format": "int64", "description": "Users registered in the current period"},
"limit": {"type": "integer", "format": "int64", "nullable": true, "description": "Max registrations per period (null = unlimited)"},
"period": {"type": "string", "enum": ["day", "week", "month"]},
"periodStart": {"type": "string", "format": "date-time"}
}
},
"SanctionsStatsResponse": {
"type": "object",
"properties": {
"addressCount": {"type": "integer", "description": "Number of sanctioned addresses currently cached"},
"countryCount": {"type": "integer", "description": "Number of blocked country codes currently cached"},
"cacheAgeSecs": {"type": "integer", "format": "int64", "nullable": true, "description": "Seconds since last refresh, null if never refreshed"}
}
},
"ComplianceStatusResponse": {
"type": "object",
"properties": {
"kycStatus": {"type": "string", "enum": ["none", "pending", "verified", "expired"]},
"accreditedInvestor": {"type": "boolean"},
"accreditedVerifiedAt": {"type": "string", "format": "date-time", "nullable": true},
"tokenGated": {"type": "boolean", "description": "True when all token gate rules pass (or gating is disabled)"}
}
},
"ReferralStatsResponse": {
"type": "object",
"properties": {
"totalReferrals": {"type": "integer", "format": "int64"},
"referralsThisMonth": {"type": "integer", "format": "int64"},
"totalPendingPayouts": {"type": "integer", "format": "int64"},
"totalCompletedPayouts": {"type": "integer", "format": "int64"},
"topAffiliates": {
"type": "array",
"items": {
"type": "object",
"properties": {
"userId": {"type": "string", "format": "uuid"},
"email": {"type": "string", "nullable": true},
"name": {"type": "string", "nullable": true},
"referralCount": {"type": "integer", "format": "int64"},
"referralCode": {"type": "string"}
}
}
}
}
},
"ListReferralPayoutsResponse": {
"type": "object",
"properties": {
"referrers": {
"type": "array",
"items": {
"type": "object",
"description": "Aggregated pending payout summary per referrer",
"properties": {
"referrerId": {"type": "string", "format": "uuid"},
"payoutWalletAddress": {"type": "string", "nullable": true},
"pendingCount": {"type": "integer"},
"totalAmount": {"type": "integer", "format": "int64"},
"currency": {"type": "string"}
}
}
},
"total": {"type": "integer", "format": "int64"}
}
},
"ProcessReferralPayoutsResponse": {
"type": "object",
"properties": {
"processed": {"type": "integer", "format": "int64"},
"failed": {"type": "integer", "format": "int64"},
"totalAmount": {"type": "integer", "format": "int64"},
"skippedNoWallet": {"type": "integer", "format": "int64"}
}
},
"RetryFailedPayoutsResponse": {
"type": "object",
"properties": {
"resetCount": {"type": "integer", "format": "int64"}
}
},
"AdminPayoutItem": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"referrerId": {"type": "string", "format": "uuid"},
"referrerEmail": {"type": "string", "nullable": true},
"referrerName": {"type": "string", "nullable": true},
"referredUserId": {"type": "string", "format": "uuid"},
"triggerType": {"type": "string"},
"amount": {"type": "integer", "format": "int64"},
"currency": {"type": "string"},
"status": {"type": "string", "enum": ["pending", "processing", "completed", "failed", "cancelled"]},
"txSignature": {"type": "string", "nullable": true},
"errorMessage": {"type": "string", "nullable": true},
"createdAt": {"type": "string", "format": "date-time"},
"completedAt": {"type": "string", "format": "date-time", "nullable": true}
}
},
"ListPayoutsResponse": {
"type": "object",
"properties": {
"payouts": {"type": "array", "items": {"$ref": "#/components/schemas/AdminPayoutItem"}},
"total": {"type": "integer", "format": "int64"}
}
},
"ProcessSingleResponse": {
"type": "object",
"properties": {
"txSignature": {"type": "string", "description": "On-chain transaction signature"}
}
},
"OkResponse": {
"type": "object",
"properties": {
"ok": {"type": "boolean"}
}
}
}
}
}