Log in
Cash Flow AnalysisFlagshipIncome VerificationFlagshipEmployment VerificationIdentity VerificationEarly accessInsurance VerificationComing soon
Industries
Auto & PowersportsDealerships & Point of SalePersonal Loan LendersSMB LendingBanksCredit Unions
Use cases
Improve portfolio performanceKoraScorePrevent fraudApprove more good borrowersAutomate stipsCustomized Project
White papers
Beyond the Credit ScoreGrow Origination, Cut Losses
More
About usBlogAPISupportCareers
Log in

Cash Flow Analysis

Affordability, stability and risk read from the whole account.

See what you get

Income Verification

Every income stream verified, including gig and cash work.

See what it verifies
More verification, one portal
Employment VerificationCurrent employer and pay, confirmed from deposits.Identity VerificationEarly accessID and live selfie, checked against the application.Insurance VerificationComing soonActive coverage and policy details, confirmed.
Industries
Auto & PowersportsBuilt for every lending model, from indirect to direct loans.Dealerships & Point of SaleFrom stip to funded, across every rooftop.Personal Loan LendersUnderwrite ability-to-pay without collateral.SMB LendingReal business cash flow, not a prepared P&L.BanksCash-flow depth on the file your committee already reviews.Credit UnionsSay yes to more members without loosening policy.
Use cases
Improve portfolio performanceCatch the account stress that shows up before a payment is missed.KoraScorePredict charge-off and 60+ day delinquency on the same file.Prevent fraudKeep fabricated income and documents off your books.Approve more good borrowersSay yes to thin- and no-file applicants a bureau score would reject.Automate stipsIncome, employment, identity and insurance from one applicant upload.Customized ProjectModernize what you run today, or stand up something new with our team.
About usWho Kora is, and where the platform came from.BlogPlaybooks and research on cash-flow underwriting.APIReference docs for the verification API.SupportEvery answer in one place, and a ticket form.CareersOpen roles on the team building KoraConnect.
White papers
Beyond the Credit ScoreHow a $1B+ lender improved performance, measured against outcomes.Grow Origination, Cut LossesDelinquency down across every credit tier, in matched cohorts.
API

API documentation

Sign in for the full API reference
This is the public introduction to the Case API: how it works, end to end, without the field-level schemas. The full reference covers every request, response and analysis attribute, and is linked from the KoraConnect dashboard, next to your API keys. No account yet? Book a demo and we will provision a sandbox with the reference included.
Getting started
  • Overview
  • How a case flows
  • Quickstart
Reference
  • Authentication
  • API versioning
  • Webhooks
  • Errors
  • Environments
  • Dealer API
Access
  • Full reference

Overview

The Case API is the primary integration surface for lending clients running underwriting workflows on KoraConnect. It models each borrower interaction as a case that moves through a configurable workflow of stages, with modules producing the underlying financial signals. Two modules are available today, with more on the way:

ModuleWhat it produces
cash_flow_analysisStructured income, monthly inflow/outflow, and a top-level risk insight from bank transactions. Sourced via automatic bank connection in the hosted flow, or bank statements uploaded directly.
paystubEmployment and income verification from uploaded paystubs, with built-in document fraud detection and identity matching.

Every account has a default workflow applied automatically on case creation: you don't pass a workflow_id unless your account has multiple workflows and you need to pick one per case. Which modules run, in which stages, is configured server-side during onboarding.

Base URLs

EnvironmentBase URLIP allowlist
Sandboxapi.sandbox.koramoney.comNot required, open from any IP
Productionapi.koramoney.comRequired, egress IPs whitelisted during onboarding

How a case flows end to end

Three actors are involved in every case: the borrower (your customer), KoraConnect, and your integration. The production-recommended pattern is borrower-driven:

  1. Your system calls POST /api/cases with borrower info and your own reference_id. The response carries a case_id and a hosted-flow link (url / short_url).
  2. You forward the link to the borrower by SMS, email or in-app, or call POST .../send-sms and we text it for you. The link's token expires 30 days after issue.
  3. The borrower opens the link and connects their bank directly: live transaction data, straight from the institution. Statement upload is available as a fallback; either way, data goes directly to KoraConnect and never passes through your servers.
  4. Analysis runs, typically seconds to about a minute, and the MODULE_COMPLETED webhook delivers the result_id.
  5. You fetch the result with GET .../modules/{module_type}/analysis/{result_id} and make your underwriting decision.
