Decisions API documentation

Everything you need to make your first Decisions API call: one endpoint, three question types, and a response your code can use without parsing.

Decisions API quickstart

A Decisions API call takes two things: the context you want a decision about, and the questions to answer, each with its allowed answers. This request routes a support ticket to one of three teams:

curl https://api.decisionsapi.cc/v1/decisions \
  -H "Authorization: Bearer $DECISIONS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "context": "Charged twice for my March invoice, please refund one.",
    "questions": {
      "team": {
        "type": "choice",
        "options": {
          "billing": "Payments, invoices, refunds",
          "technical": "Bugs, errors, integrations",
          "sales": "Plans, pricing, upgrades"
        }
      }
    }
  }'

The response contains one answer per question, keyed by the name you chose:

{
  "id": "dec_01J9X4M2Q8a7c3e5b1d0",
  "model": "decisions",
  "answers": {
    "team": {
      "choice": "billing",
      "confidence": 0.97,
      "probabilities": { "billing": 0.97, "technical": 0.02, "sales": 0.01 }
    }
  },
  "usage": { "input_tokens": 41, "credits": 1 }
}

choice is always one of the options you sent. probabilities covers every option and sums to 1, so you can apply your own threshold.

Authentication

Every Decisions API request is authenticated with a secret key in the Authorization header:

Authorization: Bearer $DECISIONS_API_KEY

Keys start with dk_live_. Keep your key on the server: never ship it in a browser bundle or a mobile app.

Don’t have a key yet? Buy credits and get one instantly. Check your remaining credits with GET /v1/balance.

Endpoint

The Decisions API has one endpoint for decisions, and one to check your balance:

POST https://api.decisionsapi.cc/v1/decisions
GET  https://api.decisionsapi.cc/v1/balance
FieldTypeDescription
contextstring | object | string[]What the decision is about. Required.
questionsobject1 or more questions, keyed by a name you choose. Required.
questions.*.typestringchoice, score or yes_no.
questions.*.optionsobject | string[]choice: option → description. score: ordered list, low to high.
questions.*.questionstringRequired for yes_no, optional framing for choice and score.
instructionsstringOptional policy text that applies to every question.
modelstringOptional. decisions (the default) or decisions-latest.

Context

The Decisions API accepts context in the form you already have it. You don’t need to extract features or summarize first.

  • Text: a ticket, an email, a chat transcript, a product description.
  • JSON: an event, a database row, an agent’s state.
  • A list of strings: messages in a thread, lines in a log.
{
  "context": {
    "event": "checkout_failed",
    "plan": "team",
    "error": "card_declined",
    "attempts": 3,
    "last_message": "tried two cards, neither works"
  },
  "questions": { ... }
}

Image input is on the Decisions API roadmap.

Decisions API question types

You can mix all three types in one request. Each question is answered independently against the same context.

choice

Pick exactly one option. Describe each option in plain words, as you would brief a colleague. Good descriptions are the biggest lever on accuracy.

"team": {
  "type": "choice",
  "options": {
    "billing": "Payments, invoices, refunds",
    "technical": "Bugs, errors, integrations",
    "sales": "Plans, pricing, upgrades"
  }
}
"team": {
  "choice": "billing",
  "confidence": 0.97,
  "probabilities": { "billing": 0.97, "technical": 0.02, "sales": 0.01 }
}

score

Place the context on an ordered scale. List options from lowest to highest. The Decisions API returns the most likely point and a probability for each, so you can also read the expected value.

"priority": {
  "type": "score",
  "question": "How soon does this need a human reply?",
  "options": ["whenever", "today", "within the hour", "right now"]
}
"priority": {
  "choice": "today",
  "confidence": 0.64,
  "probabilities": {
    "whenever": 0.08, "today": 0.64, "within the hour": 0.23, "right now": 0.05
  },
  "score": 1.25
}

yes_no

