ozzie-openapi — Intelligence Layer
Base URL: https://api.ozzieapp.com/v1
ozzie-openapi is the stateless intelligence layer. It receives full context as request input and returns plans, envelope allocations, chat responses, quiz scores, and money move recommendations.
Authentication
Authorization: Bearer base64(client_id:client_secret)
Users
POST /v1/users
Create a user identity in the intelligence layer.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
external_user_id | string | Yes | Your internal user ID |
name | string | No | Display name |
email | string | No | Email address |
language | string | No | "en" | "pt" | "es" — defaults to "en" |
Example:
curl -X POST https://api.ozzieapp.com/v1/users \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "usr_8821",
"name": "Maria Santos",
"language": "en"
}'
Response (201):
{
"object": "user",
"data": {
"id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"external_user_id": "usr_8821",
"name": "Maria Santos",
"language": "en",
"created_at": "2026-05-15T10:00:00Z"
}
}
GET /v1/users/:user_id
Retrieve a user by Ozzie UUID or by external:{external_user_id}.
curl https://api.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE \
-H "Authorization: Bearer YOUR_TOKEN"
Financial Intake
POST /v1/users/:user_id/financial-intake
Submit a financial intake snapshot.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
monthly_income | number | Yes | Gross monthly income |
monthly_expenses | number | Yes | Total monthly outgoings |
financial_goal | string | Yes | "savings" | "debt" |
next_pay_date | string | No | ISO date YYYY-MM-DD |
Example:
curl -X POST https://api.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE/financial-intake \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"monthly_income": 5000,
"monthly_expenses": 3200,
"financial_goal": "savings"
}'
Response (201):
{
"object": "financial_intake",
"data": {
"id": "ozz_intake_01HX9M3F",
"user_id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"monthly_income": 5000,
"monthly_expenses": 3200,
"monthly_surplus": 1800,
"financial_goal": "savings",
"created_at": "2026-05-15T10:01:00Z"
}
}
GET /v1/users/:user_id/financial-intake
Returns the most recently created intake snapshot.
Plan Generation
POST /v1/users/:user_id/plan/generate
Generate a personalized financial plan. Accepts personality_type in the request body.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
personality_type | string | No | HOTSHOT | STOCKPILER | GIVER | INDEPENDENT |
plan_speed | string | No | conservative | moderate | aggressive — adjusts goal allocation (±5 pp). Defaults to moderate. |
Example:
curl -X POST https://api.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE/plan/generate \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "personality_type": "STOCKPILER", "plan_speed": "aggressive" }'
Response:
{
"object": "plan",
"data": {
"id": "ozz_plan_01HX9N7C",
"user_id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"personality_type": "STOCKPILER",
"plan_tier": "30/70",
"envelopes": {
"bills": { "allocated_pct": 40.0, "allocated_amount": 2000.00 },
"future": { "allocated_pct": 30.0, "allocated_amount": 1500.00 },
"daily_living": { "allocated_pct": 10.5, "allocated_amount": 525.00 },
"health_wellness": { "allocated_pct": 6.0, "allocated_amount": 300.00 },
"lifestyle": { "allocated_pct": 6.0, "allocated_amount": 300.00 },
"people": { "allocated_pct": 7.5, "allocated_amount": 375.00 }
},
"action_items": [
"Automate a $1,500 transfer to savings on payday.",
"Keep lifestyle spend under $300 this month.",
"Your STOCKPILER profile means your emergency fund should reach 6 months before investing."
],
"created_at": "2026-05-15T10:03:00Z"
}
}
Errors:
| Code | HTTP | When |
|---|---|---|
INTAKE_REQUIRED | 422 | No intake exists for this user |
VALIDATION_ERROR | 400 | Unknown personality_type value |
GET /v1/users/:user_id/plan
Returns the current plan for the user.
Financial Profile (Envelope Allocations)
GET /v1/users/:user_id/financial-profile
Returns personality-weighted envelope allocations. Accepts personality_type as a query parameter. Returns allocation percentages only.
Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
personality_type | string | No | HOTSHOT | STOCKPILER | GIVER | INDEPENDENT |
Example:
curl "https://api.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE/financial-profile?personality_type=GIVER" \
-H "Authorization: Bearer YOUR_TOKEN"
Response:
{
"object": "financial_profile",
"data": {
"user_id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"personality_type": "GIVER",
"envelopes": {
"bills": { "allocated_pct": 30.0 },
"future": { "allocated_pct": 16.0 },
"daily_living": { "allocated_pct": 16.2 },
"health_wellness": { "allocated_pct": 8.1 },
"lifestyle": { "allocated_pct": 10.8 },
"people": { "allocated_pct": 18.9 }
}
}
}
Chat (Stateless Inference)
POST /v1/users/:user_id/chat/completion
Stateless AI chat inference. The caller provides full context (conversation history, personality type, any relevant financial data). Returns a reply without storing anything.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | User message |
history | array | No | Prior conversation turns [{ role, content }] |
personality_type | string | No | User's personality type — shapes tone |
language | string | No | "en" | "pt" | "es" |
context | string | No | Conversation context hint, e.g. "financial_planning" |
user_context | object | No | Rich user snapshot including name, plan_tier, plan_speed, goal_progress, next_move, completed_moves_count, total_saved_cents, last_confirmation_note, entry_point, spending_alert_envelope, spending_alert_ratio, and rag_context. See Chat docs for full field reference. |
entry_point values: weekly_expense | spending_alert | monthly_review | move_reminder | unprompted
Example:
curl -X POST https://api.ozzieapp.com/v1/users/ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE/chat/completion \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "oi",
"user_context": {
"name": "Ramon",
"language": "pt",
"personality_type": "STOCKPILER",
"completed_moves_count": 8,
"total_saved_cents": 125000,
"next_move": { "date": "2026-05-20", "amount_cents": 20000 },
"entry_point": "unprompted"
}
}'
Response:
{
"object": "chat_completion",
"data": {
"role": "assistant",
"content": "Oi Ramon! Você completou 8 passos e já guardou $1,250. Seu próximo passo é dia 2026-05-20. Sobre o que você quer falar hoje?",
"entry_point_opener": "Oi Ramon! Você completou 8 passos e já guardou $1,250. Seu próximo passo é dia 2026-05-20. Sobre o que você quer falar hoje?",
"context": "general",
"created_at": "2026-05-15T10:10:00Z"
}
}
entry_point_opener is a pre-built opening message the app can display before the user sends their first message. It is null for move_reminder (channel renders the passo card) and when no entry_point was provided.
This endpoint returns the AI reply without storing it. Your application is responsible for persisting the conversation history and passing it in history on subsequent calls.
Transactions (Stateless Parsing)
POST /v1/transactions/parse
Stateless AI transaction parsing. Accepts text, image, PDF, or spreadsheet content and returns parsed transaction records. Does not store anything.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "text" | "image" | "pdf" | "spreadsheet" |
content | string | Yes | The raw content to parse |
mime_type | string | Cond. | Required when type is "image" |
language | string | No | Language hint for parsing |
Example (text):
curl -X POST https://api.ozzieapp.com/v1/transactions/parse \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "text",
"content": "Coffee $5.50 and lunch $14.80 at the deli",
"language": "en"
}'
Response:
{
"object": "transaction_list",
"data": {
"transactions": [
{
"amount_cents": 550,
"currency": "USD",
"category": "food",
"envelope": "daily_living",
"description": "Coffee",
"transaction_date": "2026-05-15",
"ai_confidence": 0.98
},
{
"amount_cents": 1480,
"currency": "USD",
"category": "food",
"envelope": "daily_living",
"description": "Lunch at the deli",
"transaction_date": "2026-05-15",
"ai_confidence": 0.97
}
]
}
}
Personality
GET /v1/personality/questions
Returns the quiz question catalog.
curl https://api.ozzieapp.com/v1/personality/questions \
-H "Authorization: Bearer YOUR_TOKEN"
Response:
{
"object": "list",
"data": {
"questions": [
{
"id": "q_001",
"text": "When you get extra money, what do you do first?",
"options": [
{ "id": "q_001_a", "text": "Invest it right away" },
{ "id": "q_001_b", "text": "Move it to savings" },
{ "id": "q_001_c", "text": "Treat someone I love" },
{ "id": "q_001_d", "text": "Decide for myself" }
]
}
],
"total": 10
}
}
POST /v1/personality/score
Score a set of quiz answers and return the personality type. Does not store the result — your application is responsible for storing it.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
answers | array | Yes | Array of { question_id, option_id } objects |
Example:
curl -X POST https://api.ozzieapp.com/v1/personality/score \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"answers": [
{ "question_id": "q_001", "option_id": "q_001_c" },
{ "question_id": "q_002", "option_id": "q_002_c" }
]
}'
Response:
{
"object": "personality_score",
"data": {
"personality_type": "GIVER",
"score_breakdown": {
"HOTSHOT": 0,
"STOCKPILER": 1,
"GIVER": 8,
"INDEPENDENT": 1
}
}
}
Money Moves (Generation)
POST /v1/money-moves/generate
Generate a set of weekly money move recommendations given the user's context. Accepts personality_type and plan_tier as inputs. Does not store results.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | Ozzie user ID |
personality_type | string | Yes | HOTSHOT | STOCKPILER | GIVER | INDEPENDENT |
plan_tier | string | Yes | Plan tier string, e.g. "20/80" or "30/70" |
week_start | string | No | ISO date — defaults to current week |
Example:
curl -X POST https://api.ozzieapp.com/v1/money-moves/generate \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"user_id": "ozz_usr_01HX9KZMR4P5JQNBVT7YCW3DE",
"personality_type": "GIVER",
"plan_tier": "20/80",
"week_start": "2026-05-13"
}'
Response:
{
"object": "money_move_set",
"data": {
"week_start": "2026-05-13",
"week_end": "2026-05-19",
"personality_type": "GIVER",
"tasks": [
{
"type": "do",
"title": "Transfer $250 to your savings account this week",
"amount_cents": 25000
},
{
"type": "learn",
"title": "Read: How to give generously without undermining your own financial security"
},
{
"type": "mind",
"title": "Write down one person you want to help financially this year — and what boundary keeps you both healthy"
}
]
}
}