You don't poll for completion in production: the webhook tells you when the result is ready. Polling the module status endpoint is fine for sandbox and ad-hoc inspection.

Multi-stage workflows repeat the middle of that loop per stage, with STAGE_ADVANCED events in between. You can also drive the flow without the hosted experience by uploading documents via the API and triggering the module run yourself. The quickstart below shows it as path 2b, since it's easier to test without a real borrower.

Quickstart

End to end against sandbox in 5 to 10 minutes. You'll need a sandbox API key from the sandbox dashboard and any HTTP client that can send Bearer auth and multipart uploads.

1. Create a case

Send the borrower's identifying information and your own reference_id so webhook events correlate back to your system.

request
curl -X POST https://api.sandbox.koramoney.com/api/cases \
  -H "Authorization: Bearer $KORA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "first_name": "Jane",
    "last_name": "Doe",
    "phone_number": "+15551234567",
    "reference_id": "loan_app_42",
    "module_data": {
      "cash_flow_analysis": { "products": ["DOC_FRAUD"] }
    }
  }'
response
{
  "case_id": "00000000-0000-0000-0000-000000000001",
  "url": "https://connect.koramoney.com/verify?token=xxx",
  "short_url": "https://koramoney.com/v/xxxxxxxxxxxxxxxx"
}

Save case_id and short_url: the borrower link is only returned on creation.

2a. The borrower connects their bank

The production path. The borrower opens the link from step 1 and authenticates with their institution inside the hosted flow. Transaction data flows in live and the analysis runs on its own: no statements to collect, no files passing through your servers, nothing to trigger yourself. Your next touch is the webhook in step 3.

2b. Or upload statements you already collected and run the analysis

The quickstart demo path, no borrower needed: upload the statement PDFs via the API, then trigger the run yourself.

upload request
curl -X POST ".../api/cases/$CASE_ID/documents" \
  -H "Authorization: Bearer $KORA_API_KEY" \
  -F "files=@./statement.pdf" \
  -F "module_type=cash_flow_analysis" \
  -F "document_category=bank_statement"
run request
curl -X POST ".../api/cases/$CASE_ID/modules/cash_flow_analysis/run" \
  -H "Authorization: Bearer $KORA_API_KEY"

# → { "execution_id": "…", "status": "ANALYZING", "message": "Analysis started" }

3. Wait for the webhook

Watch for MODULE_COMPLETED with module_type: "CASH_FLOW_ANALYSIS". The payload carries the result_id for the final fetch.

webhook payload
{
  "webhook_type": "MODULE",
  "event": "MODULE_COMPLETED",
  "case_id": "00000000-0000-0000-0000-000000000001",
  "module_type": "CASH_FLOW_ANALYSIS",
  "instance_id": "00000000-0000-0000-0000-000000000002",
  "reference_id": "loan_app_42",
  "environment": "production"
}

4. Fetch the result

request
curl ".../api/cases/$CASE_ID/modules/cash_flow_analysis/analysis/$RESULT_ID" \
  -H "Authorization: Bearer $KORA_API_KEY"
response
{
  "module_type": "cash_flow_analysis",
  "instance_id": "00000000-0000-0000-0000-000000000002",
  "result_id": "00000000-0000-0000-0000-000000000003",
  "analyzed_at": "2026-04-27T18:00:30.123Z",
  "data": { /* full analysis payload, documented in the full reference */ }
}

The data field contains the structured analysis: recurring income, monthly inflow/outflow, risk insights, and any flags that triggered. Its exact shape is pinned by your Kora-Api-Version and documented field by field in the full reference.

Authentication

Every request carries a Bearer API key. Requests without a valid key return 401 Unauthorized; a valid key without access to the resource returns 403 Forbidden.

Authorization: Bearer $KORA_API_KEY

Keys live in the KoraConnect dashboard, under your integration settings. Sandbox and production are completely separate accounts with different dashboards, different keys and different data, and the keys are visually identical, so label your environment variables clearly. Each key is bound to a client type: LENDER keys call the Case API, DEALER keys call the Dealer API, never both.

Key rotation runs the new key alongside the old with a cutover window (typically 7 days). Suspected compromise gets immediate revocation. Contact support.

