One call · a scored, explained decision
Vilkax

The risk-decision API for builders who can't ship a guess.

One HTTPS call in. A scored, explained verdict out: action, reasons, evidence and confidence. The same engine that protects people, exposed as plain JSON.

Explainable verdictsEU data residency Fail-closed authPII-free inputs Pay per call
Scroll
Quickstart

Live in an afternoon.

Get a key, make one call, act on the verdict. Every example below targets a real, live endpoint. No separate host, no test keys.

01

Get a key

We issue a partner key (vlx_live_…) and a tier. The plaintext is shown exactly once; we only store its SHA-256 hash.

02

Authenticate

Send Authorization: Bearer vlx_live_… on every request. Each endpoint requires a scope the key carries.

03

Decide

POST a signal bundle, get back the verdict, score, reasons and confidence. Approve, queue for review, or block.

04

Pay for use

Transparent per-call metering. Light lookups bill 1 unit, deep fused calls bill 3, usage is free. Check it any time.

# POST a signal bundle, get one explained decision back. curl -X POST https://vilkax.com/api/partner/v1/decide \ -H "Authorization: Bearer $VILKAX_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "signals": [{ "id": "process.remote_access_tool", "value": 0.9 }, { "id": "text.urgency_pressure", "value": 0.8 }, { "id": "transfer.outbound_initiated", "value": 1.0 }], "context": { "action_kind": "transfer" } }' { "ok": true, "tier": "growth", "billed_units": 3, "decision": { "type": "remote_access_fraud", "action": "review", "confidence": 0.9, "score": 84, "why": "Remote-access tool + urgency while a transfer is initiated.", "questions": ["Did someone ask you to install this to fix a problem?"], "humanReviewRequired": true } }
// Node 18+ / browsers: native fetch. A tiny wrapper is all you need today. const res = await fetch("https://vilkax.com/api/partner/v1/decide", { method: "POST", headers: { "Authorization": `Bearer ${process.env.VILKAX_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ signals: [{ id: "process.remote_access_tool", value: 0.9 }, { id: "text.urgency_pressure", value: 0.8 }], context: { action_kind: "transfer" }, }), }); const { decision } = await res.json(); if (decision.action === "block") hold(); else if (decision.action === "review") queueForReview(decision.why);
# Python 3 + requests import os, requests res = requests.post( "https://vilkax.com/api/partner/v1/decide", headers={"Authorization": f"Bearer {os.environ['VILKAX_API_KEY']}"}, json={ "signals": [{"id": "process.remote_access_tool", "value": 0.9}, {"id": "text.urgency_pressure", "value": 0.8}], "context": {"action_kind": "transfer"}, }, ) decision = res.json()["decision"] print(decision["action"], decision["why"])
Authentication

One key scheme. Scoped, hashed, fail-closed.

One key family: vlx_live_<key> as HTTP Bearer. No test / live split. Shown once in plaintext; stored as SHA-256 only.

Authorization: Bearer vlx_live_<48-hex key> Content-Type: application/json

Scopes per key

A key carries scopes: decide, kyt:screen, signals:read, risk:lookup, usage:read. A wildcard (e.g. signals:*) grants the family.

Fails closed, always

Missing key, bad header, revoked, under-scoped or quota-exhausted: all reject before the engine runs. Never a silent downgrade to a free read.

EU residency

EU-edge only. Inputs aren't training fodder; decisioning never stores raw PII. Self-host available on Enterprise.

API reference

The live endpoints. No vapourware.

Real, deployed routes on https://vilkax.com. Contract stable across model updates. Fields add, never break.

MethodEndpointScopeUnits
POST/api/partner/v1/decideFused, explainable decision from a signal bundle (+ optional indicator text / OSINT hint).decide3
POST/api/business/v1/risk/decideB2B fraud decisioning from a PII-free feature vector. Tier-gated channels.risk:decide3
GET/api/partner/v1/signals/lookup?type=email|url|entity&q=… URL / email / entity signal lookup.signals:read1–3
GET/api/intel/v1/risk/lookup?type=email|phone|domain|ip|wallet&value=… Scammer Reputation Index (Pro+).risk:lookup1
POST/api/nexus/v1/kyt/screenKnow-Your-Transaction: wallet / tx / counterparty → allow|review|block (Pro+).kyt:screen3
GET/api/partner/v1/usageCurrent-month units, quota, rate limit, per-endpoint breakdown. Not metered.usage:read0

