Skip to content

Ask the docs-grounded in-app help assistant one question

POST
/support/chat
curl --request POST \
--url https://api.tovarifinancial.com/support/chat \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "message": "example", "screenContext": "accounts", "history": [ { "role": "user", "content": "example" } ], "platform": "web_desktop" }'

One non-streaming turn of the in-app help assistant, answered only from the product documentation. No transcript is stored: prior turns travel in history on every request.

X-Idempotency-Key is REQUIRED on this route: a missing, blank or over-long key is refused with 400 VALIDATION_ERROR before any work is done. It is HONORED through the shared idempotency store — retrying the same key with the same body replays the recorded 200 (a refusal included) without asking the assistant again, and reusing a key with a different body, or after an attempt that never completed, is refused 409 IDEMPOTENCY_CONFLICT; mint a new key. platform is EXCLUDED from the idempotency fingerprint (only message, screenContext and history are fingerprinted), so a retry whose declared platform changed replays the stored answer rather than conflicting.

OPERATIONAL LIMITS ARE 200s, NOT ERRORS. An entitlement refusal, the monthly per-user and daily per-household quotas, the spend cut-out and the kill switches all answer 200 with a degraded marker and a server-authored answer. This route is subscription-exempt, so it never answers 403 SUBSCRIPTION_REQUIRED. Only the HOURLY turn cap is an error: 429 HELP_CHAT_THROTTLED with details.retryAfterSeconds. A client branches on degraded before refusalReason.

Two further statuses carry codes the shared entries do not name: a database-level access refusal answers 403 DATABASE_ERROR, and a uniqueness conflict other than the idempotency claim answers 409 USER_ALREADY_EXISTS — so a 409 here is not necessarily an idempotency conflict. A 503 is retryable whether the assistant or the database was unavailable.

X-Idempotency-Key
string

Optional idempotency key for safe write retries. Every operation that declares this header reads it. Three cases, told apart per operation: (1) where the operation also documents a 409 whose codes include IDEMPOTENCY_CONFLICT, replaying this key with a different payload returns 409 IDEMPOTENCY_CONFLICT and replaying it with the same payload returns the original response; (2) where it documents no 409, a replay is reconciled optimistically against a unique key column and answers the original 200; (3) where it documents a 409 whose codes do NOT include IDEMPOTENCY_CONFLICT, a conflict on this key is impossible — a replay answers a 200, and that 409 is a resource-state conflict described by the operation’s own 409 schema.

Media typeapplication/json
object
message
required

The question. Trimmed before the 1..2000 bound is applied.

string
>= 1 characters <= 2000 characters
screenContext

The help topic of the screen the question was asked from. Absent is treated as null.

string
nullable
Allowed values: accounts dashboard transactions safeToSpend bankConnections gettingSetUp budget bills categories reports reviewCenter fileImport payees household twoFactorAuth dataAndPrivacy helpChat investments quickStart.addYourFirstAccount quickStart.connectABankWithPlaid quickStart.theBudgetInterview
history

Client-supplied prior turns, oldest first. Absent or null is treated as an empty list.

Array<object>
nullable <= 10 items
object
role
required
string
Allowed values: user assistant
content
required

Trimmed before the 1..2000 bound is applied.

string
>= 1 characters <= 2000 characters
platform

The surface the caller is rendering. Scopes answer wording only — never a permission. Absent is treated as null. Not part of the idempotency fingerprint.

string
nullable
Allowed values: web_desktop web_mobile ios android

The answer, a refusal, or a degraded (operational-limit) answer

Media typeapplication/json
object
data
required
object
answer
required

Plain text, never empty. Server-authored on degrades and on some refusals.

string
citations
required

Documentation page slugs. Non-empty exactly when refused is false.

Array<string>
<= 4 items
contextSlug
required

The docs slug of the screen the question came from, or null.

string
nullable
navigateTo
required

An in-app destination id to offer, or null. Always null on a refusal.

string
nullable
refused
required
boolean
refusalReason

Present exactly when refused is true — degraded answers included.

string
Allowed values: off_topic financial_advice undocumented
degraded

Present only when an operational limit answered instead of the assistant.

string
Allowed values: disabled quota capped org_quota entitlement
reportDraft

A problem report the assistant drafted with the user, for confirmation. Absent otherwise.

object
type
required
string
Allowed values: bug suggestion question
summary
required
string
description
required
string
gapReport

A server-authored documentation-gap report offered on an undocumented refusal. Never present alongside reportDraft.

object
type
required
string
Allowed values: bug suggestion question
summary
required
string
description
required
string
message
string
requestId
required
string
timestamp
required
string format: date-time
Example
{
"data": {
"refusalReason": "off_topic",
"degraded": "disabled",
"reportDraft": {
"type": "bug"
},
"gapReport": {
"type": "bug"
}
}
}

Validation failed — see errorCode / fieldErrors

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"
}

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"
}

Conflict. errorCode is IDEMPOTENCY_CONFLICT when an X-Idempotency-Key was replayed with a different request payload; where the operation instead detects a resource-state conflict it carries that endpoint’s own errorCode (a duplicate name, an import that is no longer committable, an account already linked to a bank connection).

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"
}

The hourly help-chat turn cap (per user or per household) was reached. Retry after details.retryAfterSeconds.

Media typeapplication/json
object
errorCode
required

The per-user or per-household hourly help-chat turn cap was reached.

string
Allowed values: HELP_CHAT_THROTTLED
message
required
string
details
required
object
retryAfterSeconds
required

Seconds until the hourly window admits another turn.

integer
requestId
required
string
timestamp
required
string format: date-time
Example
{
"errorCode": "HELP_CHAT_THROTTLED"
}

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"
}