Skip to content

Authentication

The Vidivo authentication system uses JWT RS256 tokens. Access tokens expire after 15 minutes; refresh tokens expire after 30 days and are rotated on each use.

All auth endpoints live under /v1/auth/ and are unauthenticated (no Bearer token required).


Create a new user account. A verification email is sent automatically.

Rate limit: 3 requests per hour per IP.

POST /v1/auth/register
Content-Type: application/json
{
"email": "jane@example.com",
"password": "SecureP@ssw0rd!",
"display_name": "Jane Smith"
}
FieldTypeRequiredDescription
emailstringYesValid email address. Must be unique.
passwordstringYesMinimum 8 characters.
display_namestringNoPublic name shown to guests. Max 80 characters.
HTTP/1.1 201 Created
Content-Type: application/json
{
"user": {
"id": "01JN2X4K8M3F7QPZRVWT6YBHCE",
"email": "jane@example.com",
"display_name": "Jane Smith",
"role": "user",
"email_verified": false,
"created_at": "2026-03-15T10:00:00Z"
},
"access_token": "eyJhbGciOiJSUzI1NiJ9...",
"refresh_token": "rt_01JN2X4K8M3F7QPZRVWT6YBHCE",
"expires_in": 900
}

The user must verify their email before accessing host features.

CodeStatusDescription
validation_error400Missing or invalid fields
conflict409Email already registered
rate_limited429Too many registration attempts

Authenticate with email and password.

Rate limit: 5 requests per 15 minutes per IP.

POST /v1/auth/login
Content-Type: application/json
{
"email": "jane@example.com",
"password": "SecureP@ssw0rd!"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"user": {
"id": "01JN2X4K8M3F7QPZRVWT6YBHCE",
"email": "jane@example.com",
"display_name": "Jane Smith",
"role": "verified_user",
"email_verified": true,
"created_at": "2026-03-15T10:00:00Z"
},
"access_token": "eyJhbGciOiJSUzI1NiJ9...",
"refresh_token": "rt_01JN2X4K8M3F7QPZRVWT6YBHCE",
"expires_in": 900
}
CodeStatusDescription
invalid_credentials401Email or password is incorrect
rate_limited429Too many login attempts

Exchange a refresh token for a new access token. The refresh token is rotated on each call --- the old refresh token is invalidated immediately.

POST /v1/auth/refresh
Content-Type: application/json
{
"refresh_token": "rt_01JN2X4K8M3F7QPZRVWT6YBHCE"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "eyJhbGciOiJSUzI1NiJ9...",
"refresh_token": "rt_01JN2X5L9N4G8RQASWU7ZCIDFE",
"expires_in": 900
}
CodeStatusDescription
invalid_token401Refresh token is invalid, expired, or already used

Invalidate the current session. The refresh token is revoked and cannot be used again.

POST /v1/auth/logout
Content-Type: application/json
{
"refresh_token": "rt_01JN2X5L9N4G8RQASWU7ZCIDFE"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "logged out successfully"
}

Verify a user’s email address using the token from the verification email.

POST /v1/auth/verify-email
Content-Type: application/json
{
"token": "verify_abc123def456"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "email verified successfully"
}
CodeStatusDescription
invalid_token401Token is invalid or expired

Request a password reset email. Always returns the same message to prevent user enumeration.

Rate limit: 10 requests per hour per IP.

POST /v1/auth/password/reset
Content-Type: application/json
{
"email": "jane@example.com"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "if an account with that email exists, a password reset link has been sent"
}

Set a new password using the token from the password reset email.

POST /v1/auth/password/confirm
Content-Type: application/json
{
"token": "reset_abc123def456",
"new_password": "NewSecureP@ss!"
}
HTTP/1.1 200 OK
Content-Type: application/json
{
"message": "password has been reset successfully"
}
CodeStatusDescription
invalid_token401Reset token is invalid or expired
validation_error400Password does not meet requirements

Authenticate with a Google OAuth ID token. Creates a new account if the email is not yet registered, or links the Google account if the email already exists.

Rate limit: 5 requests per 15 minutes per IP.

POST /v1/auth/google
Content-Type: application/json
{
"id_token": "eyJhbGciOiJSUzI1NiJ9..."
}
FieldTypeRequiredDescription
id_tokenstringYesGoogle OAuth2 ID token from the client SDK

Same format as POST /v1/auth/login.

CodeStatusDescription
invalid_token401Google ID token is invalid or expired
rate_limited429Too many login attempts

Authenticate with an Apple Sign-In ID token. Creates a new account if not registered, or links the Apple account if the email already exists.

Rate limit: 5 requests per 15 minutes per IP.

POST /v1/auth/apple
Content-Type: application/json
{
"id_token": "eyJhbGciOiJSUzI1NiJ9...",
"display_name": "Jane Smith"
}
FieldTypeRequiredDescription
id_tokenstringYesApple Sign-In identity token
display_namestringNoDisplay name (Apple may not share this on subsequent logins)

Same format as POST /v1/auth/login.

CodeStatusDescription
invalid_token401Apple ID token is invalid or expired
rate_limited429Too many login attempts

Create a guest session for an unauthenticated caller. Guest sessions allow joining a call without registering an account.

POST /v1/auth/guest-session
Content-Type: application/json
{
"display_name": "Alex"
}
FieldTypeRequiredDescription
display_namestringNoGuest’s display name shown during the call
HTTP/1.1 201 Created
Content-Type: application/json
{
"guest_session_id": "gs_a1b2c3d4e5f6",
"access_token": "eyJhbGciOiJSUzI1NiJ9...",
"expires_in": 86400
}

Terminal window
# Register
curl -X POST https://api.vidivo.app/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"jane@example.com","password":"SecureP@ssw0rd!","display_name":"Jane Smith"}'
# Login
curl -X POST https://api.vidivo.app/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"jane@example.com","password":"SecureP@ssw0rd!"}'
# Refresh
curl -X POST https://api.vidivo.app/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token":"rt_01JN2X4K8M3F7QPZRVWT6YBHCE"}'
# Logout
curl -X POST https://api.vidivo.app/v1/auth/logout \
-H "Content-Type: application/json" \
-d '{"refresh_token":"rt_01JN2X5L9N4G8RQASWU7ZCIDFE"}'
# Google login
curl -X POST https://api.vidivo.app/v1/auth/google \
-H "Content-Type: application/json" \
-d '{"id_token":"eyJhbGciOiJSUzI1NiJ9..."}'
# Guest session
curl -X POST https://api.vidivo.app/v1/auth/guest-session \
-H "Content-Type: application/json" \
-d '{"display_name":"Alex"}'

Register / Login / OAuth
|
v
access_token (15 min TTL)
refresh_token (30 day TTL)
|
| access_token expires
v
POST /v1/auth/refresh
+-- Old refresh_token invalidated
+-- New access_token + refresh_token issued
|
| logout / session revoked
v
refresh_token invalidated
All sessions for token invalidated

Access tokens contain the following claims:

{
"sub": "01JN2X4K8M3F7QPZRVWT6YBHCE",
"email": "jane@example.com",
"role": "verified_user",
"iat": 1710000000,
"exp": 1710000900,
"iss": "api.vidivo.app"
}
ClaimDescription
subUser ID (UUID format)
emailUser email address
roleCurrent role: guest, user, verified_user, host, admin
iatIssued-at timestamp (Unix)
expExpiry timestamp (Unix)
issIssuer --- always api.vidivo.app