API versioning

Header-based date versioning. Pin your integration to a dated version and that version's request and response shapes keep working, even after breaking changes ship for new clients.

Kora-Api-Version: 2025-09-30
VersionStatus
2025-09-30Current, recommended for new integrations
2025-07-31Supported
2025-01-31Supported, initial stable release

Omitting the header uses your account's pinned default; best practice is to always send it explicitly. Versions bump only for backward-incompatible changes (renamed or removed fields, type changes, new required fields). New endpoints, optional fields and additive response fields don't bump the version. Deprecations get at least 6 months of notice; no version has been sunset yet.

Webhooks

Webhooks are the production pattern for knowing when work finishes: push, not poll. Configure your endpoint and read your signing secret in the dashboard.

FamilyEvents
CASECASE_CREATED, STAGE_ADVANCED, CASE_CANCELLED
MODULEMODULE_COMPLETED, MODULE_INSUFFICIENT, MODULE_ERROR, MODULE_DOCUMENT_UPLOADED, MODULE_CONNECTED

Signature verification

Every delivery carries an X-Signature header: sha256=…, an HMAC-SHA256 over the raw request body keyed with your per-environment signing secret. Compute over the exact bytes received (don't parse-then-restringify) and compare in constant time:

node.js
import crypto from "crypto";

function verifyWebhookSignature(rawBody, header, secret) {
  const expected =
    "sha256=" +
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex");

  if (header.length !== expected.length) return false;
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}

Retries, ordering, duplicates

Success is any 2xx in under 10 seconds. Failures retry twice at 10-minute intervals, then the event is dropped, so consume webhooks into a durable queue on your side promptly. Events are not strictly ordered and can occasionally deliver twice, so handlers should be idempotent and read canonical state via GET /api/cases/{case_id} when in doubt.

Errors

Validation failures (400) name the exact field and problem:

400 validation
{
  "message": "Validation failed",
  "errors": [
    { "field": "phone_number", "error": "Phone number must be in E.164 format" },
    { "field": "address.postal_code", "error": "Postal code must be exactly 5 digits" }
  ]
}

Domain errors carry a human-readable message only. There is no published error-code enum, so branch on HTTP status, not message text. Validation errors are deterministic; don't retry them.

StatusExampleCause
404"Case not found"case_id doesn’t exist on this account
404"Module not configured for this case"Workflow doesn’t include the module, response lists available_modules
409"Module is already running"Run called during a transitional state

Environments

SandboxProduction
Dashboarddashboard.sandbox.koramoney.comdashboard.koramoney.com
IP allowlistNo, open from any IPYes, required
CostFree, provisioned on requestContracted
CredentialsSeparate account, separate keysSeparate account, separate keys

Finish your integration in sandbox, then onboard your production egress IPs as the last step before live traffic.

Dealer API

Dealer integrations use a parallel surface under /api/dealer/* with the same conventions: cases, module runs, verification results, and an income verification report PDF (GET /api/dealer/cases/{case_id}/report/pdf) for the deal jacket. Dealer keys and lender keys are separate, so if you need both surfaces you'll receive separate credentials.

The full reference

The complete reference documents every request, response and analysis data attribute, including how the result schema differs across Kora-Api-Version releases. We keep that level of detail off the open web deliberately.

You are…How to get in
A customer or sandbox userSign in to the dashboard, where the full reference is linked next to your API keys and webhook settings.
New to KoraConnectBook a demo and we'll provision a free sandbox with dashboard access, API keys and the full reference included.

Questions? Reach your account manager or support@koramoney.com.

Products

Cash Flow AnalysisIncome VerificationEmployment VerificationIdentity VerificationInsurance Verification

Industries

Auto & PowersportsDealerships & Point of SalePersonal Loan LendersSMB LendingBanksCredit Unions

Use cases

Improve portfolio performanceKoraScorePrevent fraudApprove more good borrowersAutomate stipsCustomized Project

Resources

About usBlogAPI docsSupportCareers

Cash-flow underwriting and income verification for banks, credit unions, non-bank lenders and dealers.

Approved vendor of:
Canadian Lenders Association
© 2026 Kora Financial Inc. · US & CanadaNMLS No. 1635300
Terms of UsePrivacy Policy