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
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
| Field | Type | Notes |
|---|---|---|
| workflow required | string | Policy key, e.g. consumer-loan |
| applicant.name required | string | Full name; screened against OFAC SDN |
| applicant.creditScore required | integer | 300 to 850 |
| applicant.monthlyNetIncome required | number | EUR, >= 0 |
| applicant.requestedAmount required | number | EUR, >= 1 |
| applicant.existingMonthlyDebt required | number | EUR, >= 0 |
| applicant.countryRiskTier required | string | low, 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.
declineReasonstates 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
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
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
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
Request-access intake used by the isokyn.com form. Public, rate limited to 5 requests per minute per IP.
| Field | Type | Notes |
|---|---|---|
| email required | string | Valid email, max 320 chars |
| company optional | string | Max 200 chars |
| message optional | string | Max 2000 chars |
Errors and limits
| Status | Meaning |
|---|---|
| 400 | Validation failed. The body lists every rejected field; unknown fields are rejected too. |
| 401 | Missing or invalid credentials (bad API key, expired token, wrong password). |
| 403 | Authenticated but not allowed (e.g. password change with an API key). |
| 404 | No ACTIVE policy for the requested workflow. |
| 429 | Rate 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.