Answer one yes-or-no question with a boolean and the probability of “yes”.

"refund_requested": {
  "type": "yes_no",
  "question": "Is the customer asking for money back?"
}
"refund_requested": { "answer": true, "probability": 0.93 }

Response

FieldTypeDescription
idstringUnique id for the decision, useful for logs and support.
modelstringThe model that answered.
answers.*.choicestringSelected option (choice and score).
answers.*.confidencenumberHow certain the model is, 0–1. Derived from the probabilities; use it for thresholds.
answers.*.probabilitiesobjectProbability for every option you defined.
answers.*.scorenumberscore only: expected position on the scale, 0 = first option.
answers.*.answerbooleanyes_no only.
answers.*.probabilitynumberyes_no only: probability of “yes”.
usage.input_tokensnumberInput tokens in the request.
usage.creditsnumberCredits charged: 1 per started 4,000 input tokens. See pricing.

Decisions API in Python and Node.js

The Decisions API is a single JSON endpoint, so any HTTP client works and no SDK is needed. Copy one of these helpers, or give your coding agent the markdown reference.

Python: route a ticket, send unsure cases to a person

import os
import requests

DECISIONS_URL = "https://api.decisionsapi.cc/v1/decisions"
HEADERS = {"Authorization": f"Bearer {os.environ['DECISIONS_API_KEY']}"}

def decide(context, questions):
    res = requests.post(DECISIONS_URL, headers=HEADERS, json={
        "context": context,
        "questions": questions,
    }, timeout=10)
    res.raise_for_status()
    return res.json()["answers"]

answers = decide(ticket.body, {
    "team": {"type": "choice", "options": {
        "billing": "Payments, invoices, refunds",
        "technical": "Bugs, errors, integrations",
    }},
    "urgent": {"type": "yes_no", "question": "Does the customer need action today?"},
})

if answers["team"]["confidence"] < 0.7:
    send_to_human(ticket)
else:
    route_to(answers["team"]["choice"], urgent=answers["urgent"]["answer"])

Node.js: choose an agent’s next action

const DECISIONS_URL = "https://api.decisionsapi.cc/v1/decisions";

export async function decide(context, questions) {
  const res = await fetch(DECISIONS_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ context, questions }),
  });
  if (!res.ok) throw new Error(`Decisions API error ${res.status}`);
  return (await res.json()).answers;
}

// Let an agent pick its next tool from a closed list
const { next_action } = await decide(agentState, {
  next_action: {
    type: "choice",
    options: {
      search_docs: "The answer is probably in the product docs",
      ask_user: "Required information is missing",
      create_ticket: "This needs a human on the support team",
      finish: "The user's request is fully handled",
    },
  },
});

Errors

Errors use standard HTTP status codes and a consistent body:

{
  "error": {
    "type": "invalid_request",
    "message": "questions.team.options must have at least 2 entries",
    "param": "questions.team.options"
  }
}
StatusTypeMeaning
400invalid_requestThe body failed validation. The message names the field.
401unauthorizedMissing or invalid API key.
402insufficient_balanceThis key has no credits left. Top up on the pricing page.
413context_too_largeThe context exceeds the per-request token limit.
429rate_limitedToo many requests. Retry after the Retry-After header.
503overloadedTemporarily over capacity. Retry after the Retry-After header.
5xxserver_errorSomething failed on our side. Safe to retry with backoff.

Best practices

  • Make options mutually exclusive. If two options could both be right, merge them or add a third that covers the overlap.
  • Add an escape hatch. An option like "none": "None of the above apply" keeps the Decisions API from forcing a bad fit.
  • Use probabilities, not just the choice. Pick a confidence threshold per question and route everything below it to a human.
  • Ask small questions. Three narrow questions in one request beat one broad question with twelve options.
  • Evaluate on your own data. Run 100 labeled examples before you switch traffic, and re-run them whenever you edit option descriptions.