Skip to main content

Users

The User object is the root entity in Ozzie. All other resources β€” financial intakes, plans, goals, transactions, chat messages β€” are scoped to a user. You create one user per person in your system, identified by your own external_user_id.


The User Object​

{
"object": "user",
"data": {
"id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"external_user_id": "usr_8821",
"name": "Maria Santos",
"email": "maria@example.com",
"phone": "+15551234567",
"language": "en",
"onboarding_stage": "active",
"created_at": "2025-05-05T14:30:00Z"
}
}

User Object Fields​

FieldTypeDescription
idstringOzzie-generated UUID for this user. Use this in all subsequent API paths.
external_user_idstringYour internal user ID. Unique per API client.
namestring | nullUser's display name.
emailstring | nullUser's email address.
phonestring | nullUser's phone number in E.164 format. Required for WhatsApp integration.
languagestringLanguage preference: "en", "pt", or "es".
onboarding_stagestringCurrent onboarding state (see table below).
created_atstringISO 8601 UTC timestamp of when the user was created.

onboarding_stage Values​

ValueMeaning
intake_pendingUser created, no financial intake submitted yet
plan_pendingIntake submitted, plan not yet generated
activePlan generated β€” full platform access available

POST /v1/users​

Creates a new user under your API client. Each user must have a unique external_user_id within your client account.

Request Body​

FieldTypeRequiredConstraintsDescription
external_user_idstringYesMax 100 charsYour internal user ID (e.g. database primary key or UUID)
namestringNoMax 200 charsUser's display name
emailstringNoValid email formatUser's email address
phonestringNoE.164 formatPhone number, e.g. +15551234567. Required for WhatsApp.
languagestringNo"en" | "pt" | "es"Chat and notification language. Defaults to "en".

Response​

Returns the created user object with HTTP 201 Created.

Errors​

CodeHTTPWhen
CONFLICT409A user with this external_user_id already exists under your client
VALIDATION_ERROR400A field failed validation (e.g., invalid email format, phone not in E.164)
UNAUTHORIZED401Missing or invalid credentials

Examples​

curl -X POST https://api.ozzieapp.com/v1/users \
-H "Authorization: Bearer czJjbGllbnQ6czJzZWNyZXQ=" \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "usr_8821",
"name": "Maria Santos",
"email": "maria@example.com",
"phone": "+15551234567",
"language": "en"
}'

Example Response (201 Created):

{
"object": "user",
"data": {
"id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"external_user_id": "usr_8821",
"name": "Maria Santos",
"email": "maria@example.com",
"phone": "+15551234567",
"language": "en",
"onboarding_stage": "intake_pending",
"created_at": "2025-05-05T14:30:00Z"
}
}

Error Response β€” Duplicate user (409 Conflict):

{
"error": {
"code": "CONFLICT",
"message": "A user with external_user_id 'usr_8821' already exists under your API client. Use GET /v1/users/{user_id} to retrieve them."
}
}

Error Response β€” Invalid email (400 Validation Error):

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Field 'email' must be a valid email address. Received: 'not-an-email'."
}
}
Handling CONFLICT gracefully

If you're not certain whether a user already exists, catch the CONFLICT error and immediately call GET /v1/users/external:{external_user_id} to retrieve the existing record. This is safe to do in an upsert-style flow.


GET /v1/users/{user_id}​

Retrieves a user by their Ozzie UUID or by their external_user_id.

Path Parameter​

ParameterDescription
user_idEither the Ozzie UUID (e.g. ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE) or a prefixed external ID (e.g. external:usr_8821)

Looking Up by external_user_id​

To fetch a user by your own ID instead of the Ozzie UUID, prefix the value with external::

GET /v1/users/external:usr_8821

This is equivalent to querying by external_user_id and avoids the need to store the Ozzie UUID in your database at creation time.

Response​

Returns the user object with HTTP 200 OK.

Errors​

CodeHTTPWhen
NOT_FOUND404No user exists with this ID under your client
UNAUTHORIZED401Missing or invalid credentials
FORBIDDEN403The user exists but belongs to a different API client

Examples​

# By Ozzie UUID
curl https://api.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE \
-H "Authorization: Bearer czJjbGllbnQ6czJzZWNyZXQ="

# By external_user_id
curl "https://api.ozzieapp.com/v1/users/external:usr_8821" \
-H "Authorization: Bearer czJjbGllbnQ6czJzZWNyZXQ="

Example Response (200 OK):

{
"object": "user",
"data": {
"id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"external_user_id": "usr_8821",
"name": "Maria Santos",
"email": "maria@example.com",
"phone": "+15551234567",
"language": "en",
"onboarding_stage": "active",
"created_at": "2025-05-05T14:30:00Z"
}
}

Error Response β€” Not found (404):

{
"error": {
"code": "NOT_FOUND",
"message": "No user found with id 'ozz_usr_NOTEXIST' under your API client."
}
}
Polling onboarding_stage

Use GET /v1/users/{user_id} to check a user's onboarding_stage before deciding which UI to show. If the stage is intake_pending, prompt the user for their financial details. If plan_pending, show a loading state while triggering plan generation.