Skip to main content

Documentation Index

Fetch the complete documentation index at: https://clearlayer.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

The decision engine evaluates an investor and wallet against a policy and returns an "allow", "deny", or "review" verdict. Every decision is stored immutably and can be retrieved by its audit_id.
All requests to these endpoints require a valid API key in the Authorization header.

Request a decision

POST /v1/decisions Runs a compliance check by evaluating the investor, wallet, and policy you specify. The engine applies the following rules in order:
PriorityConditionDecision
1Wallet screening_status is "blocked"denywallet_blocked
2Investor kyc_status is not "verified"reviewkyc_not_verified
3Policy requires_accredited is true and investor is not accrediteddenynot_accredited
4Policy allowed_countries is non-empty and investor’s country is not in itdenycountry_not_allowed
5Policy wallet_must_be_verified is true and wallet is not "verified"reviewwallet_not_verified
6All checks passallowpolicy_requirements_satisfied

Request body

investor_id
string
required
The ID of the investor to evaluate. Returns 404 if not found.
wallet_id
string
required
The ID of the wallet to evaluate. Returns 404 if not found.
asset_policy_id
string
required
The ID of the policy to evaluate against. Returns 404 if not found.
action
string
required
A label describing the action being attempted (e.g. "transfer", "mint", "redeem"). Stored for audit purposes.

Response fields

decision
string
The outcome of the compliance check: "allow", "deny", or "review".
reasons
string[]
An array of reason codes explaining the decision. Possible values: "policy_requirements_satisfied", "wallet_blocked", "kyc_not_verified", "not_accredited", "country_not_allowed", "wallet_not_verified".
audit_id
string
The unique ID of this decision record. Format: dec_.... Use this to retrieve the decision later with GET /v1/decisions/:id.
policy_version
string
The version of the decision engine used. Always "v1".
timestamp
string
ISO 8601 timestamp of when the decision was made.

Examples

# inv_seed_001: verified, accredited, US — wal_seed_001: verified, low-risk
curl -X POST https://clearlayer-api-production.up.railway.app/v1/decisions \
  -H "Authorization: Bearer cl_test_key_1234567890" \
  -H "Content-Type: application/json" \
  -d '{
    "investor_id": "inv_seed_001",
    "wallet_id": "wal_seed_001",
    "asset_policy_id": "pol_seed_001",
    "action": "transfer"
  }'
201 — Allow (investor and wallet pass all policy checks)
{
  "decision": "allow",
  "reasons": ["policy_requirements_satisfied"],
  "audit_id": "dec_q3r4s5t6u7v8",
  "policy_version": "v1",
  "timestamp": "2024-01-15T10:35:00.000Z"
}
201 — Deny (wallet is blocked — first check triggers immediately)
{
  "decision": "deny",
  "reasons": ["wallet_blocked"],
  "audit_id": "dec_w9x0y1z2a3b4",
  "policy_version": "v1",
  "timestamp": "2024-01-15T10:36:00.000Z"
}
201 — Review (investor KYC is pending, manual review required)
{
  "decision": "review",
  "reasons": ["kyc_not_verified"],
  "audit_id": "dec_c5d6e7f8g9h0",
  "policy_version": "v1",
  "timestamp": "2024-01-15T10:37:00.000Z"
}

Retrieve a decision

GET /v1/decisions/:id Retrieves a previously recorded decision by its audit_id. The response includes an immutable snapshot of the investor, wallet, and policy state at the time the decision was made.

Path parameters

id
string
required
The audit_id returned from POST /v1/decisions.

Response fields

id
string
The decision record ID. Format: dec_...
investor_id
string
The ID of the investor evaluated.
wallet_id
string
The ID of the wallet evaluated.
asset_policy_id
string
The ID of the policy used.
action
string
The action label provided at decision time.
decision
string
"allow", "deny", or "review".
reasons
string[]
Reason codes for the decision outcome.
policy_version
string
Always "v1".
created_at
string
ISO 8601 timestamp of when the decision was recorded.
input_snapshot
object
An immutable snapshot of the investor, wallet, and policy data used to reach the decision. This does not reflect any subsequent changes to those records.

Example

curl https://clearlayer-api-production.up.railway.app/v1/decisions/dec_q3r4s5t6u7v8 \
  -H "Authorization: Bearer cl_test_key_1234567890"

200 — OK

{
  "id": "dec_q3r4s5t6u7v8",
  "investor_id": "inv_a1b2c3d4e5f6",
  "wallet_id": "wal_g7h8i9j0k1l2",
  "asset_policy_id": "pol_m3n4o5p6q7r8",
  "action": "transfer",
  "decision": "allow",
  "reasons": ["policy_requirements_satisfied"],
  "policy_version": "v1",
  "created_at": "2024-01-15T10:35:00.000Z",
  "input_snapshot": {
    "investor": {
      "id": "inv_a1b2c3d4e5f6",
      "kyc_status": "verified",
      "accredited_status": true,
      "country": "US"
    },
    "wallet": {
      "id": "wal_g7h8i9j0k1l2",
      "screening_status": "verified",
      "risk_level": "low"
    },
    "policy": {
      "id": "pol_m3n4o5p6q7r8",
      "requires_kyc": true,
      "requires_accredited": true,
      "allowed_countries": ["US"],
      "wallet_must_be_verified": true
    }
  }
}

404 — Not found

{
  "error": "not_found",
  "message": "decision dec_notexist not found",
  "docs": "/decisions"
}