DECISIONS API · REFERENCE
Decisions API reference
The Decisions API answers closed questions about a context. You list the allowed answers; each decision returns the chosen answer and a probability for every option. Create a key, send one POST, and read typed results.
Base URL https://decisionsapi.pro/api · Endpoint POST /v1/decisions
curl --fail-with-body https://decisionsapi.pro/api/v1/decisions \
-H "Authorization: Bearer $DECISIONS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"decisions-latest","context":"I was charged twice for my Pro subscription this month. Please refund the duplicate payment before Friday.","questions":{"queue":{"type":"choice","instructions":"Which queue should handle this ticket?","options":{"billing":"Payments, refunds and invoices","technical_support":"Bugs and product problems","sales":"New purchases and upgrades"}},"urgent":{"type":"yes_no","instructions":"Does the customer mention a deadline?"}}}'API keys
Create a key on the API keys page after signing in. Send it from your server as Authorization: Bearer <key>. Never ship a key in browser or mobile code, and revoke it from the same page when you no longer need it.
Models
| Model | Runs on | Use it for |
|---|---|---|
decisions-latest | OpenAI GPT-4.1 mini | Default. Best accuracy for nuanced policies and long context. |
decisions-mini | OpenAI GPT-4.1 nano | Lowest latency and cost for simple, high-volume routing. |
GET /api/v1/models lists the models available to your key.
curl https://decisionsapi.pro/api/v1/models -H "Authorization: Bearer $DECISIONS_API_KEY"Request format
{
"model": "decisions-latest",
"context": "I was charged twice for my Pro subscription this month. Please refund the duplicate payment before Friday.",
"questions": {
"queue": {
"type": "choice",
"instructions": "Which queue should handle this ticket?",
"options": {
"billing": "Payments, refunds and invoices",
"technical_support": "Bugs and product problems",
"sales": "New purchases and upgrades"
}
},
"urgent": {
"type": "yes_no",
"instructions": "Does the customer mention a deadline?"
}
}
}| Field | Required | Format |
|---|---|---|
model | No | decisions-latest (default) or decisions-mini. |
context | Yes | Text, a JSON object or an array; up to 100,000 characters. |
images | No | Up to 4 images: https URLs or base64 data URLs (PNG, JPEG, WebP, GIF, up to 5 MB each). context may be empty when images are sent. |
image_detail | No | auto (default), low or high. Low detail uses fewer input tokens. |
questions | Yes | Object keyed by question ID; 1–32 questions. |
Question IDs use letters, digits, dot, dash or underscore (up to 64 characters). The request body is limited to 20 MB. Images are sent with every question, so each image adds input tokens per question. The context is treated as data: instructions inside it are judged, not followed.
Question types
{
"sentiment": {
"type": "score",
"instructions": "How satisfied is the reviewer overall?",
"levels": [
"Very negative",
"Negative",
"Mixed",
"Positive",
"Very positive"
]
},
"refund_requested": {
"type": "yes_no",
"instructions": "Does the customer ask for a refund?",
"criteria": {
"yes": "Explicitly asks for money back",
"no": "Anything else"
}
},
"topic": {
"type": "choice",
"instructions": "What is the main topic?",
"options": {
"shipping": null,
"product_quality": null,
"billing": null,
"other": null
}
}
}| Type | Define | Returns |
|---|---|---|
choice | options: 2–20 names, each with an optional description (or null). | answer, confidence, probabilities per option. |
yes_no | Optional criteria.yes / criteria.no descriptions. | answer (boolean), probability of yes, confidence. |
score | levels: 2–10 labels, lowest to highest. | answer (level label), level (0-based), score (expected level), probabilities. |
Response format
A 200 response maps each question ID to its decision. Probabilities for a question sum to 1. The values below are illustrative.
{
"id": "4f3c1a2e-…",
"object": "decision",
"model": "decisions-latest",
"decisions": {
"queue": {
"type": "choice",
"answer": "billing",
"confidence": 0.9998,
"probabilities": {
"billing": 0.9998,
"technical_support": 0.0001,
"sales": 0.0001
}
},
"urgent": {
"type": "yes_no",
"answer": true,
"probability": 0.9241,
"confidence": 0.9241
}
},
"usage": {
"input_tokens": 262,
"output_tokens": 2
},
"latency_ms": 612
}usage.input_tokens is the total model input for all questions; each question is one model call over the same context.
Image input
Pass screenshots, receipts, product photos or scanned documents in images. The Decisions API reads them together with the text context for every question.
{
"model": "decisions-latest",
"context": "Employee note: client dinner after the Milan workshop. Alcohol needs manager approval.",
"images": [
"https://decisionsapi.pro/examples/receipt.jpg"
],
"questions": {
"category": {
"type": "choice",
"instructions": "Which expense category is this receipt?",
"options": {
"meals": null,
"travel": null,
"software": null,
"office": null
}
},
"needs_approval": {
"type": "yes_no",
"instructions": "Does the receipt include alcohol?"
}
}
}Python example
Standard library only. Use the confidence to decide when a person should review.
import json, os, urllib.request
body = {
"model": "decisions-latest",
"context": "Nobody wants your garbage opinions here. Log off.",
"questions": {
"label": {"type": "choice", "instructions": "Which policy label fits best?",
"options": {"safe": None, "harassment": None, "threat": None, "spam": None}},
"hide": {"type": "yes_no", "instructions": "Should this be hidden until reviewed?"},
},
}
req = urllib.request.Request(
"https://decisionsapi.pro/api/v1/decisions",
data=json.dumps(body).encode(),
headers={"Authorization": f"Bearer {os.environ['DECISIONS_API_KEY']}",
"Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=30) as resp:
result = json.load(resp)
label = result["decisions"]["label"]
if label["confidence"] < 0.8:
print("send to a human reviewer", label["probabilities"])
else:
print("label:", label["answer"])Billing headers
API calls use purchased input tokens first; if the token balance is insufficient, one credit covers the whole request. A request never charges both balances, output tokens are free, and failed requests are not charged.
| Header | Meaning |
|---|---|
X-Decisions-Billing | Balance used: tokens or credits-fallback. |
X-Decisions-Paid-Input-Tokens-Used | Input tokens charged. |
X-Decisions-Credits-Used | Credits charged. |
X-Decisions-Tokens-Remaining | Token balance after the call. |
X-Decisions-Credits-Remaining | Credit balance after the call. |
See pricing for token plans.
Errors and limits
| HTTP | Meaning | What to do |
|---|---|---|
401 | Missing, invalid or revoked key. | Use a valid key; do not retry. |
402 | No balance or spending paused. | Add tokens on the pricing page. |
422 | Invalid model, context or question. | Fix the request body. |
429 | Rate limit (600 requests per minute per account) or model busy. | Wait for Retry-After, then retry. |
502 / 503 / 504 | Model unavailable or timed out. | Retry with backoff; nothing was charged. |
Readiness check
A public check that returns ready and a reason. It does not run a decision or use a key.
curl https://decisionsapi.pro/api/decisions/status