/api/v1/cases/{id}
The full underwriting report for one case.
- Scope
cases:read- Rate limit
- 200 requests / min
- Idempotency
- read-only
Authentication
Send your key as Authorization: Bearer …. It must carry the scope cases:read; a key without it receives 403 forbidden.
Path parameters
idstringrequiredRequest body
This operation takes no request body.
Response
200application/jsonSerializedCaseDetailidstringrequiredstatusstring (enum)requiredpendingapproveddeclinedreviewinvitedprocessingSerializedCaseProgressWhere the application is right now, in plain words — read this, not a
stage you stored at submission time. message is written to be shown to a
person as-is; next_step says who must act (upload_statements, wait,
retry, decide, none). Absent only if progress could not be loaded.
assessmentanyDocument integrity, evidence sufficiency and creditworthiness, kept apart: a decline for forged statements is not a finding that the borrower cannot repay. Absent only if it could not be computed.
productstringrequiredapplicantobjectrequirednamestringrequiredtypestringrequiredemailstringrequiredphonestring | nullrequirednullableeinstring | nullrequirednullableamountnumber | nullrequirednullableNull when the submission named no amount. See SerializedUnderwriteSubmission.amount.
ai_analysisobjectrequiredrisk_scorenumber | nullrequirednullableThe risk score, or null when no analysis has run. Null is never a score: a measured 0, the best possible score, is published as 0.
risk_levelstring | nullrequirednullableNull when no analysis has run — in exactly the cases risk_score is null.
confidencenumberrequiredrecommendationstringrequiredsummarystringrequiredconditionsstring[]requiredrisk_factorsSerializedCaseRiskFactor[]requiredrun_numbernumber | nullrequirednullableNull when no analysis has run. Treat it as the presence signal for the
whole ai_analysis block: risk_score and risk_level are null exactly
when it is.
creditobjectrequiredstatusstring (enum)requiredobtainednot_obtainedobtained when a credit report is on file; not_obtained otherwise.
scorenumber | nullrequirednullableThe bureau score, or null when no credit report is on file.
providerstring | nullrequirednullablereport_datestring | nullrequirednullableaccountsnumber | nullrequirednullableaccounts_closednumber | nullrequirednullabletotal_debtnumber | nullrequirednullableutilizationnumber | nullrequirednullablepayment_historynumber | nullrequirednullablederogatory_marksnumber | nullrequirednullablehard_inquiriesnumber | nullrequirednullablepublic_recordsnumber | nullrequirednullablecollectionsnumber | nullrequirednullableoldest_account_yearsnumber | nullrequirednullablebank_dataobjectrequiredconnectedbooleanrequireddeposit_breakdownany | nullrequirednullableDeposits sorted into revenue, wages, transfers, loan proceeds, refunds, cash and unclassified, with qualifying monthly revenue (dollars). Null when the statements were not classified.
providerstring | nullrequirednullablesourcestring | nullrequirednullableplaidstatementsmanualnullHow the bank evidence arrived: plaid (open banking), statements
(uploaded and read by the platform), manual, or null when there is
none. connected is true only for plaid. A partner that reads
connected: false as "no bank evidence" shows a reviewer "No bank
connected" over a case built on three months of statements — this field
is what lets them tell the two apart.
deposit_trend_pctnumber | nullrequirednullableStatement path only; null / 0 for a Plaid link. deposit_trend_pct is the
% change in monthly deposits from the first statement read to the last.
stacked_lenders counts distinct lenders with recurring debits — 2 or
more means the applicant is already servicing multiple advances.
stacked_lendersnumberrequiredperiods_analyzednumberrequiredinstitutionstring | nullrequirednullableaccount_typestring | nullrequirednullableaccount_last4string | nullrequirednullableaccountsnumberrequiredtotal_balancenumber | nullrequirednullableNULL when the platform holds no measured balance for the account — because the provider returned none, or because no bank was ever linked. NEVER estimated, and never zero-filled: a $0 balance is a measurement ("this account is empty") and absence is not.
avg_monthly_depositsnumberrequiredavg_monthly_withdrawalsnumberrequiredmonthly_net_cash_flownumberrequiredlowest_balance_30dnumber | nullrequirednullableALWAYS NULL. The platform does not compute a 30-day minimum balance and never publishes an estimate in its place.
nsf_events_90dnumberrequiredNon-sufficient-funds events in the trailing 90 days — the window the data covers.
recent_transactionsobject[]requireddatestring | nullrequirednullabledescriptionstringrequiredamountnumberrequiredtypestringrequiredcategorystringrequiredbackgroundobjectrequiredperformedbooleanrequiredidentity_verifiedbooleanrequiredssn4_matchbooleanrequiredaddress_matchbooleanrequiredofac_clearbooleanrequiredcriminal_recordsnumberrequiredcivil_judgmentsnumberrequiredbankruptciesnumberrequiredtax_liensnumberrequireddecisionobject | nullrequirednullableapplication_dataobjectrequiredcreated_atstring | nullrequirednullableupdated_atstring | nullrequirednullabledecided_atstring | nullrequirednullableErrors
The statuses this operation can return, with the error.code values behind each. Every error body is the shared envelope described under Errors in Getting started.
401unauthorized403forbidden404not_found429rate_limit_exceeded500internal_error