5-minute quickstart
This guide walks you through the core Ozzie workflow end to end: create a user, send their financial data, add a transaction, generate their plan, and open a chat β all with real request and response examples.
By the end you'll have a working integration you can build on.
Before you startβ
You need a valid client_id and client_secret. If you don't have them yet, see the Authentication page for how to get credentials and build your Bearer token.
Throughout this guide, replace the Authorization header value with your own encoded token.
Step 1 β Get your credentialsβ
Follow the Authentication guide to:
- Obtain your
client_idandclient_secretfrom commercial@ozzieapp.com or the Ozzie dashboard - Encode them:
base64("your_client_id:your_client_secret") - Store the result as your Bearer token
All examples below use the placeholder YOUR_BEARER_TOKEN. Replace it with your actual encoded token.
Store your token in an environment variable (OZZIE_TOKEN) and reference it as $OZZIE_TOKEN in curl commands so you never paste secrets into your terminal history.
Step 2 β Create a userβ
Every piece of data in Ozzie belongs to a user. The first thing you do is create one, passing your own identifier (external_user_id) so you can look them up by your database ID later.
- curl
- Node.js
- Python
curl -X POST https://api.ozzieapp.com/v1/api/v1/users \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "user_123",
"name": "Alex Johnson",
"language": "en"
}'
const response = await fetch('https://api.ozzieapp.com/v1/api/v1/users', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_BEARER_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
external_user_id: 'user_123',
name: 'Alex Johnson',
language: 'en',
}),
});
const data = await response.json();
console.log(data);
import httpx
response = httpx.post(
"https://api.ozzieapp.com/v1/api/v1/users",
headers={
"Authorization": "Bearer YOUR_BEARER_TOKEN",
"Content-Type": "application/json",
},
json={
"external_user_id": "user_123",
"name": "Alex Johnson",
"language": "en",
},
)
print(response.json())
Response:
{
"object": "user",
"data": {
"id": "ozz_usr_9f3a1b2c4d5e6f7a",
"external_user_id": "user_123",
"name": "Alex Johnson",
"language": "en",
"created_at": "2026-05-05T10:00:00Z",
"updated_at": "2026-05-05T10:00:00Z"
}
}
The id field (ozz_usr_9f3a1b2c4d5e6f7a) is Ozzie's internal user ID. You'll use this β or your external_user_id β in subsequent requests. Note it, or look it up later using external_user_id.
Step 3 β Send financial intakeβ
Financial intake is a monthly snapshot of the user's finances: their income, total spending, and primary financial goal. This is what Ozzie uses to generate a meaningful plan.
- curl
- Node.js
- Python
curl -X POST https://api.ozzieapp.com/v1/api/v1/users/user_123/financial-intake \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"monthly_income": 5000,
"monthly_expenses": 3200,
"financial_goal": "savings"
}'
const response = await fetch(
'https://api.ozzieapp.com/v1/api/v1/users/user_123/financial-intake',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_BEARER_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
monthly_income: 5000,
monthly_expenses: 3200,
financial_goal: 'savings',
}),
}
);
const data = await response.json();
console.log(data);
import httpx
response = httpx.post(
"https://api.ozzieapp.com/v1/api/v1/users/user_123/financial-intake",
headers={
"Authorization": "Bearer YOUR_BEARER_TOKEN",
"Content-Type": "application/json",
},
json={
"monthly_income": 5000,
"monthly_expenses": 3200,
"financial_goal": "savings",
},
)
print(response.json())
Response:
{
"object": "financial_intake",
"data": {
"id": "ozz_intake_c8d4e2f1a9b3c7d0",
"user_id": "ozz_usr_9f3a1b2c4d5e6f7a",
"external_user_id": "user_123",
"monthly_income": 5000,
"monthly_expenses": 3200,
"disposable_income": 1800,
"financial_goal": "savings",
"period": "2026-05",
"created_at": "2026-05-05T10:01:00Z"
}
}
Ozzie calculates disposable_income automatically (monthly_income - monthly_expenses). This feeds directly into the plan generation in Step 5.
Step 4 β Add an expense transactionβ
Transactions let you send individual spending records to Ozzie. They can be plain text descriptions, receipt images, PDFs, or spreadsheets β Ozzie parses and categorizes them automatically.
Here we'll send a simple text transaction:
- curl
- Node.js
- Python
curl -X POST https://api.ozzieapp.com/v1/api/v1/users/user_123/transactions \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"type": "text",
"content": "Spent $45 on groceries at Whole Foods"
}'
const response = await fetch(
'https://api.ozzieapp.com/v1/api/v1/users/user_123/transactions',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_BEARER_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
type: 'text',
content: 'Spent $45 on groceries at Whole Foods',
}),
}
);
const data = await response.json();
console.log(data);
import httpx
response = httpx.post(
"https://api.ozzieapp.com/v1/api/v1/users/user_123/transactions",
headers={
"Authorization": "Bearer YOUR_BEARER_TOKEN",
"Content-Type": "application/json",
},
json={
"type": "text",
"content": "Spent $45 on groceries at Whole Foods",
},
)
print(response.json())
Response:
{
"object": "transaction",
"data": {
"id": "ozz_txn_e5f6a7b8c9d0e1f2",
"user_id": "ozz_usr_9f3a1b2c4d5e6f7a",
"external_user_id": "user_123",
"type": "text",
"content": "Spent $45 on groceries at Whole Foods",
"parsed": {
"amount": 45.00,
"currency": "USD",
"merchant": "Whole Foods",
"category": "groceries",
"date": "2026-05-05"
},
"created_at": "2026-05-05T10:02:00Z"
}
}
You can send transactions as image files (e.g., a photo of a receipt), PDF statements, or CSV/Excel spreadsheets by changing the type field and providing either a file_url or a base64-encoded file_content. See the API Reference for the full schema.
Step 5 β Generate the financial planβ
Now that Alex has financial intake and at least one transaction on record, you can generate their personalized plan. This triggers Ozzie's AI to analyze their data and produce a structured plan with a summary, money moves, and a savings projection.
- curl
- Node.js
- Python
curl -X POST https://api.ozzieapp.com/v1/api/v1/users/user_123/plan \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json"
const response = await fetch(
'https://api.ozzieapp.com/v1/api/v1/users/user_123/plan',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_BEARER_TOKEN',
'Content-Type': 'application/json',
},
}
);
const data = await response.json();
console.log(data);
import httpx
response = httpx.post(
"https://api.ozzieapp.com/v1/api/v1/users/user_123/plan",
headers={
"Authorization": "Bearer YOUR_BEARER_TOKEN",
"Content-Type": "application/json",
},
)
print(response.json())
Response:
{
"object": "plan",
"data": {
"id": "ozz_plan_b1c2d3e4f5a6b7c8",
"user_id": "ozz_usr_9f3a1b2c4d5e6f7a",
"external_user_id": "user_123",
"period": "2026-05",
"summary": "Alex, you're in a solid position β you have $1,800 of disposable income each month, which is a great foundation for building savings. Your grocery spending looks reasonable. To hit a strong savings rate, I recommend targeting at least $500/month into a dedicated savings account before spending on discretionary items.",
"savings_projection": {
"monthly_target": 500,
"annual_projection": 6000,
"currency": "USD"
},
"money_moves": [
{
"id": "ozz_move_1a2b3c4d5e6f7a8b",
"priority": 1,
"title": "Open a high-yield savings account",
"description": "Move your monthly savings target ($500) to a HYSA earning 4.5%+ APY instead of letting it sit in a checking account.",
"category": "savings",
"impact": "high"
},
{
"id": "ozz_move_2b3c4d5e6f7a8b9c",
"priority": 2,
"title": "Set up an automatic transfer on payday",
"description": "Automate a $500 transfer to your savings account on the day you get paid so the money is committed before you spend it.",
"category": "automation",
"impact": "high"
},
{
"id": "ozz_move_3c4d5e6f7a8b9c0d",
"priority": 3,
"title": "Review subscriptions for hidden spending",
"description": "Based on your intake, $3,200 in monthly expenses leaves little margin. Auditing recurring subscriptions often reveals $50β$150 in quick savings.",
"category": "expenses",
"impact": "medium"
}
],
"created_at": "2026-05-05T10:03:00Z"
}
}
Step 6 β Chat with the AI coachβ
Users can ask Ozzie anything about their financial situation. The AI is fully aware of their intake, transactions, and plan β so answers are specific to their data, not generic advice.
- curl
- Node.js
- Python
curl -X POST https://api.ozzieapp.com/v1/api/v1/users/user_123/chat/messages \
-H "Authorization: Bearer YOUR_BEARER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"message": "How am I doing with my savings goal?"
}'
const response = await fetch(
'https://api.ozzieapp.com/v1/api/v1/users/user_123/chat/messages',
{
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_BEARER_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: "How am I doing with my savings goal?",
}),
}
);
const data = await response.json();
console.log(data);
import httpx
response = httpx.post(
"https://api.ozzieapp.com/v1/api/v1/users/user_123/chat/messages",
headers={
"Authorization": "Bearer YOUR_BEARER_TOKEN",
"Content-Type": "application/json",
},
json={
"message": "How am I doing with my savings goal?",
},
)
print(response.json())
Response:
{
"object": "chat_message",
"data": {
"id": "ozz_msg_d4e5f6a7b8c9d0e1",
"user_id": "ozz_usr_9f3a1b2c4d5e6f7a",
"external_user_id": "user_123",
"role": "assistant",
"message": "You're off to a good start, Alex! Your income of $5,000 and expenses of $3,200 leave you with $1,800 of disposable income each month β that's 36% of your take-home, which is above average.\n\nYour savings goal is well within reach. I've set a target of $500/month in your plan, which would get you to $6,000 saved by this time next year. The biggest thing you can do right now is make that savings automatic β transfer it the moment you get paid so it doesn't get absorbed by day-to-day spending.\n\nYour grocery transaction today ($45 at Whole Foods) looks healthy. Keep an eye on whether your total monthly spending stays under $3,200 β that's the number that keeps your plan on track.",
"plan_id": "ozz_plan_b1c2d3e4f5a6b7c8",
"created_at": "2026-05-05T10:04:00Z"
}
}
Chat responses are always grounded in the user's actual financial data. Ozzie does not give generic answers β it references their specific income, expenses, transactions, and plan in every response.
What you just builtβ
In six steps you:
- Authenticated with the Ozzie API
- Created a user (
user_123/ Alex Johnson) - Sent their monthly financial intake ($5,000 income, $3,200 expenses, savings goal)
- Logged an individual transaction (groceries, $45)
- Generated a personalized financial plan with money moves and a savings projection
- Asked the AI coach a question and got a data-grounded answer
This is the core loop of the Ozzie API. From here, you can keep sending transactions as users spend, regenerate plans monthly, and let users chat with their coach as often as they want.
Next stepsβ
- API Reference β full documentation for every endpoint, including request schemas, all response fields, and error codes
- Use Cases β deeper guides for specific integration patterns: WhatsApp bots, fintech apps, analytics dashboards, and embedded coaches
- Webhooks β learn how to receive inbound WhatsApp messages via the
/webhooks/evolutionendpoint and route them to the chat API - Postman Collection β import our pre-built collection to explore every endpoint interactively without writing any code