{"openapi":"3.0.3","info":{"title":"Simplr API","description":"\n## Overview\nSimplr provides real-time fraud detection to protect your users from account takeover and fraudulent signups:\n\n- **Email Verification**: Score email addresses for fraud risk using domain intelligence, disposable email detection, cross-org reputation, ML models, and more\n- **SIM-Swap Detection**: Check phone numbers for recent SIM swaps that indicate potential account takeover\n\n## Authentication\n\nThere are **two separate authentication methods** depending on which endpoints you're using:\n\n### 1. Portal API - JWT Bearer Token (for dashboard/management)\nUse this for managing your account, API keys, billing, and viewing usage.\n\n**Endpoints:** `/auth/*`, `/org/*`, `/keys/*`, `/usage/*`, `/billing/*`\n\n```\nAuthorization: Bearer <access_token>\n```\n\nGet your access token by calling `POST /auth/login` with email/password.\n\n### 2. Check API - API Key (for verification requests)\nUse this for actually checking emails and phone numbers.\n\n**Endpoints:** `/check`, `/check/bulk`, `/check/{checkId}`, `/check/sandbox`\n\n```\nX-API-Key: sk_live_xxxxxxxxxxxxxxxx\n```\n\nGet your API key from the dashboard (Portal API) at `/keys`.\n\n## Rate Limits\n- Portal API: 100 requests/minute\n- Check API: 1000 requests/minute (live), 100 requests/minute (test)\n\n## Environments\n- **Live**: Production environment with real data and billing\n- **Test**: Sandbox environment with simulated responses (no charges)\n    ","version":"1.0.0","contact":{"name":"Simplr Support","email":"support@simplr.com","url":"https://simplr.com"}},"servers":[{"url":"http://localhost:7002/v1","description":"Development server"},{"url":"https://api.simplr.com/v1","description":"Production server"}],"tags":[{"name":"Authentication","description":"User authentication and session management"},{"name":"Organizations","description":"Organization management"},{"name":"API Keys","description":"API key management"},{"name":"Usage","description":"Usage statistics and logs"},{"name":"Billing","description":"Billing and invoices"},{"name":"Check","description":"Email verification and SIM-swap detection (requires API key)"}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"JWT access token for Portal endpoints (/auth, /org, /keys, /usage, /billing). Get token via POST /auth/login."},"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key for Check endpoints (/check, /check/bulk). Get your key from the dashboard."}},"schemas":{"SuccessResponse":{"type":"object","properties":{"success":{"type":"boolean","example":true},"message":{"type":"string"},"content":{"type":"object"}}},"ErrorResponse":{"type":"object","properties":{"success":{"type":"boolean","example":false},"error":{"type":"string"}}},"User":{"type":"object","properties":{"id":{"type":"string","example":"507f1f77bcf86cd799439011"},"email":{"type":"string","format":"email","example":"user@example.com"},"name":{"type":"string","example":"John Doe"},"avatar_url":{"type":"string","nullable":true},"email_verified":{"type":"boolean"},"auth_provider":{"type":"string","enum":["email","google"]}}},"RegisterRequest":{"type":"object","required":["email","password","name"],"properties":{"email":{"type":"string","format":"email","example":"user@example.com"},"password":{"type":"string","minLength":8,"example":"securepassword123"},"name":{"type":"string","example":"John Doe"}}},"LoginRequest":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email","example":"user@example.com"},"password":{"type":"string","example":"securepassword123"}}},"TokenResponse":{"type":"object","properties":{"tokens":{"type":"object","properties":{"access_token":{"type":"string"},"refresh_token":{"type":"string"},"expires_in":{"type":"number","example":900}}}}},"Organization":{"type":"object","properties":{"id":{"type":"string","example":"507f1f77bcf86cd799439011"},"name":{"type":"string","example":"Acme Corp"},"slug":{"type":"string","example":"acme-corp"},"owner_id":{"type":"string"},"billing_email":{"type":"string","format":"email"},"status":{"type":"string","enum":["active","suspended","cancelled"]},"created_at":{"type":"string","format":"date-time"}}},"CreateOrgRequest":{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Acme Corp"},"billing_email":{"type":"string","format":"email"}}},"Member":{"type":"object","properties":{"id":{"type":"string"},"user_id":{"type":"string"},"role":{"type":"string","enum":["owner","admin","member"]},"status":{"type":"string","enum":["pending","active"]},"joined_at":{"type":"string","format":"date-time","nullable":true},"user":{"$ref":"#/components/schemas/User"}}},"InviteMemberRequest":{"type":"object","required":["email","role"],"properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["admin","member"]}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string","example":"Production Key"},"key_prefix":{"type":"string","example":"sk_live_abc123"},"environment":{"type":"string","enum":["live","test"]},"status":{"type":"string","enum":["active","revoked"]},"last_used_at":{"type":"string","format":"date-time","nullable":true},"created_at":{"type":"string","format":"date-time"}}},"CreateApiKeyRequest":{"type":"object","required":["org_id","name","environment"],"properties":{"org_id":{"type":"string"},"name":{"type":"string","example":"Production Key"},"environment":{"type":"string","enum":["live","test"]}}},"ApiKeyCreatedResponse":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"key_prefix":{"type":"string"},"secret_key":{"type":"string","description":"Full secret key - only shown once!"},"environment":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"UsageStats":{"type":"object","properties":{"total_requests":{"type":"number"},"requests_today":{"type":"number"},"requests_this_month":{"type":"number"},"billable_requests":{"type":"number"},"daily_breakdown":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"count":{"type":"number"}}}}}},"UsageLog":{"type":"object","properties":{"id":{"type":"string"},"endpoint":{"type":"string"},"method":{"type":"string"},"phone_number":{"type":"string","description":"Masked phone number"},"response_code":{"type":"number"},"latency_ms":{"type":"number"},"billable":{"type":"boolean"},"timestamp":{"type":"string","format":"date-time"}}},"BillingOverview":{"type":"object","properties":{"current_period":{"type":"object","properties":{"start":{"type":"string","format":"date-time"},"end":{"type":"string","format":"date-time"},"requests":{"type":"number"},"estimated_cost_cents":{"type":"number"}}},"has_payment_method":{"type":"boolean"},"next_invoice_date":{"type":"string","format":"date"}}},"Invoice":{"type":"object","properties":{"id":{"type":"string"},"stripe_invoice_id":{"type":"string"},"period_start":{"type":"string","format":"date-time"},"period_end":{"type":"string","format":"date-time"},"total_requests":{"type":"number"},"amount_cents":{"type":"number"},"status":{"type":"string","enum":["draft","paid","failed"]},"paid_at":{"type":"string","format":"date-time","nullable":true}}},"RiskCheckResult":{"type":"object","properties":{"phone_number":{"type":"string","example":"+27821234567"},"risk_score":{"type":"number","minimum":0,"maximum":100,"example":25},"risk_level":{"type":"string","enum":["low","medium","high","critical"]},"last_sim_swap":{"type":"string","format":"date-time","nullable":true},"days_since_swap":{"type":"number","nullable":true},"carrier":{"type":"string","example":"Vodacom"},"recommendation":{"type":"string","enum":["allow","challenge","block"]},"checked_at":{"type":"string","format":"date-time"}}},"EventType":{"type":"string","enum":["signup","login","forgot_password","otp_verification","checkout","payment","profile_update","subscription","contact","newsletter","referral","kyc","withdrawal","transfer","other"],"description":"Event context for pattern detection and ML training"},"CheckRequest":{"type":"object","properties":{"phone":{"type":"string","description":"Phone number in E.164 format","example":"+27821234567"},"email":{"type":"string","format":"email","description":"Email address to verify","example":"user@example.com"},"event_type":{"$ref":"#/components/schemas/EventType","description":"Context of when the check is performed (helps build fraud patterns)"},"event_id":{"type":"string","maxLength":128,"description":"Client-provided ID for deduplication and tracking","example":"signup_abc123"},"metadata":{"type":"object","additionalProperties":true,"description":"Additional context data"}},"description":"Either phone OR email is required, but not both"},"PhoneCheckResult":{"type":"object","properties":{"type":{"type":"string","enum":["phone"],"example":"phone"},"phone_number":{"type":"string","example":"+27821234567"},"risk_score":{"type":"number","minimum":0,"maximum":100,"example":25},"risk_level":{"type":"string","enum":["low","medium","high","critical"]},"last_swap_at":{"type":"string","format":"date-time","nullable":true},"swap_count_30d":{"type":"number","example":0},"swap_count_90d":{"type":"number","example":1},"checked_at":{"type":"string","format":"date-time"},"is_sandbox":{"type":"boolean","description":"True if using test API key"}}},"EmailCheckResult":{"type":"object","properties":{"type":{"type":"string","enum":["email"],"example":"email"},"check_id":{"type":"string","description":"Unique check ID for async lookups"},"email":{"type":"string","format":"email"},"risk_score":{"type":"number","minimum":0,"maximum":100,"example":35},"risk_level":{"type":"string","enum":["low","medium","high","critical"]},"signals":{"type":"object","description":"Individual signal scores that contribute to the risk score","properties":{"domain_age_score":{"type":"number","description":"0-20: Domain age risk"},"mx_score":{"type":"number","description":"0-15: MX record validity"},"spf_dmarc_score":{"type":"number","description":"0-15: Email authentication"},"disposable_score":{"type":"number","description":"0-25: Disposable email detection"},"reputation_score":{"type":"number","description":"0-25: Cross-org reputation"},"velocity_score":{"type":"number","description":"0-15: Check frequency"},"feedback_score":{"type":"number","description":"-5 to 20: Community feedback"},"pattern_score":{"type":"number","description":"0-10: Suspicious patterns"},"ml_score":{"type":"number","description":"-5 to 15: ML model score"}}},"is_sandbox":{"type":"boolean","description":"True if using test API key"}}},"EmailCheckQueued":{"type":"object","properties":{"type":{"type":"string","enum":["email"],"example":"email"},"check_id":{"type":"string","description":"Use this ID to poll for results"},"email":{"type":"string","format":"email"},"status":{"type":"string","enum":["pending","processing"]},"message":{"type":"string","example":"Result will be delivered via webhook"}}},"CheckStatus":{"type":"object","properties":{"type":{"type":"string","enum":["email"],"example":"email"},"check_id":{"type":"string"},"email_hash":{"type":"string","description":"SHA256 hash of the email"},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"risk_score":{"type":"number","nullable":true},"risk_level":{"type":"string","nullable":true},"signals":{"type":"object","nullable":true},"requested_at":{"type":"string","format":"date-time"},"completed_at":{"type":"string","format":"date-time","nullable":true},"error_message":{"type":"string","nullable":true}}},"BulkCheckRequest":{"type":"object","required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":100,"description":"Array of check requests (each with either phone OR email)","items":{"$ref":"#/components/schemas/CheckRequest"}}}},"BulkCheckResponse":{"type":"object","properties":{"total":{"type":"integer","description":"Total items processed","example":10},"successful":{"type":"integer","description":"Number of successful checks","example":9},"failed":{"type":"integer","description":"Number of failed checks","example":1},"results":{"type":"array","description":"Results in same order as input items","items":{"type":"object","properties":{"index":{"type":"integer","description":"Position in original array"},"success":{"type":"boolean"},"type":{"type":"string","enum":["phone","email"]},"phone_number":{"type":"string"},"last_swap_at":{"type":"string","format":"date-time","nullable":true},"swap_count_30d":{"type":"number"},"swap_count_90d":{"type":"number"},"check_id":{"type":"string"},"email":{"type":"string"},"signals":{"type":"object"},"status":{"type":"string","enum":["completed","pending","processing"]},"message":{"type":"string"},"risk_score":{"type":"number"},"risk_level":{"type":"string","enum":["low","medium","high","critical"]},"checked_at":{"type":"string","format":"date-time"},"is_sandbox":{"type":"boolean"},"error":{"type":"string","description":"Error message if check failed"}}}}}}}},"paths":{"/auth/register":{"post":{"tags":["Authentication"],"summary":"Register a new user","description":"Create a new user account with email and password. A verification email will be sent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}}},"responses":{"201":{"description":"User registered successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"}}}}}]}}}},"400":{"description":"Registration failed (e.g., email already exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/login":{"post":{"tags":["Authentication"],"summary":"Login with email and password","description":"Authenticate with email and password to receive access and refresh tokens.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Login successful","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"},"tokens":{"$ref":"#/components/schemas/TokenResponse/properties/tokens"}}}}}]}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/auth/verify-email":{"post":{"tags":["Authentication"],"summary":"Verify email address","description":"Verify user's email using the token sent via email.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}}}}},"responses":{"200":{"description":"Email verified successfully"},"400":{"description":"Invalid or expired token"}}}},"/auth/resend-verification":{"post":{"tags":["Authentication"],"summary":"Resend verification email","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"200":{"description":"Verification email sent"},"400":{"description":"Failed to send email"}}}},"/auth/forgot-password":{"post":{"tags":["Authentication"],"summary":"Request password reset","description":"Send a password reset email to the user.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","format":"email"}}}}}},"responses":{"200":{"description":"Reset email sent (if email exists)"}}}},"/auth/reset-password":{"post":{"tags":["Authentication"],"summary":"Reset password","description":"Reset password using the token from the reset email.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["token","password"],"properties":{"token":{"type":"string"},"password":{"type":"string","minLength":8}}}}}},"responses":{"200":{"description":"Password reset successfully"},"400":{"description":"Invalid or expired token"}}}},"/auth/refresh":{"post":{"tags":["Authentication"],"summary":"Refresh access token","description":"Exchange a refresh token for new access and refresh tokens.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["refresh_token"],"properties":{"refresh_token":{"type":"string"}}}}}},"responses":{"200":{"description":"Tokens refreshed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"401":{"description":"Invalid refresh token"}}}},"/auth/logout":{"post":{"tags":["Authentication"],"summary":"Logout user","description":"Invalidate the current session.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Logged out successfully"}}}},"/auth/me":{"get":{"tags":["Authentication"],"summary":"Get current user","description":"Retrieve the currently authenticated user's information.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"User information","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"user":{"$ref":"#/components/schemas/User"}}}}}]}}}}}}},"/org":{"get":{"tags":["Organizations"],"summary":"List organizations","description":"List all organizations the current user belongs to.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"List of organizations","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"organizations":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}}}}}}]}}}}}},"post":{"tags":["Organizations"],"summary":"Create organization","description":"Create a new organization. The current user becomes the owner.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrgRequest"}}}},"responses":{"201":{"description":"Organization created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"organization":{"$ref":"#/components/schemas/Organization"}}}}}]}}}}}}},"/org/{orgId}":{"get":{"tags":["Organizations"],"summary":"Get organization","description":"Get details of a specific organization.","security":[{"BearerAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Organization details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"organization":{"$ref":"#/components/schemas/Organization"}}}}}]}}}}}},"patch":{"tags":["Organizations"],"summary":"Update organization","description":"Update organization settings. Only owners can update.","security":[{"BearerAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"billing_email":{"type":"string","format":"email"}}}}}},"responses":{"200":{"description":"Organization updated"}}}},"/org/{orgId}/members":{"get":{"tags":["Organizations"],"summary":"List members","description":"List all members of an organization.","security":[{"BearerAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of members","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/Member"}}}}}}]}}}}}}},"/org/{orgId}/members/invite":{"post":{"tags":["Organizations"],"summary":"Invite member","description":"Invite a new member to the organization by email.","security":[{"BearerAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteMemberRequest"}}}},"responses":{"201":{"description":"Invitation sent"}}}},"/org/{orgId}/members/{memberId}":{"delete":{"tags":["Organizations"],"summary":"Remove member","description":"Remove a member from the organization. Only owners/admins can remove members.","security":[{"BearerAuth":[]}],"parameters":[{"name":"orgId","in":"path","required":true,"schema":{"type":"string"}},{"name":"memberId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Member removed"}}}},"/org/accept-invite/{token}":{"post":{"tags":["Organizations"],"summary":"Accept invitation","description":"Accept an organization invitation using the invite token.","security":[{"BearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Invitation accepted"}}}},"/keys":{"get":{"tags":["API Keys"],"summary":"List API keys","description":"List all API keys for an organization.","security":[{"BearerAuth":[]}],"parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of API keys","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"api_keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}}}}]}}}}}},"post":{"tags":["API Keys"],"summary":"Create API key","description":"Create a new API key. The full secret key is only returned once upon creation.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}}},"responses":{"201":{"description":"API key created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"api_key":{"$ref":"#/components/schemas/ApiKeyCreatedResponse"}}}}}]}}}}}}},"/keys/{keyId}":{"delete":{"tags":["API Keys"],"summary":"Revoke API key","description":"Revoke an API key. This action cannot be undone.","security":[{"BearerAuth":[]}],"parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string"}},{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"API key revoked"}}}},"/keys/{keyId}/roll":{"post":{"tags":["API Keys"],"summary":"Roll API key","description":"Generate a new secret for an existing API key. The old key will stop working.","security":[{"BearerAuth":[]}],"parameters":[{"name":"keyId","in":"path","required":true,"schema":{"type":"string"}},{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"New secret key generated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"api_key":{"$ref":"#/components/schemas/ApiKeyCreatedResponse"}}}}}]}}}}}}},"/usage/stats":{"get":{"tags":["Usage"],"summary":"Get usage statistics","description":"Get usage statistics including daily breakdown for charts.","security":[{"BearerAuth":[]}],"parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Usage statistics","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"$ref":"#/components/schemas/UsageStats"}}}]}}}}}}},"/usage/logs":{"get":{"tags":["Usage"],"summary":"Get usage logs","description":"Get paginated list of API request logs.","security":[{"BearerAuth":[]}],"parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"page","in":"query","schema":{"type":"integer","default":1}},{"name":"limit","in":"query","schema":{"type":"integer","default":50,"maximum":100}},{"name":"api_key_id","in":"query","schema":{"type":"string"},"description":"Filter by specific API key"},{"name":"start_date","in":"query","schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Usage logs","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"logs":{"type":"array","items":{"$ref":"#/components/schemas/UsageLog"}},"pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"pages":{"type":"integer"}}}}}}}]}}}}}}},"/usage/export":{"get":{"tags":["Usage"],"summary":"Export usage logs","description":"Export usage logs as CSV file.","security":[{"BearerAuth":[]}],"parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"start_date","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"end_date","in":"query","required":true,"schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"CSV file","content":{"text/csv":{"schema":{"type":"string"}}}}}}},"/billing":{"get":{"tags":["Billing"],"summary":"Get billing overview","description":"Get current billing period usage and estimated costs.","security":[{"BearerAuth":[]}],"parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Billing overview","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"$ref":"#/components/schemas/BillingOverview"}}}]}}}}}}},"/billing/setup":{"post":{"tags":["Billing"],"summary":"Create checkout session","description":"Create a Stripe checkout session to set up payment method.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["org_id"],"properties":{"org_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Checkout session URL","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}]}}}}}}},"/billing/portal":{"post":{"tags":["Billing"],"summary":"Create customer portal session","description":"Create a Stripe customer portal session to manage payment methods and view invoices.","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["org_id"],"properties":{"org_id":{"type":"string"}}}}}},"responses":{"200":{"description":"Portal session URL","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}]}}}}}}},"/billing/invoices":{"get":{"tags":["Billing"],"summary":"Get invoices","description":"Get list of invoices for the organization.","security":[{"BearerAuth":[]}],"parameters":[{"name":"org_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of invoices","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"invoices":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}}}}}}]}}}}}}},"/billing/webhook":{"post":{"tags":["Billing"],"summary":"Stripe webhook","description":"Handle Stripe webhook events. This endpoint is called by Stripe.","parameters":[{"name":"stripe-signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Webhook processed"}}}},"/billing/connect-webhook":{"post":{"tags":["Billing"],"summary":"Stripe Connect webhook","description":"Handle signed events from Stripe connected accounts.","parameters":[{"name":"stripe-signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Connect webhook processed"}}}},"/check":{"post":{"tags":["Check"],"summary":"Verify email or phone number","description":"\nUnified endpoint to check the risk score for either an email address or phone number.\n\n**Request:**\n- Provide either `phone` OR `email` (not both)\n- Optionally include `event_type` to improve ML pattern detection\n\n**Event Types:**\nUse the `event_type` field to provide context about when the check is performed. This helps build fraud patterns across your platform and the network:\n- `signup` - New user registration\n- `login` - User authentication\n- `forgot_password` - Password reset request\n- `otp_verification` - OTP/2FA verification\n- `checkout` / `payment` - Financial transactions\n- `subscription` - Recurring payment signup\n- `kyc` - Identity verification\n- `withdrawal` / `transfer` - Money movement\n\n**Email Response:**\n- Synchronous: Returns immediately with risk score and signals\n- Async (rare): Returns 202 with `check_id` for webhook delivery\n\n**Billing:**\n- Phone checks: 1 credit per check\n- Email checks: 1/2/12 credits by tier (basic/standard/premium)\n        ","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckRequest"},"examples":{"email_signup":{"summary":"Email check for signup","value":{"email":"user@example.com","event_type":"signup","event_id":"signup_abc123"}},"email_checkout":{"summary":"Email check for checkout","value":{"email":"buyer@company.com","event_type":"checkout","metadata":{"order_id":"ORD-12345","amount_cents":9900}}},"phone_login":{"summary":"Phone check for login","value":{"phone":"+27821234567","event_type":"login"}}}}}},"responses":{"200":{"description":"Check completed successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"oneOf":[{"$ref":"#/components/schemas/PhoneCheckResult"},{"$ref":"#/components/schemas/EmailCheckResult"}]}}}]}}}},"202":{"description":"Email check queued (async processing)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"$ref":"#/components/schemas/EmailCheckQueued"}}}]}}}},"400":{"description":"Invalid request (e.g., both phone and email provided)"},"401":{"description":"Invalid or missing API key"}}}},"/check/bulk":{"post":{"tags":["Check"],"summary":"Bulk verify emails and/or phone numbers","description":"\nCheck multiple emails and/or phone numbers in a single request (up to 100 items).\n\n**Request:**\n- Provide an array of items, each with either `phone` OR `email`\n- Each item can have its own `event_type`, `event_id`, and `metadata`\n\n**Response:**\nReturns an array of results in the same order as the input items. Each result includes:\n- `index`: Position in the original array\n- `success`: Whether the check succeeded\n- `type`: \"phone\" or \"email\"\n- Risk score and details (if successful)\n- `error`: Error message (if failed)\n\n**Billing:**\nEach item is billed separately:\n- Phone checks: 1 credit per check\n- Email checks: 1/2/12 credits by tier (basic/standard/premium)\n\n**Note:** Failed items don't consume credits.\n        ","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCheckRequest"},"examples":{"mixed_bulk":{"summary":"Mixed email and phone bulk check","value":{"items":[{"email":"user1@example.com","event_type":"signup"},{"email":"user2@company.com","event_type":"signup"},{"phone":"+27821234567","event_type":"login"},{"email":"buyer@shop.com","event_type":"checkout","metadata":{"order_id":"ORD-123"}}]}},"emails_only":{"summary":"Bulk email verification","value":{"items":[{"email":"lead1@example.com"},{"email":"lead2@example.com"},{"email":"lead3@example.com"}]}}}}}},"responses":{"200":{"description":"Bulk check completed","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"$ref":"#/components/schemas/BulkCheckResponse"}}}]}}}},"400":{"description":"Invalid request (e.g., too many items, invalid format)"},"401":{"description":"Invalid or missing API key"}}}},"/check/{checkId}":{"get":{"tags":["Check"],"summary":"Get async check status","description":"\nRetrieve the status and result of an async email check.\n\nUse this endpoint to poll for results if you received a 202 response from the check endpoint.\nFor real-time delivery, configure a webhook instead.\n        ","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"checkId","in":"path","required":true,"description":"The check_id returned from the initial check request","schema":{"type":"string"}}],"responses":{"200":{"description":"Check status retrieved","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"$ref":"#/components/schemas/CheckStatus"}}}]}}}},"401":{"description":"Invalid or missing API key"},"404":{"description":"Check not found"}}}},"/check/sandbox":{"get":{"tags":["Check"],"summary":"Get sandbox test data","description":"\nReturns test phone numbers and emails that can be used with test API keys to get predictable responses.\n\nUse these values in development to test your integration without consuming live credits.\n        ","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Sandbox test data","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessResponse"},{"type":"object","properties":{"content":{"type":"object","properties":{"description":{"type":"string"},"phone_numbers":{"type":"object","description":"Test phone numbers with different risk profiles"},"emails":{"type":"object","description":"Test emails with different risk profiles"},"event_types":{"type":"object","properties":{"description":{"type":"string"},"available":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},"example":{"type":"object"}}}}}}}]}}}}}}}}}