API reference
Request and response details for the core Underwriter integration.
Base URL: https://underwriter.kita.ai/api/v1. Send your API key with every request.
| Resource | Operations |
|---|---|
| Applications | Intake, create, list, retrieve, update, delete. |
| Documents | Upload files, check extraction, retrieve results, delete. |
| Credit | Retrieve the current assessment and credit signals. |
| Memo | Start generation, check progress, read sections. |
| Conversation | Read borrower messages and sync new messages. |
| Exports | Download the extraction workbook. |
See the Quickstart for a working example and the Integration guide for permissions, retries, and processing states.
Applications
Single-call application intake
Create an application with optional files. Send multipart form data with
an application JSON string and file/files parts, or JSON without files.
Keep the total request below 4.5 MB.
Reusing external_ref within your organization returns the existing
application (200, idempotent: true) without changes; attached files are skipped.
Every application endpoint identifies the application in its path by the
UUID id or the human app_id (e.g. APP-1042) from the response.
Scope: write
/intakecurl
curl -X POST "https://underwriter.kita.ai/api/v1/intake" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx" \
-F 'application={"business_name":"Example Bakery","borrower_email":"borrower@example.com","loan_type":"SBA 7(a)","loan_amount":250000,"external_ref":"LOS-44821","send_outreach":false}' \
-F "file=@./2023_form_1120s.pdf"Request fields
multipart/form-data
applicationstringrequiredJSON-encoded ApplicationInput metadata (see the JSON request schema).filefilefilesfile[]
Response shape (illustrative) · 200
{
"data": {
"id": "<id>",
"app_id": "<app_id>",
"external_ref": "<external_ref>",
"business_name": "<business_name>"
},
"idempotent": true
}Errors400 · 401 · 403 What these mean
502Application created but a document failed to store. Reconcile documents before retrying.
List applications
List applications in your org, most-recently-active first.
Scope: read
/applicationscurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Query parameters
statusstringFilter to one status value (see the Integration guide). One of: submitted, awaiting_docs, underwriting, question_raised, memo_drafted, approved, declined.limitintegerDefault 50, clamped to 1–200.offsetintegerDefault 0. Use with limit to page.
Response example · 200
{
"data": [
{
"id": "...",
"app_id": "APP-1042",
"status": "underwriting"
}
],
"pagination": {
"total": 137,
"limit": 25,
"offset": 0
}
}Errors400 · 401 · 403 What these mean
Create an application
Create an application without files. Accepts the same metadata as intake,
including external_ref for deduplication. Add files with the upload endpoint.
Scope: write
/applicationscurl
curl -X POST "https://underwriter.kita.ai/api/v1/applications" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"business_name": "Rivera Family Bakery LLC",
"borrower_email": "maria@riverabakery.com",
"loan_type": "SBA 7(a)",
"loan_amount": 250000
}'Request fields
application/json
business_namestringrequiredBorrower business / legal name.borrower_emailstringrequiredBorrower contact email.borrower_phonestringBorrower contact phone.loan_typestringrequiredLoan product name, e.g. "SBA 7(a)". Use a product configured for your organization.loan_amountnumberrequiredRequested amount in dollars; must be greater than zero.application_contextstringLoan purpose / free-text context for the file.external_refstringStable loan ID within your organization. A repeated value returns the existing application unchanged.intake_dataobjectAnswers keyed by configured loan-product question. Unknown questions are rejected; partial answers are allowed.scorecard_inputsobjectExplicit product-specific scorecard inputs. Overrides inputs derived from intake_data.send_outreachbooleanDefault false. If true, Kita emails the borrower for missing docs.
Response shape (illustrative) · 200
{
"data": {
"id": "<id>",
"app_id": "<app_id>",
"external_ref": "<external_ref>",
"business_name": "<business_name>"
},
"idempotent": true
}Errors400 · 401 · 403 What these mean
Get an application
Fetch one application by UUID or by human app_id (e.g. APP-1042).
Includes a live document_count.
Scope: read
/applications/{id}curl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response shape (illustrative) · 200
{
"data": {
"id": "<id>",
"app_id": "<app_id>",
"external_ref": "<external_ref>",
"business_name": "<business_name>"
}
}Errors401 · 403 · 404 What these mean
Update an application
Update mutable fields. All fields optional; omit to leave unchanged.
Scope: write
/applications/{id}curl
curl -X PATCH "https://underwriter.kita.ai/api/v1/applications/{id}" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"status": "approved"
}'Request fields
application/json
business_namestringNon-empty. Applies only if the app has a linked borrower.loan_typestringNon-empty.loan_amountnumberMust be > 0.application_contextstring | nullLoan purpose / context.statusstringApplication status (see the Integration guide). One of: submitted, awaiting_docs, underwriting, question_raised, memo_drafted, approved, declined.
Response shape (illustrative) · 200
{
"data": {
"id": "<id>",
"app_id": "<app_id>",
"external_ref": "<external_ref>",
"business_name": "<business_name>"
}
}Errors400 · 401 · 403 · 404 What these mean
Archive an application
Reversibly archive an application. Its child records and stored documents
are retained. deleted: true is kept for compatibility; archived: true
describes the operation. This endpoint does not permanently erase data.
Scope: write
/applications/{id}curl
curl -X DELETE "https://underwriter.kita.ai/api/v1/applications/{id}" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response example · 200
{
"data": {
"deleted": true,
"archived": true,
"archive_id": "7786293f-b0a9-4c2f-805c-f6240637077d",
"archived_at": "2026-09-21T22:43:46.311Z",
"already_archived": false
}
}Errors401 · 403 · 404 What these mean
Documents
List documents
List an application's documents. Add ?include=download_url to attach a
signed download URL (1-hour expiry) to each.
Scope: read
/applications/{id}/documentscurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/documents" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Query parameters
includestringAdddownload_urlto attach a signed download URL (1-hour expiry) to each. One of: download_url.
Response example · 200
{
"data": [
{
"id": "9f2...",
"doc_name": "2023_form_1120s.pdf",
"doc_type": "Tax Return",
"classified_type": "form_1120s",
"status": "verified",
"flag_message": null,
"source": "API upload",
"storage_path": "org/app/2023_form_1120s.pdf",
"download_url": "https://...signed...&expires=3600"
}
]
}Errors401 · 403 · 404 What these mean
Upload documents
Upload one or more files to an existing application as
multipart/form-data. Accepts a single file field or repeated
file/files fields (a whole package in one call).
A single-file upload returns one document object; multiple files return an
array under data. Poll the document(s) for progress. Keep the request
below 4.5 MB. After a partial failure, list documents before retrying;
retries can create duplicate files.
Scope: write
/applications/{id}/documentscurl
curl -X POST "https://underwriter.kita.ai/api/v1/applications/{id}/documents" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx" \
-F "file=@./941_q1.pdf"Request fields
multipart/form-data
filefilefilesfile[]
201 A single-file upload returns one document object; multiple files return an array under data.
Errors400 · 401 · 403 · 404 What these mean
413Request body exceeds the 4.5 MB upload limit.
Get a document
Fetch a single document including the full extraction result. Poll this
endpoint for progress: status transitions awaiting → processing → verified
/ low_confidence.
Scope: read
/applications/{id}/documents/{docId}curl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/documents/{docId}" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response shape (illustrative) · 200
{
"data": {
"id": "<id>",
"doc_name": "<doc_name>",
"doc_type": "<doc_type>",
"classified_type": "<classified_type>"
}
}Errors401 · 403 · 404 What these mean
Delete a document
Delete a document (row + storage file) and recompute file completeness.
Returns { "data": { "deleted": true } }.
Scope: write
/applications/{id}/documents/{docId}curl
curl -X DELETE "https://underwriter.kita.ai/api/v1/applications/{id}/documents/{docId}" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response example · 200
{
"data": {
"deleted": true
}
}Errors401 · 403 · 404 What these mean
Read a document transcript
Reconstruct existing layout text; this does not run OCR. Defaults to plain text. JSON includes per-page text, counts, and has_text. Documents without layout text return has_text: false in JSON; TXT returns a no-text message.
Scope: read
/applications/{id}/documents/{docId}/transcriptcurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/documents/{docId}/transcript" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Query parameters
formatstringOne of: txt, json.
Response JSON Schema · 200
{
"type": "string"
}Errors400 · 401 · 403 · 404 What these mean
Read all document transcripts
Read existing text for every document. JSON is the default and includes has_text per file; TXT groups text under document headers. Documents without layout text remain in the inventory.
Scope: read
/applications/{id}/transcriptscurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/transcripts" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Query parameters
formatstringOne of: json, txt.
Response JSON Schema · 200
{
"type": "string"
}Errors400 · 401 · 403 · 404 What these mean
Credit
Get the credit picture
Read the current assessment: scorecard, credit policy, financial spread, adjustments, and routing recommendation. Unavailable computed objects are null; adjustments is an array. Results update as documents process.
Scope: read
/applications/{id}/creditcurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/credit" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response example · 200
{
"data": {
"application_id": "b1e7c9a4-...",
"app_id": "APP-1042",
"spread": {
"adjusted_ebitda": 412000,
"adjusted_net_income": 188500,
"ratios": {
"dscr": 1.42,
"global_dscr": 1.31,
"debt_to_worth": 2.1,
"current_ratio": 1.6,
"ltv": 0.74
}
},
"adjustments": [
{
"line_item": "owner_comp_addback",
"label": "Owner compensation to market",
"amount": 60000,
"source": "ai"
}
],
"decision": {
"routing": "human_review",
"auto_routed": false,
"rules": [
{
"label": "Min DSCR 1.25x",
"outcome": "pass",
"actual": 1.42,
"expected": 1.25
}
]
}
}
}Errors401 · 403 · 404 What these mean
Read decision-engine inputs
Versioned evidence for a lender-owned decision engine. Inspect assessment.complete and missing_required_metrics before using the snapshot. Completeness requires configured metrics, provider operations, and a versioned calculation timestamp; it is not loan approval.
Scope: read
/applications/{id}/decision-inputcurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/decision-input" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response shape (illustrative) · 200
{
"data": {
"schema_version": "kita.underwriting_decision_input.v1",
"assessment": {
"complete": true,
"missing_required_metrics": []
}
}
}Errors400 · 401 · 403 · 404 What these mean
Diagnose the scorecard
Read product configuration, inputs, computed metrics, rendered scorecard, and diagnosis. diagnosis.blocked_at identifies the first missing or invalid layer; this read does not recalculate the assessment.
Scope: read
/applications/{id}/scorecardcurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/scorecard" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response shape (illustrative) · 200
{
"data": {
"diagnosis": {}
}
}Errors400 · 401 · 403 · 404 What these mean
Read historical precedents
Read the advisory precedent table. Disabled, not_run, no_matches, and unavailable states return 200 with an empty precedents array. Historical comparisons do not make a lending decision.
Scope: read
/applications/{id}/historical-precedentscurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/historical-precedents" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response shape (illustrative) · 200
{
"data": {
"status": "disabled",
"precedents": []
}
}Errors400 · 401 · 403 · 404 What these mean
Memo
Read the memo
Read the memo sections in order. Bodies preserve their JSON structure; citation markers and citation_map are removed recursively.
Scope: read
/applications/{id}/memocurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/memo" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Query parameters
includestringInclude the advisory precedent table when enabled. One of: historical_precedents.
Response example · 200
{
"data": {
"last_synthesis_at": "2026-06-17T18:22:09.000Z",
"sections": [
{
"section_number": 1,
"title": "Deal Summary",
"body": {
"text": "Rivera Family Bakery requests equipment financing."
},
"locked_by_lo": false,
"updated_at": "2026-06-17T18:22:09.000Z"
}
]
}
}Errors401 · 403 · 404 What these mean
Generate the credit memo
Start memo generation. Returns 202 with data.status of accepted or
already_running. Poll /applications/{id}/memo/status and check for
failure before reading the memo. Sample applications cannot generate memos.
Scope: write
/applications/{id}/memocurl
curl -X POST "https://underwriter.kita.ai/api/v1/applications/{id}/memo" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response shape (illustrative) · 202
{
"data": {
"status": "accepted",
"application_id": "<application_id>",
"poll": "<poll>"
}
}Errors401 · 403 · 404 What these mean
503Memo generation could not be started.
Poll memo freshness
Freshness + synthesis progress. Poll after POST …/memo until
synthesis_in_progress is false. Check last_run_status for failure;
is_stale indicates whether the memo needs refreshing.
Scope: read
/applications/{id}/memo/statuscurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/memo/status" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response shape (illustrative) · 200
{
"data": {
"synthesis_in_progress": true,
"is_stale": true,
"stale_reasons": [
"<stale_reasons>"
],
"new_doc_count": 42
}
}Errors401 · 403 · 404 What these mean
Conversation
Read borrower conversation
The borrower-facing thread, ordered by display_order. Pass
?after={display_order} to fetch only newer messages for incremental sync.
Scope: read
/applications/{id}/conversationcurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/conversation" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Query parameters
afterintegerPass adisplay_orderto fetch only newer messages for incremental sync.
Response shape (illustrative) · 200
{
"data": [
{
"display_order": 42
}
]
}Errors401 · 403 · 404 What these mean
Exports
Download the extraction workbook
Download the extraction workbook (a Summary sheet plus one sheet per file
area) as .xlsx. Returns 404 if no document has extraction data yet.
Scope: read
/applications/{id}/exportcurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/export" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Response JSON Schema · 200
{
"type": "string",
"format": "binary"
}Errors401 · 403 What these mean
404No document has extraction data yet.
Export the memo or financial spread
Download the current memo PDF (default) or financial-spread XLSX. This does not start synthesis. Generate and poll the memo first for populated narrative. XLSX returns 404 when no spread exists; it differs from the raw extraction workbook at /export. Historical precedents can be included in PDF only.
Scope: read
/applications/{id}/memo/exportcurl
curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/memo/export" \
-H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"Query parameters
formatstringOne of: pdf, xlsx.includestringInclude advisory historical precedents. One of: historical_precedents.
Response JSON Schema · 200
{
"type": "string",
"format": "binary"
}Errors400 · 401 · 403 · 404 What these mean


