Overview
AudioPod AI supports multiple authentication methods with advanced security features:
JWT Authentication : Session-based authentication with device tracking
API Key Authentication : Server-to-server integration with scoped permissions
OAuth Integration : Google and GitHub single sign-on with account linking
Session Management : Multi-device session tracking and management
Security Features : CAPTCHA protection, rate limiting, and abuse prevention
Phone Verification : SMS-based phone number verification
Device Management : Trust and security management for user devices
All authenticated endpoints require either a valid JWT token in the
Authorization: Bearer {token} header or an API key in the X-API-Key:{" "} {api_key} header.
JWT Authentication
Login
Authenticate with email/password to receive JWT tokens.
POST /api/v1/auth/token
Content-Type : application/x-www-form-urlencoded
username=user@example.com&password=secure_password
Response:
{
"user" : {
"id" : "550e8400-e29b-41d4-a716-446655440000" ,
"email" : "user@example.com" ,
"full_name" : "John Doe" ,
"is_active" : true ,
"is_verified" : true ,
"created_at" : "2024-01-15T10:30:00Z" ,
"updated_at" : "2024-01-15T10:30:00Z" ,
"image" : null ,
"phone_number" : null ,
"phone_verified" : false ,
"user_type" : null ,
"audio_usage" : null ,
"credits" : {
"credits_balance" : 1500 ,
"payg_balance" : 500 ,
"total_available_credits" : 2000 ,
"credits_used_today" : 0 ,
"daily_limit" : 10000 ,
"last_reset_at" : "2024-01-15T00:00:00Z"
},
"subscription" : {
"plan_id" : "price_free" ,
"plan_name" : "Free" ,
"is_free_plan" : true ,
"status" : "active" ,
"current_period_start" : "2024-01-15T10:30:00Z" ,
"current_period_end" : "2024-02-15T10:30:00Z" ,
"cancel_at" : null
},
"is_eligible_for_first_time_discount" : true ,
"first_time_discount_active" : true
},
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"token_type" : "bearer" ,
"expires_in" : 3600
}
Refresh Token
Refresh an expired access token using the refresh token.
POST /api/v1/auth/refresh
Content-Type : application/json
{
"refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Logout
Invalidate current tokens and end the session.
POST /api/v1/auth/logout
Authorization : Bearer {access_token}
OAuth Authentication
Google OAuth
Authenticate or register using Google account. This endpoint handles both new user registration and existing user login.
POST /api/v1/auth/oauth/google
Content-Type : application/json
{
"profile" : {
"email" : "user@example.com" ,
"name" : "John Doe" ,
"picture" : "https://lh3.googleusercontent.com/a/..."
},
"account" : {
"id_token" : "eyJhbGciOiJSUzI1NiIsImtpZCI6..." ,
"access_token" : "ya29.a0AfH6SMC..." ,
"providerAccountId" : "1234567890" ,
"type" : "oauth" ,
"expires_at" : 1640995200
},
"browser_fingerprint" : "optional-fingerprint-string"
}
GitHub OAuth
Authenticate or register using GitHub account. Same response format as Google OAuth.
POST /api/v1/auth/oauth/github
Content-Type : application/json
{
"profile" : {
"email" : "user@example.com" ,
"name" : "John Doe" ,
"picture" : "https://avatars.githubusercontent.com/u/..."
},
"account" : {
"access_token" : "ghp_abcdef1234567890" ,
"providerAccountId" : "987654321" ,
"type" : "oauth"
}
}
OAuth Response (for both Google and GitHub):
Returns the same format as login - complete user object with tokens:
{
"user" : {
"id" : "550e8400-e29b-41d4-a716-446655440000" ,
"email" : "user@example.com" ,
"full_name" : "John Doe" ,
"image" : "https://lh3.googleusercontent.com/a/..." ,
"is_active" : true ,
"is_verified" : true ,
"created_at" : "2024-01-15T10:30:00Z" ,
"credits" : {
"credits_balance" : 5000 ,
"payg_balance" : 0 ,
"total_available_credits" : 5000
},
"subscription" : {
"plan_name" : "Free" ,
"is_free_plan" : true ,
"status" : "active"
}
},
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"token_type" : "bearer" ,
"expires_in" : 3600
}
API Key Authentication
Generate API Key
Create a new API key for programmatic access.
POST /api/v1/auth/api-keys
Authorization : Bearer {access_token}
Content-Type : application/json
{
"name" : "Production API Key" ,
"scopes" : [ "voice:read" , "voice:write" ]
}
Response:
{
"id" : "550e8400-e29b-41d4-a716-446655440000" ,
"name" : "Production API Key" ,
"api_key" : "ap_live_sk_1234567890abcdef" ,
"description" : "API key for production environment" ,
"status" : "active" ,
"created_at" : "2024-01-15T10:30:00Z" ,
"last_used_at" : null ,
"revoked_at" : null
}
List API Keys
Get all API keys for the authenticated user.
GET /api/v1/auth/api-keys?status=active
Authorization : Bearer {access_token}
Revoke API Key
Disable an API key permanently.
DELETE /api/v1/auth/api-keys/{key_id}
Authorization : Bearer {access_token}
User Registration
Step 1: Initiate Registration
Start the registration process and receive verification code.
POST /api/v1/auth/initiate-registration
Content-Type : application/json
{
"email" : "newuser@example.com" ,
"password" : "secure_password123" ,
"full_name" : "Jane Doe"
}
Response:
{
"message" : "Verification code sent to email" ,
"email" : "newuser@example.com"
}
Step 2: Verify Registration
Complete registration with verification code from email.
POST /api/v1/auth/verify-registration
Content-Type : application/json
{
"email" : "newuser@example.com" ,
"verification_code" : "123456"
}
Response:
{
"user" : {
"id" : "550e8400-e29b-41d4-a716-446655440000" ,
"email" : "newuser@example.com" ,
"full_name" : "Jane Doe" ,
"image" : null ,
"phone_number" : null ,
"phone_verified" : false ,
"is_active" : true ,
"is_verified" : true ,
"created_at" : "2024-01-15T10:30:00Z" ,
"updated_at" : "2024-01-15T10:30:00Z" ,
"credits" : {
"credits_balance" : 5000 ,
"payg_balance" : 0 ,
"total_available_credits" : 5000 ,
"credits_used_today" : 0 ,
"daily_limit" : 10000 ,
"last_reset_at" : "2024-01-15T00:00:00Z"
},
"subscription" : {
"plan_id" : "price_free" ,
"plan_name" : "Free" ,
"is_free_plan" : true ,
"status" : "active" ,
"current_period_start" : "2024-01-15T10:30:00Z" ,
"current_period_end" : "2024-02-15T10:30:00Z" ,
"cancel_at" : null
},
"is_eligible_for_first_time_discount" : true ,
"first_time_discount_active" : true
},
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ,
"token_type" : "bearer" ,
"expires_in" : 3600
}
Password Reset
Request and confirm password reset.
POST /api/v1/auth/forgot-password
Content-Type : application/json
{
"email" : "user@example.com"
}
User Profile Management
Get Current User
Retrieve complete information about the authenticated user including credits, subscription, and security settings.
GET /api/v1/auth/me
Authorization : Bearer {access_token}
Response:
{
"id" : "550e8400-e29b-41d4-a716-446655440000" ,
"email" : "user@example.com" ,
"full_name" : "John Doe" ,
"image" : "https://lh3.googleusercontent.com/a/..." ,
"phone_number" : "+1234567890" ,
"phone_verified" : true ,
"user_type" : "individual" ,
"audio_usage" : "personal" ,
"is_active" : true ,
"is_verified" : true ,
"created_at" : "2024-01-15T10:30:00Z" ,
"updated_at" : "2024-01-15T11:00:00Z" ,
"credits" : {
"credits_balance" : 1500 ,
"payg_balance" : 500 ,
"total_available_credits" : 2000 ,
"credits_used_today" : 150 ,
"daily_limit" : 10000 ,
"last_reset_at" : "2024-01-15T00:00:00Z"
},
"subscription" : {
"plan_id" : "price_pro_monthly" ,
"plan_name" : "Pro" ,
"is_free_plan" : false ,
"status" : "active" ,
"current_period_start" : "2024-01-15T00:00:00Z" ,
"current_period_end" : "2024-02-15T00:00:00Z" ,
"cancel_at" : null
},
"is_eligible_for_first_time_discount" : false ,
"first_time_discount_active" : false
}
Update Profile
Update user profile information.
PATCH /api/v1/auth/me
Authorization : Bearer {access_token}
Content-Type : application/json
{
"full_name" : "Updated Name" ,
"user_type" : "individual" ,
"audio_usage" : "personal" ,
"phone_number" : "+1234567890" ,
"country_code" : "US"
}
Updating phone number will reset phone verification status. You’ll need to verify the new number using the phone verification endpoints.
Session Management
Validate Current Session
Check if the current session is valid and get detailed session information.
GET /api/v1/auth/session/validate
Authorization : Bearer {access_token}
Response:
{
"is_valid" : true ,
"session_info" : {
"session_id" : "sess_abc123" ,
"user_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"device_info" : "Chrome on Windows" ,
"ip_address" : "192.168.1.1" ,
"created_at" : "2024-01-15T10:30:00Z" ,
"last_active" : "2024-01-15T11:00:00Z" ,
"expires_at" : "2024-01-15T16:30:00Z" ,
"is_current" : true
},
"user" : { /* Complete user object */ },
"expires_in" : 18000 ,
"needs_refresh" : false
}
List Active Sessions
View and manage all your active sessions across devices.
GET /api/v1/auth/sessions
Authorization : Bearer {access_token}
Response:
[
{
"session_id" : "sess_abc123" ,
"user_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"device_info" : "Chrome on Windows" ,
"ip_address" : "192.168.1.1" ,
"user_agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" ,
"created_at" : "2024-01-15T10:30:00Z" ,
"last_active" : "2024-01-15T11:00:00Z" ,
"expires_at" : "2024-01-15T16:30:00Z" ,
"is_current" : true
},
{
"session_id" : "sess_def456" ,
"user_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"device_info" : "Safari on iPhone" ,
"ip_address" : "10.0.0.1" ,
"created_at" : "2024-01-14T09:15:00Z" ,
"last_active" : "2024-01-14T22:45:00Z" ,
"expires_at" : "2024-01-15T04:15:00Z" ,
"is_current" : false
}
]
Revoke Sessions
Revoke specific sessions or all other sessions for security.
POST /api/v1/auth/sessions/revoke
Authorization : Bearer {access_token}
Content-Type : application/json
{
"session_id" : "sess_def456" ,
"revoke_all_others" : false
}
Enhanced Token Refresh
Refresh access token with complete user data (alternative to basic refresh).
POST /api/v1/auth/refresh-enhanced
Content-Type : application/json
{
"refresh_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Check Token Health
Check token validity and expiration status without full validation.
GET /api/v1/auth/token-health
Authorization : Bearer {access_token}
Response:
{
"valid" : true ,
"expired" : false ,
"expires_in_seconds" : 1800 ,
"expires_in_minutes" : 30 ,
"should_refresh" : false ,
"user_id" : "550e8400-e29b-41d4-a716-446655440000"
}
Device Management
List User Devices
Get all devices and browsers the user has logged in from.
GET /api/v1/auth/devices?include_inactive=true
Authorization : Bearer {access_token}
Response:
{
"devices" : [
{
"id" : "dev_abc123" ,
"device_fingerprint" : "fp_xyz789" ,
"display_name" : "Chrome on Windows" ,
"browser" : "Chrome" ,
"os" : "Windows" ,
"device_type" : "desktop" ,
"ip_address" : "192.168.1.1" ,
"location" : "New York, NY, US" ,
"timezone" : "America/New_York" ,
"first_seen" : "2024-01-10T10:00:00Z" ,
"last_seen" : "2024-01-15T11:00:00Z" ,
"last_login_method" : "password" ,
"login_count" : 15 ,
"is_active" : true ,
"is_current_session" : true ,
"is_trusted" : true ,
"is_blocked" : false ,
"current_session_id" : "sess_abc123"
}
],
"total_count" : 3 ,
"active_count" : 2 ,
"current_device" : { /* Current device object */ },
"trusted_count" : 2
}
Security Features
CAPTCHA Protection
CAPTCHA challenges are automatically required based on IP reputation and activity patterns.
Check if CAPTCHA is Required
GET /api/v1/auth/captcha/required
Generate CAPTCHA Challenge
GET /api/v1/auth/captcha/generate
Response:
{
"captcha_id" : "capt_abc123" ,
"question" : "What is 7 + 15?" ,
"expires_in" : 300
}
Verify CAPTCHA Response
POST /api/v1/auth/captcha/verify
Content-Type : application/json
{
"captcha_id" : "capt_abc123" ,
"answer" : "22"
}
Phone Verification
Send Phone Verification Code
Send SMS verification code to user’s phone number.
POST /api/v1/auth/send-phone-verification
Authorization : Bearer {access_token}
Content-Type : application/json
{
"phone_number" : "+1234567890" ,
"country_code" : "US"
}
Verify Phone Number
Verify phone number with received OTP code.
POST /api/v1/auth/verify-phone
Authorization : Bearer {access_token}
Content-Type : application/json
{
"phone_number" : "+1234567890" ,
"otp_code" : "123456"
}
Password Management
Change Password
Change user password (requires current password).
POST /api/v1/auth/change-password
Authorization : Bearer {access_token}
Content-Type : application/json
{
"current_password" : "current_password123" ,
"new_password" : "new_secure_password456"
}
Password changes automatically log out all other active sessions for security.
OAuth Account Management
Link OAuth Provider
Link additional OAuth providers to your account.
POST /api/v1/auth/account-providers
Authorization : Bearer {access_token}
Content-Type : application/json
{
"provider" : "google" ,
"provider_account_id" : "1234567890" ,
"type" : "oauth" ,
"access_token" : "ya29.a0AfH6SMC..." ,
"id_token" : "eyJhbGciOiJSUzI1NiIs..."
}
List Linked Providers
GET /api/v1/auth/account-providers
Authorization : Bearer {access_token}
Unlink Provider
DELETE /api/v1/auth/account-providers/{provider}
Authorization : Bearer {access_token}
Rate Limiting
Authentication endpoints have specific rate limits to prevent abuse:
Endpoint Rate Limit Window Notes /auth/initiate-registration5 requests 1 minute Prevents spam registrations /auth/verify-registration10 requests 1 minute Prevents code brute force /auth/forgot-password3 requests 1 hour Prevents email flooding /auth/reset-password5 requests 1 hour Prevents token brute force
Additional Security:
CAPTCHA required after suspicious activity
Maximum 3 signups per device/IP combination
Email flood protection across all users
Automatic account flagging for review
Rate Limit Headers:
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4
X-RateLimit-Reset: 1640995200
Retry-After: 60
Error Handling
Authentication Error Responses
401 Unauthorized - Invalid Credentials
{
"error" : {
"code" : "invalid_credentials" ,
"message" : "Incorrect email or password"
}
}
401 Unauthorized - Token Expired
{
"error" : {
"code" : "token_expired" ,
"message" : "Access token has expired" ,
"suggestion" : "Use refresh token to get a new access token"
}
}
401 Unauthorized - Invalid Token
{
"error" : {
"code" : "invalid_token" ,
"message" : "Invalid token format or signature"
}
}
404 Not Found - User Not Found
{
"error" : {
"code" : "user_not_found" ,
"message" : "User not found"
}
}
Registration Error Responses
400 Bad Request - Email Already Registered
{
"error" : {
"code" : "email_already_registered" ,
"message" : "This email address is already registered."
}
}
400 Bad Request - Invalid Verification Code
{
"error" : {
"code" : "invalid_verification_code" ,
"message" : "Invalid email or verification code."
}
}
400 Bad Request - Verification Code Expired
{
"error" : {
"code" : "verification_code_expired" ,
"message" : "Verification code has expired. Please register again."
}
}
400 Bad Request - Too Many Signups
{
"error" : {
"code" : "too_many_signups" ,
"message" : "Signup limit reached for this device or network."
}
}
OAuth Error Responses
400 Bad Request - Unsupported Provider
{
"error" : {
"code" : "provider_not_supported" ,
"message" : "Unsupported provider: facebook"
}
}
400 Bad Request - OAuth Verification Failed
{
"error" : {
"code" : "oauth_verification_failed" ,
"message" : "Invalid OAuth token data"
}
}
Security Error Responses
400 Bad Request - CAPTCHA Required
{
"detail" : "Security verification required. Please complete the CAPTCHA challenge." ,
"headers" : {
"X-Captcha-Required" : "true"
}
}
400 Bad Request - Invalid CAPTCHA
{
"detail" : "Invalid security verification. Please try again." ,
"headers" : {
"X-Captcha-Required" : "true"
}
}
400 Bad Request - Password Recently Used
{
"error" : {
"code" : "password_recently_used" ,
"message" : "Cannot reuse recent passwords"
}
}
400 Bad Request - Invalid Password
{
"error" : {
"code" : "invalid_password" ,
"message" : "Incorrect current password"
}
}
Rate Limiting and System Errors
{
"error" : {
"code" : "rate_limit_exceeded" ,
"message" : "Too many requests" ,
"retry_after" : 60
}
}
Headers: X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 60
500 Internal Server Error - System Error
{
"error" : {
"code" : "system_error" ,
"message" : "Failed to process request" ,
"details" : {
"error" : "Internal server error details"
}
}
}
422 Validation Error - Invalid Input
Authentication endpoints may include additional headers:
Header Description Example X-Captcha-RequiredCAPTCHA verification needed "true"X-RateLimit-LimitRequest limit per window 5X-RateLimit-RemainingRemaining requests in window 4X-RateLimit-ResetWindow reset timestamp 1640995200Retry-AfterSeconds to wait when rate limited 60
Scopes and Permissions
Available Scopes
API keys can be granted specific scopes to limit access:
Scope Description voice:readList and read voice data voice:writeCreate and modify voices voice:generateGenerate speech with voices music:readAccess music generation data music:generateGenerate music content translation:useUse translation services account:readRead account information account:writeModify account settings credits:readView credit balance admin:*Administrative access
Scope Inheritance
Some scopes include others:
voice:write includes voice:read
admin:* includes all scopes
account:write includes account:read
Integration Examples
Web Application (React)
// React authentication hook
import { useState , useEffect } from "react" ;
export function useAuth () {
const [ user , setUser ] = useState ( null );
const [ loading , setLoading ] = useState ( true );
const login = async ( email , password ) => {
const response = await fetch ( "/api/v1/auth/token" , {
method: "POST" ,
headers: { "Content-Type" : "application/x-www-form-urlencoded" },
body: new URLSearchParams ({ username: email , password }),
});
if ( response . ok ) {
const data = await response . json ();
localStorage . setItem ( "access_token" , data . access_token );
localStorage . setItem ( "refresh_token" , data . refresh_token );
setUser ( data . user );
return true ;
}
return false ;
};
const logout = async () => {
await fetch ( "/api/v1/auth/logout" , {
method: "POST" ,
headers: {
Authorization: `Bearer ${ localStorage . getItem ( "access_token" ) } ` ,
},
});
localStorage . removeItem ( "access_token" );
localStorage . removeItem ( "refresh_token" );
setUser ( null );
};
return { user , login , logout , loading };
}
Server-to-Server (Python)
# Python client with API key authentication
import requests
class AudioPodClient :
def __init__ ( self , api_key ):
self .api_key = api_key
self .base_url = "https://api.audiopod.ai/api/v1"
self .session = requests.Session()
self .session.headers.update({
"X-API-Key" : api_key,
"User-Agent" : "AudioPod-Python-Client/1.0"
})
def generate_speech ( self , text , voice_id = "aura-en-female" ):
response = self .session.post(
f " { self .base_url } /voice/clone/" ,
json = {
"input_text" : text,
"voice_id" : voice_id
}
)
response.raise_for_status()
return response.json()
# Usage
client = AudioPodClient( "ap_live_sk_your_api_key" )
result = client.generate_speech( "Hello, world!" )
Best Practices
Security Recommendations
Store tokens securely : Use secure storage for refresh tokens
Implement token rotation : Regularly refresh access tokens
Use HTTPS only : Never send tokens over unencrypted connections
Validate tokens server-side : Always verify tokens on your backend
Implement logout : Properly invalidate tokens when users log out
Use minimal scopes : Grant only necessary permissions to API keys
Monitor usage : Track API key usage and revoke suspicious keys
Error Handling
# Robust error handling example
import requests
from requests.exceptions import RequestException
def handle_auth_request ( func , * args , ** kwargs ):
try :
response = func( * args, ** kwargs)
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
raise AuthError( "Request timed out" )
except requests.exceptions.ConnectionError:
raise AuthError( "Connection failed" )
except requests.exceptions.HTTPError as e:
if e.response.status_code == 401 :
raise AuthError( "Invalid credentials" )
elif e.response.status_code == 429 :
raise AuthError( "Rate limit exceeded" )
else :
raise AuthError( f "HTTP error: { e.response.status_code } " )
except RequestException:
raise AuthError( "Unexpected error occurred" )
Token Management
# Automatic token refresh implementation
import time
import jwt
class TokenManager :
def __init__ ( self , access_token , refresh_token ):
self .access_token = access_token
self .refresh_token = refresh_token
def get_valid_token ( self ):
if self ._is_token_expired( self .access_token):
self ._refresh_access_token()
return self .access_token
def _is_token_expired ( self , token ):
try :
payload = jwt.decode(token, options = { "verify_signature" : False })
return payload[ 'exp' ] < time.time() + 60 # Refresh 1 min before expiry
except :
return True
def _refresh_access_token ( self ):
response = requests.post(
"https://api.audiopod.ai/api/v1/auth/refresh" ,
json = { "refresh_token" : self .refresh_token}
)
if response.status_code == 200 :
data = response.json()
self .access_token = data[ "access_token" ]
else :
raise AuthError( "Failed to refresh token" )