Isokyn API

One API call, one explainable decision. Send an application to the fabric; get back approve, review or decline with the complete reasoning attached: every rule checked, every signal consulted, every threshold cited.

Overview

The Isokyn API is a JSON-over-HTTPS decision API. The core flow has three parts:

  • Policies are versioned data, not code. Thresholds and model coefficients live on a policy version; changing anything means publishing a new version. Decisions always record which policy version produced them.
  • Signals are consulted per decision. Today that includes live OFAC SDN sanctions screening of the applicant name; the trace cites the list date used.
  • Every decision is persisted with a full audit trail: the input, the per-step trace, the computed figures, the policy version and the latency. Append-only, replayable.

Base URL and environments

https://api.isokyn.com

All requests use HTTPS and JSON bodies with Content-Type: application/json. The sandbox organization is pre-provisioned with the consumer-loan policy v1; production tenants are provisioned during onboarding.

Authentication

Two credential types, usable on the same endpoints:

API key (machine-to-machine)

Send your key in the X-Api-Key header. Keys are stored hashed (SHA-256); treat them like passwords and rotate on compromise.

# example
curl https://api.isokyn.com/v1/stats/overview \
  -H "X-Api-Key: isk_..."

User session (console, short-lived)

Exchange email and password for a 12-hour JWT, then send it as a Bearer token.

POST /v1/auth/login
{ "email": "you@company.com", "password": "..." }

# response
{ "token": "eyJ...", "user": { "email": "...", "role": "ADMIN", "org": "..." } }

Password changes: POST /v1/auth/change-password with currentPassword and newPassword (user sessions only; API keys get 403).

Decisions

POST /v1/decisions auth required

Evaluates an application against your organization's ACTIVE policy version for the given workflow and returns the outcome with full reasoning. The decision and its audit event are persisted before the response returns.

Request body

FieldTypeNotes
workflow requiredstringPolicy key, e.g. consumer-loan
applicant.name requiredstringFull name; screened against OFAC SDN
applicant.creditScore requiredinteger300 to 850
applicant.monthlyNetIncome requirednumberEUR, >= 0
applicant.requestedAmount requirednumberEUR, >= 1
applicant.existingMonthlyDebt requirednumberEUR, >= 0
applicant.countryRiskTier requiredstringlow, med or high

Example

curl -X POST https://api.isokyn.com/v1/decisions \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: isk_..." \
  -d '{
    "workflow": "consumer-loan",
    "applicant": {
      "name": "Ana Marinescu",
      "creditScore": 682,
      "monthlyNetIncome": 3200,
      "requestedAmount": 15000,
      "existingMonthlyDebt": 450,
      "countryRiskTier": "low"
    }
  }'

Response

{
  "id": "cms32ac6x0001v0ioke8yf4t3",
  "outcome": "APPROVE",            // APPROVE | REVIEW | DECLINE
  "declineReason": null,             // set when outcome is DECLINE
  "policy": { "key": "consumer-loan", "version": 1 },
  "trace": [ ... ],                  // see The decision trace
  "computed": {
    "dti": 0.23828125,
    "monthlyPayment": 312.5,
    "modelScore": 57
  },
  "latencyMs": 4,
  "createdAt": "2026-07-27T09:10:31.518Z"
}

Outcomes

  • APPROVE: every rule passed and the composite model score cleared the auto-approve line.
  • REVIEW: at least one signal landed in a caution band (possible sanctions match, DTI near the limit, model score between the cut-offs, high-risk jurisdiction, or screening list unavailable). Route to a human with the trace attached.
  • DECLINE: a hard rule failed. declineReason states which one, with the threshold cited.

The decision trace

Every decision carries a step-by-step trace: what was checked, what was found, and how it affected the outcome. Statuses are ok, warn (caution band) and fail (hard rule).

[
  { "name": "Sanctions screening (OFAC SDN)",
    "detail": "No hit across 19254 SDN entries (SDN list 2026-07-27)",
    "status": "ok" },
  { "name": "Policy rule: minimum score",
    "detail": "Credit score 682 vs threshold 580",
    "status": "ok" },
  { "name": "Affordability rule (DTI)",
    "detail": "Debt-to-income 23.8% vs limit 45%",
    "status": "ok" },
  { "name": "Risk model",
    "detail": "Composite risk score 57/100 (higher is safer)",
    "status": "ok" }
]

Sanctions screening is live data: applicant names are screened against the OFAC SDN list (currently ~19,000 entries). An exact match is a hard decline; a partial match routes to review; the trace always cites the list date used, so any decision can be defended later against the list as it stood.

Policies

GET /v1/policies auth required

Lists every policy version in your organization with its status (ACTIVE, DRAFT, RETIRED) and the last-24h decision count. One key has at most one ACTIVE version; decisions always run against it.

[ { "key": "consumer-loan", "version": 1, "status": "ACTIVE",
    "createdAt": "2026-07-27T...", "decisions24h": 12 } ]

Stats

GET /v1/stats/overview auth required

Aggregates over your last 24 hours of decisions: totals per outcome, auto-approval rate, latency p50 and p99, hourly volumes, top decline reasons (aggregated from traces) and the most recent decisions. This is the endpoint behind the console Overview.

Signal sources

GET /v1/sources auth required

The live connector registry: each connected signal source with its status, entry count and data date.

[ { "key": "ofac-sdn", "name": "OFAC SDN",
    "status": "connected", "entries": 19254,
    "listDate": "2026-07-27T11:49:58Z" } ]

Leads

POST /v1/leads public

Request-access intake used by the isokyn.com form. Public, rate limited to 5 requests per minute per IP.

FieldTypeNotes
email requiredstringValid email, max 320 chars
company optionalstringMax 200 chars
message optionalstringMax 2000 chars

Errors and limits

StatusMeaning
400Validation failed. The body lists every rejected field; unknown fields are rejected too.
401Missing or invalid credentials (bad API key, expired token, wrong password).
403Authenticated but not allowed (e.g. password change with an API key).
404No ACTIVE policy for the requested workflow.
429Rate limit exceeded (public endpoints).

Error bodies follow the NestJS shape: { "statusCode": 400, "message": [...], "error": "Bad Request" }.

Versioning

The API is versioned in the path (/v1/). Additive changes (new fields, new endpoints) ship without notice; breaking changes get a new path version. Policy changes never alter the API contract: a new policy version changes thresholds, not shapes.