Goals
A Goal represents a user's primary financial objective. Each user has one active goal at a time, and it directly shapes the tone and priorities of their financial plan, money moves, and AI coach responses.
Goal types:
"savings"β the user is working toward a savings target (e.g., emergency fund, down payment)"debt"β the user is focused on paying down debt (e.g., credit card, student loans)
Object referenceβ
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for this goal |
user_id | string | The Ozzie user this goal belongs to |
goal_type | "savings" | "debt" | The type of financial goal |
goal_name | string | A human-readable label for the goal (e.g., "Emergency Fund") |
target_amount | number | The dollar amount the user is trying to reach or eliminate |
starting_amount | number | The user's current balance or debt amount at goal creation |
cadence | "weekly" | "biweekly" | "twice_monthly" | "monthly" | How often the user wants to make progress contributions |
next_move_date | string (ISO 8601) | The next scheduled date for a money move contribution |
created_at | string (ISO 8601) | Timestamp when the goal was created |
GET /v1/users/{user_id}/goalsβ
Retrieves the user's currently active goal. Returns a single goal object (users have one active goal at a time).
Path parametersβ
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | The Ozzie user ID |
Requestβ
- curl
- Node.js
- Python
curl https://api.ozzieapp.com/v1/users/usr_4f8a1b2c3d/goals \
-H "Authorization: Bearer ozp_Y2xpZW50X2ExYjJjM2Q0OnNrX2xpdmVfeEs5bVAycVI3dEwu"
const token = Buffer.from(
`${process.env.OZZIE_CLIENT_ID}:${process.env.OZZIE_CLIENT_SECRET}`
).toString('base64');
const response = await fetch(
'https://api.ozzieapp.com/v1/users/usr_4f8a1b2c3d/goals',
{
headers: {
'Authorization': `Bearer ${token}`,
},
}
);
const { data } = await response.json();
console.log(data);
import base64, os, httpx
token = base64.b64encode(
f"{os.environ['OZZIE_CLIENT_ID']}:{os.environ['OZZIE_CLIENT_SECRET']}".encode()
).decode()
response = httpx.get(
"https://api.ozzieapp.com/v1/users/usr_4f8a1b2c3d/goals",
headers={"Authorization": f"Bearer {token}"},
)
print(response.json()["data"])
Responseβ
{
"object": "goal",
"data": {
"id": "goal_9c2e7a1b4d",
"user_id": "usr_4f8a1b2c3d",
"goal_type": "savings",
"goal_name": "Emergency Fund",
"target_amount": 10000.00,
"starting_amount": 1200.00,
"cadence": "biweekly",
"next_move_date": "2025-05-19T00:00:00Z",
"created_at": "2025-05-05T14:32:10Z"
}
}
Errorsβ
| Code | HTTP Status | When it occurs |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid credentials |
NOT_FOUND | 404 | The user does not exist, or they have no active goal |
POST /v1/users/{user_id}/goalsβ
Creates or updates the user's active goal. If a goal already exists, this call replaces it entirely with the new values. There is no separate PATCH endpoint β always send the full goal object.
Setting or updating a goal will trigger the AI coach to recalibrate its recommendations on the next chat or money move generation. If a plan exists, it will reflect the new goal the next time POST /plan is called.
Path parametersβ
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | string | Yes | The Ozzie user ID |
Request bodyβ
| Field | Type | Required | Description |
|---|---|---|---|
goal_type | "savings" | "debt" | Yes | The type of goal |
goal_name | string | Yes | A short label for the goal. Max 100 characters. |
target_amount | number | Yes | The target dollar amount. Must be positive. |
starting_amount | number | Yes | Current balance or current debt. Must be β₯ 0. |
cadence | "weekly" | "biweekly" | "twice_monthly" | "monthly" | Yes | Contribution frequency |
Requestβ
- curl
- Node.js
- Python
curl -X POST https://api.ozzieapp.com/v1/users/usr_4f8a1b2c3d/goals \
-H "Authorization: Bearer ozp_Y2xpZW50X2ExYjJjM2Q0OnNrX2xpdmVfeEs5bVAycVI3dEwu" \
-H "Content-Type: application/json" \
-d '{
"goal_type": "savings",
"goal_name": "Emergency Fund",
"target_amount": 10000.00,
"starting_amount": 1200.00,
"cadence": "biweekly"
}'
const token = Buffer.from(
`${process.env.OZZIE_CLIENT_ID}:${process.env.OZZIE_CLIENT_SECRET}`
).toString('base64');
const response = await fetch(
'https://api.ozzieapp.com/v1/users/usr_4f8a1b2c3d/goals',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
goal_type: 'savings',
goal_name: 'Emergency Fund',
target_amount: 10000.00,
starting_amount: 1200.00,
cadence: 'biweekly',
}),
}
);
const { data } = await response.json();
console.log(data);
import base64, os, httpx
token = base64.b64encode(
f"{os.environ['OZZIE_CLIENT_ID']}:{os.environ['OZZIE_CLIENT_SECRET']}".encode()
).decode()
response = httpx.post(
"https://api.ozzieapp.com/v1/users/usr_4f8a1b2c3d/goals",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
},
json={
"goal_type": "savings",
"goal_name": "Emergency Fund",
"target_amount": 10000.00,
"starting_amount": 1200.00,
"cadence": "biweekly",
},
)
print(response.json()["data"])
Responseβ
Returns the full created or updated goal object.
{
"object": "goal",
"data": {
"id": "goal_9c2e7a1b4d",
"user_id": "usr_4f8a1b2c3d",
"goal_type": "savings",
"goal_name": "Emergency Fund",
"target_amount": 10000.00,
"starting_amount": 1200.00,
"cadence": "biweekly",
"next_move_date": "2025-05-19T00:00:00Z",
"created_at": "2025-05-05T14:32:10Z"
}
}
Debt payoff exampleβ
curl -X POST https://api.ozzieapp.com/v1/users/usr_4f8a1b2c3d/goals \
-H "Authorization: Bearer ozp_Y2xpZW50X2ExYjJjM2Q0OnNrX2xpdmVfeEs5bVAycVI3dEwu" \
-H "Content-Type: application/json" \
-d '{
"goal_type": "debt",
"goal_name": "Pay Off Credit Card",
"target_amount": 0,
"starting_amount": 4850.00,
"cadence": "monthly"
}'
{
"object": "goal",
"data": {
"id": "goal_7d3f9b2e1a",
"user_id": "usr_4f8a1b2c3d",
"goal_type": "debt",
"goal_name": "Pay Off Credit Card",
"target_amount": 0,
"starting_amount": 4850.00,
"cadence": "monthly",
"next_move_date": "2025-06-01T00:00:00Z",
"created_at": "2025-05-05T15:00:00Z"
}
}
Errorsβ
| Code | HTTP Status | When it occurs |
|---|---|---|
UNAUTHORIZED | 401 | Missing or invalid credentials |
NOT_FOUND | 404 | The user does not exist |
VALIDATION_ERROR | 422 | Missing required fields, invalid goal_type or cadence, negative target_amount |
INVALID_JSON | 400 | The request body is not valid JSON |
For debt goals, set target_amount to 0 β that's the goal state (zero debt). Set starting_amount to the current outstanding balance.