New: score your first 1,000 statements free during pilot.Get started ›

Developers

Build credit into your product

Kova turns bank and wallet statements into an explainable credit score and offer decision. Share a secure link and run the full lend loop — score, offer, accept, disburse and collect — from your dashboard today.

Coming soon

The SDK widget, JS client andREST API below are a preview of what's landing next. Today, use the shareable link + dashboard flow — it's fully live. API keys and programmatic access are opening soon.

Overview

Ways to integrate, from live today to coming soon:

  • Shareable link Live — create a link, send it to a borrower. They upload, we score, and you get an offer decision. Disburse from your dashboard. Zero frontend work.
  • SDK widget Soon — embed a polished upload widget in your own app with one script tag.
  • REST API + client Soon — drive scoring, offers, and rejection programmatically.

Authentication

Create keys in your dashboard under API keys. Each workspace gets apk_ publishable key (safe in the browser SDK) and ask_ secret key (server-side only). Send it as a Bearer token:

Authorization: Bearer sk_live_xxx

Publishable keys can score. Privileged actions (list links, reject) require a secret key or a signed-in dashboard session. Keys are scoped to their workspace — you can never act on another tenant. You can restrict a key to specific domains and IPs from the dashboard. Disbursement is not exposed to API keys — it's a dashboard-only action against your connected wallet.

Quickstart

Score a statement in one call:

curl -X POST https://api.kova.dev/v1/score \
  -H "Authorization: Bearer sk_live_xxx" \
  -F "statements=@statement.pdf"

SDK · Upload widget

Drop the widget into any page. Link mode needs no key.

<script src="https://unpkg.com/@kova/sdk"></script>
<script>
  Kova.init({
    requestId: 'REQUEST_ID',        // link mode (or key: 'pk_...')
    container: document.getElementById('mount'),
    autoOpen: true,
    onResult: (report) => console.log(report.score),   // direct/key mode
    onSubmitted: () => console.log('emailed'),          // link mode (async)
    onError: (err) => console.error(err),
  });
</script>

SDK · Assessment client

A typed client for creditworthiness assessment (server-side, secret key):

import { Kova } from '@kova/sdk';

const kova = Kova.client({ apiBase: 'https://api.kova.dev', key: 'sk_live_xxx' });

const link = await kova.createLink('John Doe · loan enquiry');
// share link.borrowerUrl with the borrower …

const req = await kova.getRequest(link.id);   // status, decision, offer, report
if (req.decision === 'declined') {
  await kova.reject(link.id);
}
// When the borrower accepts, disburse the loan from your Kova dashboard.

REST API

MethodEndpointDescription
POST/v1/scoreScore uploaded statements directly (multipart, field: statements). Key: any.
POST/v1/requestsCreate a shareable borrower link. Key: any.
GET/v1/requests/{id}Read a request: status, decision, offer, score report (non-PII). Public.
POST/v1/requests/{id}/intakeBorrower submits name, email, amount. Public (link is the capability).
POST/v1/requests/{id}/scoreBorrower uploads statements; scored async, result emailed. Public.
POST/v1/requests/{id}/acceptBorrower accepts an offer with account + BVN. Public.
POST/api/links/{id}/rejectLender declines a request before payout. Session or secret key.
GET/api/linksList all requests for the workspace. Session or secret key.

Request lifecycle

A shareable request moves through these states:

pendingscoredaccepteddisbursed·rejected
  • pending — link created; awaiting borrower intake + upload.
  • scored — statements scored; an offer decision (approved / counter / declined) is produced and emailed.
  • accepted — borrower confirmed a payout account; ready to disburse from your dashboard.
  • disbursed — funds sent via Monnify (dashboard action).
  • rejected — lender declined before payout. Links expire after 30 days.

Webhooks

Point Monnify's disbursement webhook at /webhooks/monnify. Kova verifies the monnify-signature (HMAC-SHA512) and updates the final payout status. A failed or reversed transfer automatically returns the loan toaccepted so it can be retried.

Ready to start?

Create a workspace, grab your keys, and score your first statement.

Get started free