Skip to content

The household planning window and cushion, with all three previews

GET
/settings/safe-to-spend
curl --request GET \
--url https://api.tovarifinancial.com/settings/safe-to-spend \
--header 'Authorization: Bearer <token>'

NO HOUSEHOLD ID ANYWHERE — the org comes from the bearer token and nothing else. AN ABSENT ROW IS NOT AN ERROR: a household that has never saved reads the defaults (window 2, automatic) with a 200 and settings.isExplicit === false; there is no 404 on this endpoint. The response carries ALL THREE window projections, so the settings screen previews a change by selecting over projections rather than by a second request — which is also why a client must never recompute a projected figure itself.

The settings, the product limits, and the three projections

Media typeapplication/json
object
data
required
object
settings
required
object
paycheckWindow
required

Planning window counted in scheduled paychecks.

integer
Allowed values: 1 2 3
cushionMode
required
string
Allowed values: automatic fixed
cushionFixedCents
required

Integer minor units. Persisted independently of cushionMode; null when never set.

integer format: int64
nullable
updatedAt
required

The OPAQUE concurrency token — round-trip it verbatim on the next PUT. Never parse or format it; null when no row exists yet.

string
nullable
updatedByUserId
required
string
nullable
updatedByName
required
string
nullable
isExplicit
required

FALSE when no row exists: these are the defaults and the household never chose them. An absent row is a 200, never a 404.

boolean
limits
required
object
cushionMinCents
required

Integer minor units (cents)

integer format: int64
cushionMaxCents
required

Integer minor units (cents)

integer format: int64
cushionMaxMessage
required

Server-authored ceiling copy. Render THIS string — never a client-side number.

string
context
required
object
hasScheduledPaycheck
required
boolean
hasSpendingHistory
required
boolean
todayIso
required

Calendar date, ‘YYYY-MM-DD’

string
projections
required

Exactly three, ordered paycheckWindow 1,2,3 — the settings screen previews a change by selecting over these rather than by a second request.

Array<object>
>= 3 items <= 3 items
object
paycheckWindow
required

Planning window counted in scheduled paychecks.

integer
Allowed values: 1 2 3
projectedSafeToSpendCents
required

The figure the dashboard will render after saving THIS window, to the cent.

integer format: int64
windowEndDate
required

Always resolved — end-of-month when windowIsFallback.

string
windowIsFallback
required
boolean
payPeriodsCounted
required

Equals paycheckWindow unless windowIsFallback, when it is 0.

integer
cycleDays
required
integer
automaticCushionCents
required

Integer minor units (cents)

integer format: int64
totalBalanceCents
required

Integer minor units (cents)

integer format: int64
totalObligationsCents
required

Integer minor units (cents)

integer format: int64
obligationCount
required
integer
computedAt
required
string format: date-time
message
string
requestId
required
string
timestamp
required
string format: date-time
Example
{
"data": {
"settings": {
"paycheckWindow": 1,
"cushionMode": "automatic"
},
"projections": [
{
"paycheckWindow": 1
}
]
}
}

Missing, invalid, or expired bearer token

Media typeapplication/json
object
errorCode
required

Machine-readable error code (AUTH_ERROR_CODES).

string
Allowed values: INVALID_EMAIL_FORMAT USER_ALREADY_EXISTS INVALID_INVITE_CODE WRONG_PASSWORD USER_NOT_FOUND AUTHENTICATION_FAILED EXPIRED_CODE INVALID_CODE INVALID_PASSWORD VALIDATION_ERROR SIGNUP_FAILED DATABASE_ERROR SERVICE_UNAVAILABLE PLAID_ERROR IDEMPOTENCY_CONFLICT ACCOUNT_ALREADY_LINKED NOT_FOUND
message
required
string
fieldErrors

Optional field-level validation errors, keyed by field name.

object
key
additional properties
Array<string>
requestId
required
string
timestamp
required
string format: date-time
Example
{
"errorCode": "INVALID_EMAIL_FORMAT"
}

