Skip to content
DecisionNodeDecisionNdedocs
  • Guides
  • API reference
  • Examples
  • Playground

start here

  • QuickstartGet startedGet an API key, send one request with three questions, and branch your code on the typed answers. Plain HTTPS, no SDK to install.
  • POST /v1/decideAPI referenceAnswer typed questions about a state and optional images. One request, one buffered JSON response, one answer per question.
  • QuestionsConceptsQuestions say what to decide. Each one has a type that fixes the shape of its answer: a choice from your options, a score on your scale, a…
  • ConfidenceConceptsProbabilities are calibrated per question type, so a threshold means what it says.
  • ImagesConceptsSend images and text in the same request. The model reads printed and handwritten text, amounts, dates, objects and layout, and answers…
  • Pricing and billingYou pay for input tokens only. Output is free because the model generates no text.
↑↓ moveopen6 suggestions
Get API keyGet API key
DecisionNodeDecisionNde

Get started

  • Introduction
  • Quickstart
  • With coding agents
  • Examples

Concepts

  • State
  • Questions
  • Choice
  • Score
  • Truth
  • Number
  • Images
  • Confidence
  • Determinism

Models

  • DecisionNode-1.0
  • DecisionNode-1.0 Flash
  • Limits

Patterns

  • Confidence-gated routing
  • Fan-out
  • Guardrails
  • Control loopscomingcoming soon

API reference

  • POST/v1/decide
  • POST/v1/sessionscomingcoming soon
  • GET/v1/models
  • Errors
  • Rate limits

Pricing and billing

  • Pricing and billing

Policies

  • Responsible use

Migrate

  • Coming from a Jev-shaped API
  • Benchmarks
  • Pricing
  • Playground
Get API key
  • Guides
  • API reference
  • Examples
  • Playground

Get started

  • Introduction
  • Quickstart
  • With coding agents
  • Examples

Concepts

  • State
  • Questions
  • Choice
  • Score
  • Truth
  • Number
  • Images
  • Confidence
  • Determinism

Models

  • DecisionNode-1.0
  • DecisionNode-1.0 Flash
  • Limits

Patterns

  • Confidence-gated routing
  • Fan-out
  • Guardrails
  • Control loopscomingcoming soon

API reference

  • POST/v1/decide
  • POST/v1/sessionscomingcoming soon
  • GET/v1/models
  • Errors
  • Rate limits

Pricing and billing

  • Pricing and billing

Policies

  • Responsible use

Migrate

  • Coming from a Jev-shaped API
  1. docs
  2. /
  3. Get started

Examples

Complete recipes you can start from: the problem, the request, the answer and the code that branches on it. Each one runs in the playground as is.

on this page7 sections
  1. Support inbox that routes itself
  2. Moderation pipeline
  3. Receipt and invoice checker
  4. Listing photo verifier
  5. Lead scoring
  6. Statement reader that chases late invoices
  7. Agent that asks before it acts

Run them without a key

Every recipe here is also a card in the example gallery, which opens it in the playground with the request filled in.

Support inbox that routes itself#

Problem: new tickets land in one pile and wait hours to be sorted. Build: one request per ticket picks the queue, ranks urgency and decides whether to refund on the spot.

{
  "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?"
    }
  }
}
Branch
a = answers
if a["refund"]["truth"] >= 0.8:
    issue_refund(ticket)
elif a["route"]["confidence"] < 0.7:
    reply(ticket, template="ask_for_order_id")   # the safe path, still automatic
else:
    queues[a["route"]["choice"]].put(ticket, priority=round(a["urgency"]["score"]))

Moderation pipeline#

Problem: comments need a decision in the time it takes to post them. Build: Flash answers three questions per comment; clear cases are published or removed on the spot, and the uncertain middle is shown with limited reach while the full model re-checks it. Here the model is sure the comment pushes buyers off the platform (0.96) even though the action itself is less certain.