Auth & scopes

Bearer key on every call; wildcards like signals:* grant the family. Missing, inactive or under-scoped keys fail closed. No silent downgrade.

Graceful degrade, never a false clear

When a source isn't configured yet, responses are still well-formed with "degraded": true. Never a false all-clear. Build against the real shape from day one.

The contract

Predictable errors. Honest headers.

Every error is { "ok": false, "error": "<code>" }, documented and machine-parseable. Metering and limits ride in response headers.

Error codes

400 bad_bodyBody wasn't valid JSON or didn't match the endpoint schema.
400 no_signalsThe bundle carried no known signal id / feature.
400 pii_in_featuresA feature id smuggled raw PII. Send opaque signal ids only, never a card / SSN / email.
400 invalid_typeA query type wasn't one of the allowed values for that lookup.
401 invalid_authMissing or malformed Authorization: Bearer header. Sends WWW-Authenticate: Bearer.
401 invalid_api_keyNo active row matches the key's SHA-256 hash.
403 insufficient_scopeKey authenticated but lacks the scope this endpoint needs.
403 tier_gatedEndpoint needs a higher tier (SRI and KYT require Pro+). The response names your tier.
403 key_revoked / key_inactiveThe key was revoked or has been deactivated.
403 partner_suspendedThe partner account is suspended.
403 business_trial_expiredThe 15-day business evaluation has ended; pick a plan to continue.
413 body_too_largeRequest body exceeded the per-endpoint limit (decide is 16 KB).
429 rate_limitedPer-minute burst limit hit. Honour Retry-After and back off.
429 quota_exceededMonthly metered-unit quota for the tier exhausted. Upgrade or wait for the period to roll.
503 service_unavailableBacking store briefly unavailable. Retry with backoff. Never returned as a false success.
405 method_not_allowedWrong HTTP method for the route.
500 internal_errorAn unexpected server-side error; safe to retry with backoff.

Rate limits & quota

Burst limit (per-minute) + monthly unit quota. Deep calls = 3 units, lookups = 1, usage = 0. Burst → 429 rate_limited + Retry-After; quota exhausted → 429 quota_exceeded. Enterprise uncapped.

Idempotency & retries

Same bundle → same verdict, so retrying /decide is safe. 503 service_unavailable → retry with backoff; never a false success. idempotency-key header on roadmap

Versioning

Every route is namespaced and versioned under /v1. The allow / review / block verdict contract is stable; we add fields, we don't break them.

# Check your current-month usage any time. This call is never metered. curl https://vilkax.com/api/partner/v1/usage \ -H "Authorization: Bearer $VILKAX_API_KEY" { "ok": true, "tier": "growth", "period": "2026-06", "quota": { "monthly_quota_units": 200000, "used_units": 41280, "remaining_units": 158720, "rate_limit_rpm": 600 }, "total_calls": 18640, "by_endpoint": [ … ] }
Pricing

Pay per call. Start with a free 15-day trial.

Lookups bill 1 unit, deep fused calls (/decide, KYT) bill 3, usage bills 0. No seat fees, no lock-in. Plans from €149/mo. Enterprise is uncapped by contract with EU-dedicated residency.

FAQ

Common questions.

How do I get an API key?

Request one from the contact form. We issue your vlx_live_ key and tier; the plaintext is shown exactly once. A self-serve portal is on the way.

What's the base URL and are there test keys?

One production server: https://vilkax.com, no separate api. host. There are no test keys; every new key starts with a free 15-day evaluation across all signal types.

What happens when a source isn't configured?

Responses are still well-formed with "degraded": true and an honest note. Never a false all-clear. Build against the real shape from day one.

Can I send raw PII?

No. Decisioning endpoints take opaque signal ids only; raw PII is rejected with pii_in_features. Lookup values (email, phone, domain, IP, wallet) are hashed server-side.

Built for the builders who can't ship a guess.

Start free, wire one call, and decide with evidence from day one.