Overview
Unconditional Logic is a platform-agnostic decision engine. It evaluates data against configurable rules and returns structured decisions that power your business logic.
Fast Evaluation
Sub-50ms response times for real-time decisions.
Flexible Input
Accept any JSON. Auto-maps to known signals.
Auditable
Every decision logged with full context.
How It Works
Quick Start
Get your first decision in under 5 minutes.
1Get Your API Key
Sign up and generate an API key from your dashboard. Keys are prefixed with sk_live_ for production.
2Create an Engine
POST /api/v1/engines{
"name": "Lead Qualifier",
"slug": "lead-qualifier",
"configJson": {
"signals": [
{ "key": "email", "weight": 0.1, "evaluation": { "operator": "exists" } },
{ "key": "company_size", "weight": 0.2, "evaluation": { "operator": "gte", "value": 50 } }
],
"thresholds": { "tierA": 0.75, "tierB": 0.45 }
}
}3Evaluate Data
POST /api/v1/decisions/evaluate{
"engineId": "your-engine-uuid",
"input": {
"data": {
"email": "john@acme.com",
"company_size": 250,
"job_title": "VP Engineering"
}
}
}4Handle the Response
Response{
"decisionId": "dec_abc123",
"tier": "A",
"score": 0.82,
"confidence": 0.91,
"recommendedAction": "book",
"allowBooking": true,
"primaryDrivers": ["company_size", "email"]
}Authentication
Secure your API requests with API keys.
Header AuthenticationX-API-Key: sk_live_your_api_key_here
# Or using Bearer token
Authorization: Bearer sk_live_your_api_key_hereFull API Access
API keys provide full programmatic access to all endpoints including evaluation and management (engines, quizzes, actions). LLMs and external systems can create and manage resources without dashboard login.
| Endpoint | API Key | Public |
|---|---|---|
| /api/v1/decisions/evaluate | ✓ | — |
| /api/v1/engines/* | ✓ | — |
| /api/v1/quizzes/* | ✓ | — |
| /api/v1/actions/* | ✓ | — |
| /api/v1/public/evaluate | — | ✓ No auth |
| Prefix | Environment | Usage |
|---|---|---|
sk_live_ | Production | Live evaluations, real data |
sk_test_ | Test | Development, testing |
Evaluate
/api/v1/decisions/evaluateThe primary evaluation endpoint. Send data, receive a decision.
Request
{
"engineId": "uuid",
"input": {
"data": {
"email": "john@acme.com",
"job_title": "VP Engineering",
"company_name": "Acme Corp",
"company_size": 500,
"timeline": "1-3 months",
"budget_authority": true
}
},
"options": {
"persist": true,
"idempotencyKey": "unique-id"
}
}Response
{
"decisionId": "dec_xyz789",
"tier": "A",
"score": 0.87,
"confidence": 0.93,
"recommendedAction": "book",
"allowBooking": true,
"primaryDrivers": [
"budget_authority",
"company_size",
"job_title"
],
"processingTimeMs": 42
}Tier Classification
High quality — approve, book, proceed
Medium — review, nurture, conditional
Low quality — decline, queue
Scoring & Thresholds
How decisions are calculated and tiers assigned.
Critical: Thresholds Must Be 0-1
Thresholds are decimal values between 0 and 1, not percentages. Use 0.75 for 75%, not 75.
How Scoring Works
Each signal has a weight and scoreIfMatch/scoreIfMiss
Total score = sum of (weight × score) for all matching signals
Normalized score = totalScore / maxPossibleScore (always 0 to 1)
Tier is assigned by comparing normalized score to thresholds
✓ Correct Thresholds
"thresholds": {
"tierA": 0.75, // 75% - score >= 0.75 = Tier A
"tierB": 0.50 // 50% - score >= 0.50 = Tier B
} // Below 0.50 = Tier C✗ Wrong Thresholds
"thresholds": {
"tierA": 75, // ❌ This is NOT a percentage!
"tierB": 50 // ❌ Will never match correctly
}Response Score Formats
score0-100 integer for display (e.g., "85")
normalizedScore0-1 decimal, actual value used (e.g., "0.85")
Debug Information
Every API response includes _debug explaining the tier logic:
{
"decision": {
"tier": "A",
"score": 85,
"normalizedScore": 0.85
},
"_debug": {
"scoreExplanation": "Score 85% (0.850 normalized)",
"tierLogic": "0.850 >= tierA threshold (0.75)",
"note": "Thresholds are 0-1 values. Score 0.75 = 75%."
}
}Public API
No authentication required. For quizzes, forms, and widgets.
/api/v1/public/evaluateNo AuthRequest{
"engineSlug": "wellness-quiz",
"data": {
"sleep_score": 65,
"energy_score": 70,
"stress_score": 55,
"age": 35
},
"email": "user@example.com"
}Response{
"decision": {
"tier": "B",
"score": 63,
"confidence": 85
},
"outcome": {
"action": "recommend_standard",
"allowBooking": true,
"drivers": ["stress_score", "sleep_score"]
}
}Rate Limited
Public endpoints are limited to 60 requests/minute per IP address.
Engines
Create and manage decision engines.
| Endpoint | Description |
|---|---|
GET /api/v1/engines | List all engines |
POST /api/v1/engines | Create engine |
GET /api/v1/engines/:id | Get engine details |
PUT /api/v1/engines/:id | Update engine |
DELETE /api/v1/engines/:id | Delete engine |
Engine Configuration
{
"signals": [
{
"key": "job_title",
"weight": 0.25,
"evaluation": {
"operator": "exists",
"scoreIfMatch": 1,
"scoreIfMiss": 0
}
},
{
"key": "company_size",
"weight": 0.2,
"evaluation": {
"operator": "gte",
"value": 50,
"scoreIfMatch": 1,
"scoreIfMiss": 0.3
}
}
],
"thresholds": { "tierA": 0.75, "tierB": 0.45 },
"outcomes": {
"tierA": {
"label": "Qualified",
"action": "book",
"allowBooking": true,
"webhookUrl": "https://hooks.example.com/...",
"tags": ["qualified", "enterprise"],
"priority": "high"
},
"tierB": {
"label": "Review",
"action": "review",
"allowBooking": true,
"tags": ["needs-review"]
},
"tierC": {
"label": "Not Qualified",
"action": "decline",
"allowBooking": false,
"redirectUrl": "https://example.com/resources"
}
}
}Outcome Configuration
Define what happens when each tier is assigned.
Each tier (A, B, C) can have a rich outcome configuration that defines actions, webhooks, redirects, and CRM integrations. These are returned in the API response and can drive your frontend behavior.
Outcome Fields
| Field | Type | Description |
|---|---|---|
| label | string | Display name (e.g., "Qualified", "VIP") |
| action | string | Primary action type |
| allowBooking | boolean | Can proceed to booking/checkout |
| message | string | User-facing message |
| priority | string | high, medium, or low |
| webhookUrl | string | URL to POST decision payload |
| redirectUrl | string | URL to redirect user (supports variables) |
| tags | string[] | CRM tags to apply |
| notifyEmails | string[] | Emails to notify |
| responseData | object | Custom key-value data in response |
Action Types
proceedAllow user to proceedbookDirect to meeting bookingreviewSend to manual reviewnurtureAdd to nurture sequencerecommendShow recommendationsdeclinePolitely declineredirectRedirect to URLwebhookTrigger webhook onlyqueueAdd to general queueURL Variables
Redirect URLs support variable interpolation:
{{tier}}The assigned tier (A, B, or C){{email}}User's email address{{score}}Normalized score (0-100){{decisionId}}Unique decision identifierhttps://example.com/thank-you?tier={{tier}}&ref={{decisionId}}Webhook Payload
When a webhookUrl is configured, this payload is POSTed:
{
"event": "decision.created",
"decisionId": "uuid",
"tier": "A",
"score": 82,
"confidence": 91,
"outcome": {
"label": "Qualified",
"action": "book",
"priority": "high",
"tags": ["qualified", "enterprise"]
},
"person": {
"email": "john@example.com",
"name": "John Doe",
"company": "Acme Corp"
},
"engineId": "uuid",
"engineSlug": "b2b-lead-scorer",
"timestamp": "2024-12-16T10:30:00Z"
}Webhooks
Accept data from external form providers.
/api/webhooks/intake/:orgSlug/:engineIdAccepts submissions from Typeform, Jotform, Tally, and other form providers. Automatically maps common field formats.
Typeform Format
{
"form_response": {
"answers": [
{
"field": { "ref": "email" },
"email": "john@acme.com"
},
{
"field": { "ref": "company" },
"text": "Acme Corp"
}
]
}
}Generic Format
{
"email": "john@acme.com",
"firstName": "John",
"lastName": "Doe",
"company": "Acme Corp",
"customField": "value"
}AI Wizards
Generate engine and quiz configurations with AI.
Engine Wizard
POST /api/ai/engine-wizard
Describe your use case in plain English. Get a complete engine configuration.
{
"useCase": "Qualify B2B leads for SaaS sales",
"vertical": "b2b"
}Quiz Wizard
POST /api/ai/quiz-wizard
Generate complete quiz configurations with questions, themes, and results.
{
"useCase": "Wellness assessment quiz",
"vertical": "health",
"questionCount": 8
}Signal Catalog
Built-in signals the engine recognizes.
The engine auto-maps common field names to known signals. You can also define custom signals per engine.
Identity
emailfirst_namelast_namephoneagelocationAuthority
job_titleseniority_levelbudget_authoritydecision_makerFit
company_namecompany_sizeindustryrevenuetech_stackReadiness
timelinebudget_rangebuying_stagepain_levelHealth
health_scoresleep_scoreenergy_scorestress_scoreEcommerce
cart_valuelifetime_valueorder_countdays_since_purchaseEvaluation Operators
| Operator | Description | Example |
|---|---|---|
exists | Field has a value | { "operator": "exists" } |
equals | Exact match | { "operator": "equals", "value": true } |
gte | Greater than or equal | { "operator": "gte", "value": 50 } |
in | Value in array | { "operator": "in", "value": ["A", "B"] } |
contains | String contains | { "operator": "contains", "value": "VP" } |
Error Handling
HTTP status codes and error responses.
| Code | Meaning | Common Causes |
|---|---|---|
200 | Success | Request processed |
400 | Bad Request | Invalid input, validation failed |
401 | Unauthorized | Missing or invalid API key |
404 | Not Found | Resource doesn't exist |
429 | Too Many Requests | Rate limit exceeded |
500 | Server Error | Internal error |
Error Response Format{
"error": "Validation failed",
"details": [
{ "path": ["input", "data", "email"], "message": "Invalid email format" }
]
}Rate Limits
Request limits per endpoint type.
| Endpoint Type | Limit | Window |
|---|---|---|
| Authenticated API | 1000 requests | Per minute |
| Public Evaluation | 60 requests | Per minute (per IP) |
| AI Wizards | 20 requests | Per minute |
| Webhooks | 100 requests | Per minute (per endpoint) |
Ready to build?
Get your API key and start building intelligent decision systems in minutes.