{
  "model": "decisionnode-flash-latest",
  "state": {
    "surface": "listing comments",
    "comment": "DM me on telegram for half price, this seller is a fraud"
  },
  "questions": {
    "action": {
      "type": "choice",
      "instructions": "What should happen to this comment?",
      "criteria": {
        "allow": "fine to show as is",
        "limit": "show it with limited reach for now",
        "remove": "breaks the community rules"
      }
    },
    "off_platform": {
      "type": "truth",
      "instructions": "Is the comment trying to move a buyer off the platform?"
    },
    "toxicity": {
      "type": "score",
      "instructions": "How hostile is the language?",
      "criteria": ["none", "mild", "strong", "severe"]
    }
  }
}
Branch
const { action, off_platform, toxicity } = answers;

if (off_platform.truth >= 0.9 || (action.choice === "remove" && action.confidence >= 0.8)) {
  await removeComment(comment, { reason: off_platform.truth >= 0.9 ? "off_platform" : "rules" });
} else if (action.choice === "allow" && action.confidence >= 0.8 && toxicity.score < 1) {
  await publish(comment);
} else {
  await limitReach(comment); // unsure: the safe action first
  const recheck = await decide({ ...request, model: "decisionnode-latest" });
  if (recheck.action.choice === "remove") await removeComment(comment, { reason: "rules" });
}

Receipt and invoice checker#

Problem: expense claims arrive with a photo of the receipt and sit unpaid until they are checked. Build: send the claim as JSON and the receipt as an image; the model reads the printed total, currency and date and answers against the claim.

{
  "model": "decisionnode-latest",
  "state": {
    "expense_claim": {
      "amount": 48.2,
      "currency": "EUR",
      "date": "2026-09-28",
      "merchant": "Northside Cafe"
    }
  },
  "images": [
    { "id": "receipt", "media_type": "image/jpeg", "data": "<base64>" }
  ],
  "questions": {
    "matches": {
      "type": "truth",
      "instructions": "Does the receipt image show the same total, currency and date as the claim?"
    },
    "currency": {
      "type": "choice",
      "instructions": "Which currency is printed on the receipt?",
      "criteria": {
        "EUR": "euro",
        "GBP": "pound sterling",
        "USD": "US dollar"
      }
    },
    "legible": {
      "type": "truth",
      "instructions": "Is the total on the receipt clearly legible?"
    }
  }
}
Branch
a = answers
if a["legible"]["truth"] < 0.8:
    ask_for_new_photo(claim)
elif a["matches"]["truth"] >= 0.9 and a["currency"]["choice"] == claim["currency"]:
    approve(claim)
else:
    reject(claim, reason="receipt does not match the claim")  # and request a corrected receipt

Listing photo verifier#

Problem: a marketplace wants listing photos to show the actual item in the stated condition. Build: compare the listing record with its first photo. The score answer gives an expected condition of 2.15 (between good and like new), with the probabilities to back it.

{
  "model": "decisionnode-latest",
  "state": {
    "listing": {
      "title": "Oak dining table, seats 6",
      "condition": "like new",
      "finish": "natural oak"
    }
  },
  "images": [
    { "id": "photo_1", "media_type": "image/webp", "data": "<base64>" }
  ],
  "questions": {
    "shows_item": {
      "type": "truth",
      "instructions": "Does photo_1 show the item described in the listing?"
    },
    "condition": {
      "type": "score",
      "instructions": "What condition is the item in, judging by the photo?",
      "criteria": ["damaged", "worn", "good", "like new"]
    },
    "photo_kind": {
      "type": "choice",
      "instructions": "What kind of photo is this?",
      "criteria": {
        "own": "a real photo of this item",
        "stock": "a catalogue or stock image",
        "unclear": "cannot tell"
      }
    }
  }
}

Read the distribution, not only the score

The probability that the item is at least "good" is 0.57 + 0.30 = 0.87. That is often a better gate than the expected level itself. See Score.

Lead scoring#

Problem: sales wants the signups worth a reply today at the top. Build: score fit on your own rubric, classify intent, and filter out personal projects, all from the text of the form.

