SDK reference
In-app iOS and Android hosts, web embedding, server endpoints, and troubleshooting.
Web SDK
Load the script from sdk_url, then call KitaRisk.create(options).open().
For CSP, allow your Kita host in script-src, style-src, and frame-src.
| Option | Type | Required | Description |
|---|---|---|---|
sessionId | string | yes | session_id from create session. |
clientToken | string | yes | client_token from the same response. Expires after 30 minutes. |
container | element or selector | no | Render inline inside this element. Omit for a modal dialog. |
connectUrl | string | no | connect_url from the session response. Needed only when the script is served from a different host than the flow. |
onSubmitted | function | no | ({ sessionId, status: 'accepted' }). The borrower sent their files. |
onExit | function | no | ({ sessionId }). Closed before finishing; uploads are kept until the session expires. |
onError | function | no | ({ code, sessionId }). See errors; most are recoverable in the flow. |
onEvent | function | no | ({ name, sessionId }): consent_recorded, documents_added, documents_submitted. |
Methods: open(), back(), exit(), and destroy() (call on unmount). An inline
container needs at least 360 × 640 CSS pixels. To resume, create a new handle with
the same session ID and a new client token. Verify outcomes from your server, not
browser callbacks.
Server API
Send X-API-Key with your Risk Score key to the same base URL as the Scoring API:
https://riskscore.kita.ai for kita_prod_ keys, https://sandbox-api.kita.ai for
kita_sbx_ keys. Your organization path (/<org>/v1/risk/...) works too. Manage
keys on the dashboard's API keys page, and allowed
origins and your logo on its SDK page, which also
lists recent runs. Never send an API key to a browser or mobile app.
| Method | Path | Result |
|---|---|---|
POST | /v1/risk/sessions | Create a session; returns 201 with identifiers, token, expiry, SDK URL, and connect URL. |
POST | /v1/risk/sessions/{id}/client-token | Issue a new 30-minute token; the previous token stops working. |
GET | /v1/risk/sessions/{id} | Read status and per-file outcomes. |
GET | /v1/risk/sessions?offset=0 | List sessions, 40 per page, newest first. |
GET | /v1/risk/sessions/{id}/results | Read results; returns 409 results_not_ready before a terminal state. |
DELETE | /v1/risk/sessions/{id} | Delete session, files, and results; returns 204. |
Create a session
| Field | Type | Required | Description |
|---|---|---|---|
reference_id | string, 1–128 | yes | Your applicant or loan ID. |
origin | string | yes | The exact origin that embeds the SDK, saved as an allowed origin on the dashboard's SDK page. For iOS and Android, the app origin you pass to the SDK: an HTTPS origin you own; nothing has to be served there. |
display_name | string, 1–60 | no | Overrides the name borrowers see for this session. Default: your organization's name, shown beside your logo. |
country | MX or PH | no | Default MX. Must be a country enabled for you. |
location | optional or disabled | no | Legacy; use disabled. |
Send an Idempotency-Key header (up to 128 characters) per applicant. Repeating
the same key and body returns the same session with a new client token; a different
body returns 409 idempotency_conflict.
Returns 201 with session_id, client_token, expires_at, sdk_url,
connect_url and environment.
Session status
collecting → queued → processing → completed, partial, or failed.
Check each document's status and reason. Scores are included only with live scoring.
Python helper
Download kita_risk.py (standard library only).
Webhooks
Kita turns on webhooks for your organization on request: send the HTTPS URL and
we will share the signing secret. Events carry id, session_id, and a type:
risk.session.completed,
risk.session.partial, or risk.session.failed. They contain no scores; fetch results.
Verify Kita-Signature: t=TIMESTAMP,v1=DIGEST, where the digest is HMAC-SHA256 of
TIMESTAMP.RAW_BODY with your webhook secret (or use KitaRisk.verify_webhook(secret, signature_header, raw_body)). Reject timestamps older than five minutes and
deduplicate event IDs. Return 2xx after storing; failures retry up to six times.
iOS
Add the supplied KitaRisk Swift package and present KitaRiskViewController
(iOS 15+). It runs in-app with the photo, Files and camera pickers.
Add NSCameraUsageDescription to Info.plist. Both origins must be HTTPS, and
appOrigin must match the session and an allowed origin. The callback confirms
receipt only; fetch results on your server.
Android
Android has no drop-in screen yet: host the flow in your own WebView with the
supplied capture Gradle module (Android 8+, Java 17, compile SDK 36).
- Enable JavaScript and DOM storage, and allow navigation only to the SDK origin and your app origin.
- Attach the bridge, then load a small host page under your app origin that loads
{sdkOrigin}/sdk/v1/kita-risk.jsandkita-risk.cssand callsKitaRisk.create({ sessionId, clientToken, baseUrl: sdkOrigin, container: '#sdk' }).open(). - Handle
WebChromeClient.onShowFileChooserfor photos and documents, and receiveonSubmitted/onExit/onErrorthrough a message listener scoped to your app origin (WebViewCompat.addWebMessageListener).
Forward onActivityResult and onRequestPermissionsResult to the bridge, and call
capture.close() when the host is destroyed. Call
capture.setPhotoCaptureAvailable(true) only if your file chooser supports the camera.
The SDK repository's Android sample is a complete host to start from.
Testing uploads
Use the SDK repository's iOS and Android samples and Maestro journeys; see
docs/SDK_MOBILE_TESTING.md.
Errors
Errors contain error.code and error.request_id; include the request ID when
contacting Kita.
| Status | Code | Fix |
|---|---|---|
| 401 | invalid_api_key | Missing, truncated, rotated, or revoked key. A key used on the other environment's base URL gets wrong_environment, which names the right URL. |
| 403 | sdk_not_enabled | Your organization has no allowed origins for this environment yet. Add them on the dashboard's SDK page. |
| 403 | origin_not_allowed | origin must exactly match one of your allowed origins: scheme, host and port, no path. |
| 403 | profile_not_enabled | This country is not enabled for your organization. |
| 404 | session_not_found | Wrong ID, another organization's session, or expired. |
| 409 | idempotency_conflict | Same Idempotency-Key, different body. Use one key per applicant. |
| 409 | results_not_ready | Wait for the webhook or for a terminal status. |
| 413 | request_too_large | Over the size limit. |
| 422 | invalid_request, market_profile_not_validated | A field failed validation (error.fields names it), or country does not match your profile. Checked before the key. |
| 429 | rate_limited | Wait for Retry-After seconds. |
| 503 | sdk_settings_unavailable | Your SDK settings could not be read. Retry after Retry-After seconds. |
Upload errors
| Code | Cause | What happens |
|---|---|---|
encrypted_pdf | The PDF needs a document password. | The flow asks for it. |
invalid_pdf_password | Wrong document password. | The borrower can retry. |
unsupported_format | Not a PDF or supported image. | The borrower picks another file. |
invalid_image, corrupt_pdf, empty_document | The file cannot be opened. | The borrower picks another file. |
document_too_large, too_many_pages, oversized_image | Over a limit. | The borrower picks a smaller copy. |
multiple_image_frames | An animated or multi-frame image. | Export pages as a PDF or separate photos. |
document_limit_reached | 12 files already uploaded. | Remove one first. |
connection_error, rate_limited | Network trouble or throttling. | The flow offers Retry. |
client_token_expired, invalid_client_token, missing_client_token | The 30-minute token ran out, was replaced, or was not sent. | Get a new client token and reopen. |
session_locked | The files were already shared. | Nothing to do; the session shows its receipt. |
Finished sessions may report per-file model_rejected, blank_document,
extraction_error, or processing_timeout. These are analysis outcomes; the
borrower still sees a receipt.
Limits
| Write requests | 120 per minute per organization, in bursts of up to 30. 429 carries Retry-After. |
| File size | 100 MB per file uploaded through the SDK. The Scoring API accepts up to 30 MB per document. |
| Files per session | 12 |
| PDF pages | 150 per file |
| Client token lifetime | 30 minutes |
| Session retention | 24 hours unless agreed otherwise |


