{"openapi":"3.1.0","info":{"title":"POST /api/v1/credit/bank-analysis","version":"1.0.0","description":"Analyze partner bank data without importing bank records"},"servers":[{"url":"https://api.ondayzero.com","description":"Production"}],"paths":{"/api/v1/credit/bank-analysis":{"post":{"tags":["credit"],"summary":"Analyze partner bank data without importing bank records","description":"Read the configured source and return provisional cash movements.\n\n**Prerequisites:** Server-configured lender, program/merchant binding,\nand either Tie service credentials or a trusted BigQuery dataset/identity binding.\n\n**Returns:** Safe aggregates and evidence fingerprints. `unavailable`\ncarries a fixed error code. Source v1 does not attest history/freshness,\nso underwriting measures remain unmeasured. Cash inflows are not revenue.\n\n**Note:** Explicit `tie_api_transient` or `bigquery_transient` mode is required. Existing\nledger-backed assessment defaults are unchanged. This endpoint neither\nsaves an assessment nor applies approval policy or opens loans. Replay\nis not exposed. Direct BigQuery returns aggregate-only results; raw data is\nnever copied into query result tables or retained here.","operationId":"analyze_credit_bank_snapshot","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"x-business-id","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Business-Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankAnalysisRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessEnvelope_BankAnalysisResponse_"}}}},"401":{"description":"Unauthorized - Missing or expired token, an MCP OAuth token used against the REST API, or no access to this business","content":{"application/json":{"example":{"error":"unauthorized","message":"Authentication required","code":"AUTH_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions","content":{"application/json":{"example":{"error":"forbidden","message":"You don't have permission to access this resource","code":"AUTH_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Not Found - Resource does not exist","content":{"application/json":{"example":{"error":"not_found","message":"Resource not found","code":"NOT_FOUND_001","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error - Request body or parameters failed validation","content":{"application/json":{"example":{"error":"validation_error","message":"Validation failed: amount: Input should be a valid integer","errors":{"amount":"Input should be a valid integer"},"code":"GEN_002","request_id":"3f0e7c2a-9b4d-4e1a-8c6f-2d5b7a1e9c30"},"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"x-fastapi-operation-id":"analyze_credit_bank_snapshot_api_v1_credit_bank_analysis_post"}}},"components":{"schemas":{"BankAnalysisRequest":{"properties":{"program_id":{"type":"string","title":"Program Id","description":"Your lending program UUID."},"external_merchant_id":{"type":"string","maxLength":128,"minLength":1,"title":"External Merchant Id","description":"Your merchant identifier, bound server-side to its source organization or dataset."},"source_mode":{"type":"string","enum":["tie_api_transient","bigquery_transient"],"title":"Source Mode","description":"Explicit opt-in to temporary Tie API or direct BigQuery analysis."},"start_date":{"type":"string","format":"date","title":"Start Date","description":"Inclusive window start; at most 366 days."},"end_date":{"type":"string","format":"date","title":"End Date","description":"Inclusive window end, no later than today UTC."}},"additionalProperties":false,"type":"object","required":["program_id","external_merchant_id","source_mode","start_date","end_date"],"title":"BankAnalysisRequest"},"BankAnalysisResponse":{"properties":{"source_mode":{"type":"string","enum":["tie_api_transient","bigquery_transient"],"title":"Source Mode","description":"Temporary source analysis; no bank records imported.","default":"tie_api_transient"},"status":{"type":"string","enum":["analyzed","unavailable"],"title":"Status","description":"Whether retrieval and provisional analysis completed."},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Code","description":"Fixed safe failure code; never an upstream body."},"summary":{"anyOf":[{"$ref":"#/components/schemas/BankAnalysisSummary"},{"type":"null"}],"description":"Safe aggregates/evidence on success; nothing is persisted."}},"type":"object","required":["status"],"title":"BankAnalysisResponse"},"BankAnalysisSummary":{"properties":{"analysis_version":{"type":"string","title":"Analysis Version","description":"DayZero measurement algorithm version."},"source_contract_version":{"type":"string","title":"Source Contract Version","description":"Reviewed source and aggregation contract version."},"snapshot_fingerprint":{"type":"string","title":"Snapshot Fingerprint","description":"SHA-256 of the ephemeral snapshot token or scoped query boundary; not a replay token."},"content_sha256":{"type":"string","title":"Content Sha256","description":"SHA-256 of canonical source records; cannot reconstruct input."},"snapshot_as_of":{"type":"string","format":"date-time","title":"Snapshot As Of","description":"Warehouse point-in-time boundary, not upstream freshness."},"snapshot_expires_at":{"type":"string","format":"date-time","title":"Snapshot Expires At","description":"Analysis boundary expiry; this API does not expose replay."},"coverage_status":{"type":"string","enum":["unknown","attested"],"title":"Coverage Status","description":"Source history completeness is not attested in v1."},"freshness_status":{"type":"string","enum":["unknown","attested"],"title":"Freshness Status","description":"Upstream refresh freshness is not attested in v1."},"eligible_for_underwriting":{"type":"boolean","const":false,"title":"Eligible For Underwriting","description":"False: incomplete evidence cannot support lending eligibility."},"provisional":{"type":"boolean","const":true,"title":"Provisional","description":"True: cash movement totals have unverified source completeness."},"window_start":{"type":"string","format":"date","title":"Window Start","description":"Inclusive analyzed window start."},"window_end":{"type":"string","format":"date","title":"Window End","description":"Inclusive analyzed window end."},"currency":{"type":"string","title":"Currency","description":"Single ISO currency of the account scope."},"days":{"type":"integer","title":"Days","description":"Calendar days in the requested window."},"gross_inflows_cents":{"type":"integer","title":"Gross Inflows Cents","description":"Posted cash inflows including financing/transfers; not revenue."},"gross_outflows_cents":{"type":"integer","title":"Gross Outflows Cents","description":"Absolute posted cash outflows including transfers, in cents."},"net_movement_cents":{"type":"integer","title":"Net Movement Cents","description":"Inflows minus outflows in cents; not profit or operating cash flow."},"transaction_count":{"type":"integer","title":"Transaction Count","description":"Posted transactions included in cash totals."},"account_count":{"type":"integer","title":"Account Count","description":"Active cash accounts in the validated snapshot scope."},"measures":{"$ref":"#/components/schemas/BankMeasures","description":"Supported underwriting keys with explicit evidence gates."},"source_evidence":{"anyOf":[{"$ref":"#/components/schemas/BankSourceEvidence"},{"type":"null"}],"description":"Aggregate-only source capabilities, observations and authenticated provenance."}},"type":"object","required":["analysis_version","source_contract_version","snapshot_fingerprint","content_sha256","snapshot_as_of","snapshot_expires_at","coverage_status","freshness_status","eligible_for_underwriting","provisional","window_start","window_end","currency","days","gross_inflows_cents","gross_outflows_cents","net_movement_cents","transaction_count","account_count","measures"],"title":"BankAnalysisSummary"},"BankMeasure":{"properties":{"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value","description":"Measured value, or null when evidence is insufficient."},"reason_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason Code","description":"Why the measure is unavailable, or null."}},"type":"object","required":["value","reason_code"],"title":"BankMeasure"},"BankMeasures":{"properties":{"nsf_count_12m":{"$ref":"#/components/schemas/BankMeasure","description":"NSF/overdraft events over 365 days; unmeasured for source v1."},"average_daily_cash_balance":{"$ref":"#/components/schemas/BankMeasure","description":"90-day average closing cash in whole currency units; unmeasured for source v1."}},"type":"object","required":["nsf_count_12m","average_daily_cash_balance"],"title":"BankMeasures"},"BankSourceEvidence":{"properties":{"scope_hash":{"type":"string","title":"Scope Hash","description":"Hash binding the query, account scope and metadata statement."},"attestation_sha256":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attestation Sha256","description":"Hash of the authenticated metadata statement, when available."},"account_set_sha256":{"type":"string","title":"Account Set Sha256","description":"Hash of the sorted account inventory; no account identifiers."},"account_completeness":{"type":"string","enum":["attested","unknown"],"title":"Account Completeness","description":"Whether the complete account inventory was independently attested."},"covered_from":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Covered From","description":"Authoritatively covered history start for every scoped account."},"covered_through":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Covered Through","description":"Authoritatively covered history end for every scoped account."},"fresh_through":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Fresh Through","description":"Latest date covered by authoritative source freshness evidence."},"sync_succeeded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sync Succeeded At","description":"Attested upstream successful synchronization time."},"first_transaction_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"First Transaction Date","description":"First observed posted transaction date; not evidence of coverage."},"last_transaction_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Last Transaction Date","description":"Last observed posted transaction date; not evidence of freshness."},"first_balance_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"First Balance Date","description":"First observed balance date; not a daily closing guarantee."},"last_balance_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Last Balance Date","description":"Last observed balance date; not a daily closing guarantee."},"observed_nsf_count":{"type":"integer","title":"Observed Nsf Count","description":"Negative posted transactions matching NSF or overdraft description patterns."},"nsf_evidence_type":{"type":"string","const":"description_pattern","title":"Nsf Evidence Type","description":"Evidence used to identify observed NSF transactions.","default":"description_pattern"},"nsf_semantics_attested":{"type":"boolean","title":"Nsf Semantics Attested","description":"Whether the issuer attested complete NSF description semantics."},"classified_revenue_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Classified Revenue Cents","description":"Classified positive revenue cash credits; may be partial, not accrual revenue."},"excluded_transfers_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Excluded Transfers Cents","description":"Positive cash credits classified as transfers, in cents."},"excluded_financing_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Excluded Financing Cents","description":"Positive cash credits classified as financing, in cents."},"excluded_owner_contributions_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Excluded Owner Contributions Cents","description":"Positive cash credits classified as owner contributions, in cents."},"unclassified_inflow_count":{"type":"integer","title":"Unclassified Inflow Count","description":"Posted positive cash credits without an authenticated classification."},"revenue_classification_status":{"type":"string","enum":["complete_attested","partial_attested","unknown"],"title":"Revenue Classification Status","description":"Whether authenticated rules classify every positive cash credit."},"missing_reasons":{"items":{"type":"string"},"type":"array","title":"Missing Reasons","description":"Fixed reason codes for unsupported or insufficiently evidenced measures."}},"type":"object","required":["scope_hash","account_set_sha256","account_completeness","observed_nsf_count","nsf_semantics_attested","unclassified_inflow_count","revenue_classification_status","missing_reasons"],"title":"BankSourceEvidence","description":"Allowlisted aggregates and provenance; observations are not coverage."},"SuccessEnvelope_BankAnalysisResponse_":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"data":{"anyOf":[{"$ref":"#/components/schemas/BankAnalysisResponse"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"SuccessEnvelope[BankAnalysisResponse]"},"ErrorResponse":{"title":"ErrorResponse","type":"object","description":"Envelope returned by every non-2xx response. Branch on `code` (stable) rather than `message` (human-readable, may change).","required":["error","message","code"],"properties":{"error":{"type":"string","description":"Error category: `validation_error`, `unauthorized`, `forbidden`, `not_found`, `conflict`, `rate_limited`, `server_error`, or `service_unavailable`."},"message":{"type":"string","description":"Human-readable explanation, safe to show to end users."},"code":{"type":"string","description":"Stable machine-readable code in `CATEGORY_NNN` form (e.g. `NOT_FOUND_006`, `AUTH_010`, `GEN_002`)."},"request_id":{"type":"string","description":"Correlation id for support requests. Echoes the `x-request-id` request header when one was supplied."},"errors":{"type":"object","additionalProperties":{"type":"string"},"description":"Field-level validation messages keyed by field name. Present on 400/422 validation failures only."}}}},"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API Token","description":"API token authentication. Format: `Bearer dz_...`"}}},"security":[{"BearerAuth":[]}]}