Kita

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.

ResourceOperations
ApplicationsIntake, create, list, retrieve, update, delete.
DocumentsUpload files, check extraction, retrieve results, delete.
CreditRetrieve the current assessment and credit signals.
MemoStart generation, check progress, read sections.
ConversationRead borrower messages and sync new messages.
ExportsDownload 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

POST/intake

curl

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

  • applicationstringrequired
    JSON-encoded ApplicationInput metadata (see the JSON request schema).
  • filefile
  • filesfile[]

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

  • 502 Application created but a document failed to store. Reconcile documents before retrying.

List applications

List applications in your org, most-recently-active first.

Scope: read

GET/applications

curl

curl -X GET "https://underwriter.kita.ai/api/v1/applications" \
  -H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"

Query parameters

  • statusstring
    Filter to one status value (see the Integration guide). One of: submitted, awaiting_docs, underwriting, question_raised, memo_drafted, approved, declined.
  • limitinteger
    Default 50, clamped to 1–200.
  • offsetinteger
    Default 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

POST/applications

curl

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_namestringrequired
    Borrower business / legal name.
  • borrower_emailstringrequired
    Borrower contact email.
  • borrower_phonestring
    Borrower contact phone.
  • loan_typestringrequired
    Loan product name, e.g. "SBA 7(a)". Use a product configured for your organization.
  • loan_amountnumberrequired
    Requested amount in dollars; must be greater than zero.
  • application_contextstring
    Loan purpose / free-text context for the file.
  • external_refstring
    Stable loan ID within your organization. A repeated value returns the existing application unchanged.
  • intake_dataobject
    Answers keyed by configured loan-product question. Unknown questions are rejected; partial answers are allowed.
  • scorecard_inputsobject
    Explicit product-specific scorecard inputs. Overrides inputs derived from intake_data.
  • send_outreachboolean
    Default 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

GET/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

PATCH/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_namestring
    Non-empty. Applies only if the app has a linked borrower.
  • loan_typestring
    Non-empty.
  • loan_amountnumber
    Must be > 0.
  • application_contextstring | null
    Loan purpose / context.
  • statusstring
    Application 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

DELETE/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

GET/applications/{id}/documents

curl

curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/documents" \
  -H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"

Query parameters

  • includestring
    Add download_url to 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

POST/applications/{id}/documents

curl

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

  • filefile
  • filesfile[]

201 A single-file upload returns one document object; multiple files return an array under data.

Errors400 · 401 · 403 · 404 What these mean

  • 413 Request 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

GET/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

DELETE/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

GET/applications/{id}/documents/{docId}/transcript

curl

curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/documents/{docId}/transcript" \
  -H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"

Query parameters

  • formatstring
    One 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

GET/applications/{id}/transcripts

curl

curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/transcripts" \
  -H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"

Query parameters

  • formatstring
    One 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

GET/applications/{id}/credit

curl

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

GET/applications/{id}/decision-input

curl

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

GET/applications/{id}/scorecard

curl

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

GET/applications/{id}/historical-precedents

curl

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

GET/applications/{id}/memo

curl

curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/memo" \
  -H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"

Query parameters

  • includestring
    Include 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

POST/applications/{id}/memo

curl

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

  • 503 Memo 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

GET/applications/{id}/memo/status

curl

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

GET/applications/{id}/conversation

curl

curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/conversation" \
  -H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"

Query parameters

  • afterinteger
    Pass a display_order to 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

GET/applications/{id}/export

curl

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

  • 404 No 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

GET/applications/{id}/memo/export

curl

curl -X GET "https://underwriter.kita.ai/api/v1/applications/{id}/memo/export" \
  -H "Authorization: ApiKey kita_uw_xxxxxxxxxxxx"

Query parameters

  • formatstring
    One of: pdf, xlsx.
  • includestring
    Include advisory historical precedents. One of: historical_precedents.
Response JSON Schema · 200
{
  "type": "string",
  "format": "binary"
}

Errors400 · 401 · 403 · 404 What these mean