Skip to content

Users

The Users API manages user profiles, host onboarding, avatar uploads, and availability scheduling. All endpoints under /v1/users/me require authentication.


Retrieve the full profile of the authenticated user.

Authentication: Bearer token required.

GET /v1/users/me
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
{
"id": "01JN2X4K8M3F7QPZRVWT6YBHCE",
"email": "jane@example.com",
"display_name": "Jane Smith",
"username": "janesmith",
"bio": "Life coach and productivity consultant",
"avatar_url": "https://cdn.vidivo.app/avatars/01JN2X4K.jpg",
"role": "host",
"email_verified": true,
"is_age_verified": true,
"is_available": true,
"rate_per_minute": "2.50",
"window_size_minutes": 10,
"payout_enabled": true,
"created_at": "2026-03-15T10:00:00Z"
}

Update the authenticated user’s profile. Only included fields are updated (partial update).

Authentication: Bearer token required.

PUT /v1/users/me
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: application/json
{
"display_name": "Jane Smith-Jones",
"bio": "Executive coach specializing in leadership development",
"username": "janecoach"
}
FieldTypeRequiredDescription
display_namestringNoPublic name. Max 80 characters.
biostringNoProfile bio. Max 500 characters.
usernamestringNoUnique username for public profile URL.

Returns the updated user profile (same format as GET /v1/users/me).

CodeStatusDescription
validation_error400Invalid field values
conflict409Username already taken
unauthorized401Missing or invalid token

Upload a profile avatar image. The image is resized to 512x512 pixels and stored in Cloudflare R2.

Authentication: Bearer token required.

PUT /v1/users/me/avatar
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: multipart/form-data
FieldTypeRequiredDescription
avatarfileYesImage file (JPEG, PNG, WebP, or GIF). Max 5 MB.
Terminal window
curl -X PUT https://api.vidivo.app/v1/users/me/avatar \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiJ9..." \
-F "avatar=@photo.jpg"
{
"avatar_url": "https://cdn.vidivo.app/avatars/01JN2X4K.jpg"
}
CodeStatusDescription
validation_error400File too large or unsupported format
unauthorized401Missing or invalid token

Transition a verified user to the host role. Requires email verification and age verification to be completed first.

Authentication: Bearer token required (role: verified_user).

POST /v1/users/me/become-host
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: application/json
{
"username": "janecoach",
"bio": "Life coach and productivity consultant",
"rate_per_minute": "2.50",
"window_size_minutes": 10
}
FieldTypeRequiredDescription
usernamestringYesUnique username for public profile
biostringNoProfile bio
rate_per_minutestringYesPer-minute rate in USD
window_size_minutesintegerYesBilling window size (1—60 minutes)

Returns the updated user profile with role: "host".

CodeStatusDescription
forbidden403Email not verified or age verification not complete
conflict409Username already taken
validation_error400Invalid rate or window size

Set or update the host’s per-minute billing rate.

Authentication: Bearer token required (role: host or admin).

PUT /v1/users/me/rate
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: application/json
{
"rate_per_minute": "3.00"
}
{
"rate_per_minute": "3.00"
}

Toggle the host’s online/offline status. When available, the host appears in search results and can receive calls.

Authentication: Bearer token required.

PUT /v1/users/me/toggle-available
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
{
"is_available": true
}

Retrieve the host’s weekly availability schedule.

Authentication: Bearer token required.

GET /v1/users/me/availability
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
{
"slots": [
{
"day_of_week": 1,
"start_time": "09:00",
"end_time": "17:00"
},
{
"day_of_week": 2,
"start_time": "09:00",
"end_time": "17:00"
},
{
"day_of_week": 3,
"start_time": "10:00",
"end_time": "14:00"
}
]
}
FieldTypeDescription
day_of_weekinteger0 = Sunday, 1 = Monday, …, 6 = Saturday
start_timestringStart time in HH:MM format (UTC)
end_timestringEnd time in HH:MM format (UTC)

Replace the host’s entire weekly availability schedule with new slots.

Authentication: Bearer token required.

PUT /v1/users/me/availability
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: application/json
{
"slots": [
{ "day_of_week": 1, "start_time": "09:00", "end_time": "17:00" },
{ "day_of_week": 2, "start_time": "09:00", "end_time": "17:00" },
{ "day_of_week": 3, "start_time": "10:00", "end_time": "14:00" },
{ "day_of_week": 4, "start_time": "09:00", "end_time": "17:00" },
{ "day_of_week": 5, "start_time": "09:00", "end_time": "12:00" }
]
}

Returns the updated availability schedule (same format as GET).

CodeStatusDescription
validation_error400Invalid time format or overlapping slots

Retrieve the public profile of a host by their username. No authentication required.

GET /v1/users/janecoach
{
"id": "01JN2X4K8M3F7QPZRVWT6YBHCE",
"display_name": "Jane Smith",
"username": "janecoach",
"bio": "Life coach and productivity consultant",
"avatar_url": "https://cdn.vidivo.app/avatars/01JN2X4K.jpg",
"is_available": true,
"rate_per_minute": "2.50",
"window_size_minutes": 10,
"follower_count": 42
}
CodeStatusDescription
not_found404Username does not exist or user is not a host

Device push tokens are managed via the notification endpoints but are also aliased under /v1/users/me/devices for convenience.

Register a push notification token for the current device.

POST /v1/users/me/devices
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Content-Type: application/json
{
"token": "fcm_device_token_string",
"platform": "ios"
}
FieldTypeRequiredDescription
tokenstringYesFCM device token
platformstringYesios, android, or web

Remove a registered push token.

DELETE /v1/users/me/devices/01JN2X4K8M3F7QPZRVWT6YBHCE
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...

Returns 204 No Content on success.