Authenticated, but the tenant gate refuses the request until the caller resolves a precondition. errorCode is one of EMAIL_NOT_VERIFIED, POLICY_ACCEPTANCE_REQUIRED, or SUBSCRIPTION_REQUIRED, evaluated in exactly that order (contract term CCR-1: email verification first, then policy acceptance, then subscription — so a subscriber who has merely not re-accepted the current policies always sees POLICY_ACCEPTANCE_REQUIRED). A POLICY_ACCEPTANCE_REQUIRED body additionally carries details.outstanding (the policy versions still to accept) and details.firstAcceptance. The SUBSCRIPTION_REQUIRED arm is INERT unless the server-side BILLING_ENABLED flag is exactly the string true; while it is off, only the first two codes are reachable. Not retryable as sent — resolve the named condition, then resend.

Media typeapplication/json
object
errorCode
required

Which precondition refused the request. Evaluated in this order (CCR-1); SUBSCRIPTION_REQUIRED is unreachable while BILLING_ENABLED is not exactly true.

string
Allowed values: EMAIL_NOT_VERIFIED POLICY_ACCEPTANCE_REQUIRED SUBSCRIPTION_REQUIRED
message
required
string
details
object
outstanding
required

Active policy versions the user has not yet accepted.

Array<object>
object
id
required
string format: uuid
policyType
required
string
version
required
integer
title
required
string
firstAcceptance
required

True when the user has accepted no policy before — the client renders the new-signup screen rather than the re-acceptance one.

boolean
requestId
required
string
timestamp
required
string format: date-time
Example
{
"errorCode": "EMAIL_NOT_VERIFIED"
}

Internal error (no internal detail leaked)

Media typeapplication/json
object
errorCode
required

Machine-readable error code (AUTH_ERROR_CODES).

string
Allowed values: INVALID_EMAIL_FORMAT USER_ALREADY_EXISTS INVALID_INVITE_CODE WRONG_PASSWORD USER_NOT_FOUND AUTHENTICATION_FAILED EXPIRED_CODE INVALID_CODE INVALID_PASSWORD VALIDATION_ERROR SIGNUP_FAILED DATABASE_ERROR SERVICE_UNAVAILABLE PLAID_ERROR IDEMPOTENCY_CONFLICT ACCOUNT_ALREADY_LINKED NOT_FOUND
message
required
string
fieldErrors

Optional field-level validation errors, keyed by field name.

object
key
additional properties
Array<string>
requestId
required
string
timestamp
required
string format: date-time
Example
{
"errorCode": "INVALID_EMAIL_FORMAT"
}

Service temporarily unavailable — errorCode is SERVICE_UNAVAILABLE. A TRANSIENT, RETRYABLE condition rather than a defect in the request: a query that exceeded its time budget, a lost or refused database connection, a saturated connection pool, or an outage at an upstream provider the request depends on (the authentication provider, or the bank data provider on a bank-connection operation). The identical request may succeed on retry — back off briefly and, on a write, resend the same X-Idempotency-Key where the operation accepts one.

Media typeapplication/json
object
errorCode
required

Machine-readable error code (AUTH_ERROR_CODES).

string
Allowed values: INVALID_EMAIL_FORMAT USER_ALREADY_EXISTS INVALID_INVITE_CODE WRONG_PASSWORD USER_NOT_FOUND AUTHENTICATION_FAILED EXPIRED_CODE INVALID_CODE INVALID_PASSWORD VALIDATION_ERROR SIGNUP_FAILED DATABASE_ERROR SERVICE_UNAVAILABLE PLAID_ERROR IDEMPOTENCY_CONFLICT ACCOUNT_ALREADY_LINKED NOT_FOUND
message
required
string
fieldErrors

Optional field-level validation errors, keyed by field name.

object
key
additional properties
Array<string>
requestId
required
string
timestamp
required
string format: date-time
Example
{
"errorCode": "INVALID_EMAIL_FORMAT"
}