{
  "model": "decisionnode-flash-latest",
  "state": "Signup form. Company: 40-person logistics startup. Role: head of engineering. Message: We classify about 200k shipping exceptions a day with an LLM and it is too slow and too expensive. Want to test this next week.",
  "questions": {
    "fit": {
      "type": "score",
      "instructions": "How well does this lead fit a high-volume API product?",
      "criteria": ["poor", "possible", "good", "excellent"]
    },
    "intent": {
      "type": "choice",
      "instructions": "What does this person want right now?",
      "criteria": {
        "buying": "ready to buy or start a trial",
        "researching": "comparing options",
        "support": "an existing customer with a problem",
        "other": "none of these"
      }
    },
    "personal": {
      "type": "truth",
      "instructions": "Is this a personal or student project?"
    }
  }
}
Branch
const { fit, intent, personal } = answers;
const priority = personal.truth > 0.5 ? 0 : fit.score * (intent.choice === "buying" ? 2 : 1);
await crm.update(lead.id, { priority, intent: intent.choice });

Statement reader that chases late invoices#

Problem: finance reads customer statements by hand to decide who gets a reminder. Build: two Number questions count the overdue invoices (4, probability 0.84) and read how late the oldest one is (78 days), and a Choice picks the reminder. The reminder goes out on its own.

{
  "model": "decisionnode-latest",
  "state": "Customer statement\nAccount: Norrvik Supply AB (30-4471)\nStatement date: 2026-10-01\nTerms: net 30, amounts in EUR\n\nInvoice   Issued      Due         Amount    Status\nINV-2041  2026-06-15  2026-07-15  1,240.00  open\nINV-2058  2026-07-03  2026-08-02    410.00  paid 2026-08-01\nINV-2063  2026-07-21  2026-08-20    860.00  open\nINV-2069  2026-07-29  2026-08-28    395.00  paid 2026-09-02\nINV-2077  2026-08-06  2026-09-05  1,120.00  part paid, 300.00 open\nINV-2081  2026-08-13  2026-09-12    640.00  open\nINV-2090  2026-08-31  2026-09-30    780.00  paid 2026-09-29\nINV-2094  2026-09-10  2026-10-10    520.00  open\nINV-2102  2026-09-24  2026-10-24    915.00  open",
  "questions": {
    "overdue": {
      "type": "number",
      "instructions": "How many invoices on this statement are overdue on the statement date?",
      "min": 0,
      "max": 30
    },
    "oldest_days": {
      "type": "number",
      "instructions": "How many days past its due date is the oldest unpaid invoice?",
      "min": 0,
      "max": 180
    },
    "reminder": {
      "type": "choice",
      "instructions": "Which reminder should go out today?",
      "criteria": {
        "none": "nothing is overdue, send nothing",
        "friendly": "a friendly reminder for one recent invoice",
        "firm": "a firm reminder listing every overdue invoice",
        "final": "a final notice before the account is passed to collections"
      }
    }
  }
}
Branch
overdue, oldest, reminder = a["overdue"], a["oldest_days"], a["reminder"]

if overdue["confidence"] >= 0.7 and reminder["confidence"] >= 0.6:
    send_reminder(account, template=reminder["choice"],
                  overdue=overdue["number"], oldest_days=oldest["number"])
else:
    # unsure: the gentlest reminder is the safe path, still sent automatically
    send_reminder(account, template="friendly")

Agent that asks before it acts#

Problem: an agent with tools can do real damage on one bad call. Build: pass each proposed tool call to DecisionNode and run it only when the answer clears your bar. The full recipe is in Guardrails.

previousWith coding agentsnextState

DecisionNode is built and run by Bynn Intelligence, Inc.

  • Home
  • Playground
  • Examples
  • Console
  • Responsible use
  • Terms
  • Acceptable use
  • Privacy
  • Data processing
  • Defence addendum
  • Cookies

on this page

  1. Support inbox that routes itself
  2. Moderation pipeline
  3. Receipt and invoice checker
  4. Listing photo verifier
  5. Lead scoring
  6. Statement reader that chases late invoices
  7. Agent that asks before it acts