# DecisionNode documentation > A decision model and the inference API that serves it. Send text, JSON or images and get a typed choice, a score or the probability that a statement is true, calibrated, in milliseconds, from our own GPUs. The map of this documentation is https://decisionnode.com/llms.txt. Each page below is headed by its title and URL. --- # Introduction Section: Get started · URL: https://decisionnode.com/docs DecisionNode is a decision model and the inference API that serves it. You send text, JSON or images with typed questions and get typed answers back in milliseconds: a choice or a score with calibrated confidence, a Truth (the calibrated probability that a statement is true), or a number on your grid. (Diagram: a state and its questions go into one request; typed answers with probabilities come back.) ## What you send and what comes back One request carries a `state` (the thing to decide about) and a map of `questions`. The response carries one answer per question, under the same keys, in the shape its type defines. Here is a support message routed, ranked and checked for an automatic refund in one call. Request: ```json { "model": "decisionnode-flash-latest", "state": "Customer: I was charged twice and nobody has replied for 3 days.", "questions": { "route": { "type": "choice", "instructions": "Where should this go?", "criteria": { "billing": "money", "bug": "broken", "account": "login" } }, "urgency": { "type": "score", "instructions": "How urgent is this?", "criteria": ["routine", "today", "urgent", "critical"] }, "refund": { "type": "truth", "instructions": "Refund this automatically?" } } } ``` Response: ```json { "model": "decisionnode-1.0-flash", "answers": { "route": { "type": "choice", "choice": "billing", "confidence": 0.81, "probabilities": { "account": 0.05, "billing": 0.87, "bug": 0.08 } }, "urgency": { "type": "score", "score": 2.31, "confidence": 0.47, "legend": { "0": "routine", "1": "today", "2": "urgent", "3": "critical" }, "probabilities": { "0": 0.01, "1": 0.09, "2": 0.48, "3": 0.42 } }, "refund": { "type": "truth", "truth": 0.94 } }, "usage": { "input_tokens": 62, "output_tokens": 0 } } ``` The model read the message once and answered three questions in one pass. It generated no text, so `output_tokens` is 0 and you pay only for the 62 input tokens. This request goes to DecisionNode-1.0 Flash, about 5 ms server side. A refund in the unsure middle (0.40 to 0.80) is re-checked by the full model, `decisionnode-latest`, as the diagram shows; everything else is settled by the first answer. ## Four question types Every type names its answer: choice (one of your labels), score (a level on your scale), truth (a probability), number (a value on your grid). The four question types | Type | In the API | What it asks | What comes back | | --- | --- | --- | --- | | [Choice](https://decisionnode.com/docs/concepts/choice) | `"type": "choice"` | Pick one option from the list you give | `choice` (always one of your keys), `probabilities` per option, `confidence` | | [Score](https://decisionnode.com/docs/concepts/score) | `"type": "score"` | Place the input on your ordered scale | `score` (expected level), `probabilities` per level, `legend`, `confidence` | | [Truth](https://decisionnode.com/docs/concepts/truth) | `"type": "truth"` | Is this statement true? | `truth`, one number from 0.00 to 1.00: the probability that the statement is true | | [Number](https://decisionnode.com/docs/concepts/number) | `"type": "number"` | How many, or what value? | `number` (a value on your grid), `expected`, `confidence`, `probabilities` per value | **Reading a Truth answer.** One calibrated probability from 0.00 to 1.00 that the statement is true. 0.80 means true about 8 times in 10. Your code picks the cut-off: 0.50 for a plain yes or no, higher when acting on a false yes is costly. **Reading a Number answer**. One value on a grid you set (min, max and an optional step), with a calibrated probability for every value: the most probable value, the expected value and the confidence. Count the cars in a drone frame, read the year off a contract, count the overdue invoices in a statement. See [Number](https://decisionnode.com/docs/concepts/number). **Streaming decisions** (announced, not yet served). More than 10 decisions a second, for a drone, a simulator or a monitoring loop? Open a [session](https://decisionnode.com/docs/api/sessions): send the context once, stream frames over a WebSocket and get a typed decision for each. [Control loops](https://decisionnode.com/docs/patterns/control-loops) shows where it fits. ## Why a decision model Rules break on real input: a regex does not know that "charged twice" is a billing problem. A chat model knows, but it writes text you have to parse, and it does not answer the same way twice. DecisionNode is trained to decide, not to write. - **Always valid.** Every answer has the shape its type defines. A choice is always one of the keys you sent, so there is nothing to parse or repair. - **Calibrated.** Probabilities are calibrated per question type, so a threshold on confidence means what it says. See [Confidence](https://decisionnode.com/docs/concepts/confidence). - **Deterministic.** The same request to the same model version returns the same answer. There is no sampling. See [Determinism](https://decisionnode.com/docs/concepts/determinism). - **State read once.** The state and images are encoded once and shared by every question, so ten questions cost little more than one. ## The model and the machine We train the models and we run them, on our own inference stack and our own GPUs. There is no third-party API between your request and the answer, so nothing waits in someone else's queue. DecisionNode-1.0 Flash answers a short request in about 5 ms, measured server side in October 2026: fast enough to sit inside every request, every payment and every frame of a robot's loop. The two models | Model | Model id | Price per 1M input tokens | Output | | --- | --- | --- | --- | | [DecisionNode-1.0](https://decisionnode.com/docs/models/decisionnode) | `decisionnode-latest` | $0.042 | Free | | [DecisionNode-1.0 Flash](https://decisionnode.com/docs/models/flash) | `decisionnode-flash-latest` | $0.021 (provisional) | Free | ## Start here - [Quickstart](https://decisionnode.com/docs/quickstart): Get a key, send one request, branch on the answer. Under five minutes. - [With coding agents](https://decisionnode.com/docs/coding-agents): A prompt to paste into your coding agent and a decide tool for your own agents. - [Examples](https://decisionnode.com/docs/examples): Complete recipes: support triage, moderation, receipts, listing photos, lead scoring. - [POST /v1/decide](https://decisionnode.com/docs/api/decide): Every field of the request and the response, headers and errors. --- # Quickstart Section: Get started · URL: https://decisionnode.com/docs/quickstart Get an API key, send one request with three questions, and branch your code on the typed answers. Plain HTTPS, no SDK to install. 1. **Get an API key** Open the [console](https://decisionnode.com/console/keys), go to **API keys** and choose **Create key**. The key is shown once, so copy it straight into your environment. Live keys start with `dn_live_`. ```bash export DECISIONNODE_API_KEY="dn_live_..." ``` 2. **Send your first request** Post a state and your questions to `https://api.decisionnode.com/v1/decide`. This one routes a support message, ranks its urgency and asks whether to refund it automatically. curl: ```bash curl https://api.decisionnode.com/v1/decide \ -H "Authorization: Bearer $DECISIONNODE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "decisionnode-latest", "state": "Customer: I was charged twice and nobody has replied for 3 days.", "questions": { "route": { "type": "choice", "instructions": "Where should this go?", "criteria": { "billing": "money", "bug": "broken", "account": "login" } }, "urgency": { "type": "score", "instructions": "How urgent is this?", "criteria": ["routine", "today", "urgent", "critical"] }, "refund": { "type": "truth", "instructions": "Refund this automatically?" } } }' ``` Python: ```python import os import requests response = requests.post( "https://api.decisionnode.com/v1/decide", headers={"Authorization": f"Bearer {os.environ['DECISIONNODE_API_KEY']}"}, json={ "model": "decisionnode-latest", "state": "Customer: I was charged twice and nobody has replied for 3 days.", "questions": { "route": { "type": "choice", "instructions": "Where should this go?", "criteria": { "billing": "money", "bug": "broken", "account": "login" } }, "urgency": { "type": "score", "instructions": "How urgent is this?", "criteria": ["routine", "today", "urgent", "critical"] }, "refund": { "type": "truth", "instructions": "Refund this automatically?" } } }, timeout=10, ) response.raise_for_status() answers = response.json()["answers"] ``` TypeScript: ```typescript const response = await fetch("https://api.decisionnode.com/v1/decide", { method: "POST", headers: { Authorization: `Bearer ${process.env.DECISIONNODE_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ "model": "decisionnode-latest", "state": "Customer: I was charged twice and nobody has replied for 3 days.", "questions": { "route": { "type": "choice", "instructions": "Where should this go?", "criteria": { "billing": "money", "bug": "broken", "account": "login" } }, "urgency": { "type": "score", "instructions": "How urgent is this?", "criteria": ["routine", "today", "urgent", "critical"] }, "refund": { "type": "truth", "instructions": "Refund this automatically?" } } }), }); if (!response.ok) throw new Error(`DecisionNode ${response.status}`); const { answers } = await response.json(); ``` 3. **Read the answers** Each answer comes back under the key you gave its question. The route is `billing` with confidence 0.81, the urgency sits at 2.31 on your 0 to 3 scale, and the refund probability is 0.94. That last one is a [Truth](https://decisionnode.com/docs/concepts/truth) answer: the calibrated probability, from 0.00 to 1.00, that the statement is true, here that this charge should be refunded automatically. 0.80 means true about 8 times in 10. Your code picks the cut-off: 0.50 for a plain yes or no, higher when acting on a false yes is costly, as with a refund. ```json { "model": "decisionnode-1.0", "answers": { "route": { "type": "choice", "choice": "billing", "confidence": 0.81, "probabilities": { "account": 0.05, "billing": 0.87, "bug": 0.08 } }, "urgency": { "type": "score", "score": 2.31, "confidence": 0.47, "legend": { "0": "routine", "1": "today", "2": "urgent", "3": "critical" }, "probabilities": { "0": 0.01, "1": 0.09, "2": 0.48, "3": 0.42 } }, "refund": { "type": "truth", "truth": 0.94 } }, "usage": { "input_tokens": 62, "output_tokens": 0 } } ``` 4. **Branch on them** Answers are numbers and keys, so your code acts on them the moment they land. Sure cases go straight through; unsure ones take the safe path, still automatically. Python: ```python route = answers["route"] urgency = answers["urgency"] refund = answers["refund"] if refund["truth"] >= 0.8: # sure: refund now issue_refund(ticket) reply(ticket, template="refund_issued") elif route["confidence"] < 0.7: # unsure: safe path reply(ticket, template="ask_for_order_id") else: # sure: route it priority = round(urgency["score"]) assign(ticket, route["choice"], priority) ``` TypeScript: ```typescript const { route, urgency, refund } = answers; if (refund.truth >= 0.8) { // sure: refund now await issueRefund(ticket); await reply(ticket, { template: "refund_issued" }); } else if (route.confidence < 0.7) { // unsure: safe path await reply(ticket, { template: "ask_for_order_id" }); } else { // sure: route it const priority = Math.round(urgency.score); await assign(ticket, { queue: route.choice, priority }); } ``` > **No key yet?** The [playground](https://decisionnode.com/playground) runs the same request in the browser, shows the answers as charts and copies the request as curl, Python or TypeScript. ## What just happened - The model read the state once and answered all three questions in one pass, with `decisionnode-latest`. - It generated no text: `usage.output_tokens` is always 0, and output is free. - The request used 62 input tokens. At $0.042 per million, a million of these requests cost about $2.60. - Up to 64k tokens fit in one request, so the state can be a whole thread or a JSON record. - Choice, score and truth are three of the four question types. The fourth, [Number](https://decisionnode.com/docs/concepts/number), answers how many or what value, on a grid you set. ## Next steps - [Write better questions](https://decisionnode.com/docs/concepts/questions): Options, scales and instructions that the model reads well. - [Gate on confidence](https://decisionnode.com/docs/patterns/confidence-gated-routing): Act above a threshold, re-check the unsure middle with the full model, and take the safe path below it. - [Add an image](https://decisionnode.com/docs/concepts/images): Receipts, photos and screenshots in the same request. - [Handle errors](https://decisionnode.com/docs/api/errors): 400 to 529: which to fix, which to retry, and what to do when credit runs out. --- # With coding agents Section: Get started · URL: https://decisionnode.com/docs/coding-agents DecisionNode is one HTTPS call, so a coding agent can write the integration for you once it knows the shape. Paste the prompt below, or give your own agents a decide tool. ## A prompt for your coding agent Paste this into the agent that works in your repository, then tell it what to decide: "route new tickets in `support/inbox.ts` with DecisionNode". It carries the endpoint, the request and response shapes and the rules that keep the integration honest. **Agent prompt** ``` You are adding DecisionNode to this codebase. DecisionNode is a decision API: it reads a state (text, JSON or images) and answers typed questions with calibrated probabilities. It never generates text. Endpoint: POST https://api.decisionnode.com/v1/decide Auth: header "Authorization: Bearer ", key read from the DECISIONNODE_API_KEY environment variable on the server. Never ship the key to a browser or log it. Request body (model and questions required, state and images optional): { "model": "decisionnode-latest", // or "decisionnode-flash-latest" "state": "" | { ...json }, "images": [{ "id": "photo", "media_type": "image/jpeg", "data": "" }], "questions": { "": { "type": "choice", "instructions": "...", "criteria": { "