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, optional images and video frames. 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 on the data we measure.
  • ImagesConceptsSend up to 16 images and text in the same request. The model reads printed and handwritten text, amounts, dates, objects and layout, and…
  • Batch jobsPatternsSend up to 10,000 requests in one file and collect the answers later, at a lower price than live calls.
  • Pricing and billingYou pay for input tokens only. Output is free because the model generates no text.
↑↓ moveopen7 suggestions
Get API keyGet API key
DecisionNodeDecisionNde

Get started

  • Introduction
  • Quickstart
  • Playground
  • Console and keys
  • With coding agents
  • MCP server
  • Examples

Concepts

  • State
  • Questions
  • Choice
  • Score
  • Truth
  • Number
  • Points and boxes
  • Images
  • Video
  • Boosters
  • Confidence
  • Determinism

Models

  • DecisionNode-1.0
  • DecisionNode-1.0 Flash
  • Limits
  • Versions
  • Dedicated capacity

Fine-tuning

  • Overview
  • Prepare your dataset
  • Upload and validation
  • Start a training run
  • Watch a run
  • The quality gate
  • Use your model
  • Limits and pricing

Patterns

  • Confidence-gated routing
  • Fan-out
  • Guardrails
  • Control loops
  • Batch jobs

API reference

  • Overview
  • POST/v1/decide
  • GET/v1/models
  • POST/v1/uploads
  • Errors
  • Safety check
  • Rate limits

Sessions API

  • Sessions overview
  • POSTOpen a session
  • WSStream frames
  • DELEnd a session

Batch API

  • The batch object
  • POSTCreate a batch
  • POSTAdd requests
  • POSTFinalize a batch
  • GETRetrieve a batch
  • GETGet batch results
  • POSTCancel a batch
  • GETList batches

Pricing and billing

  • Pricing and billing
  • Refer & earn

Policies

  • Responsible use
  • Data and privacy
  • Benchmarks
  • Pricing
  • Playground
Get API key
  • Guides
  • API reference
  • Examples
  • Playground

Get started

  • Introduction
  • Quickstart
  • Playground
  • Console and keys
  • With coding agents
  • MCP server
  • Examples

Concepts

  • State
  • Questions
  • Choice
  • Score
  • Truth
  • Number
  • Points and boxes
  • Images
  • Video
  • Boosters
  • Confidence
  • Determinism

Models

  • DecisionNode-1.0
  • DecisionNode-1.0 Flash
  • Limits
  • Versions
  • Dedicated capacity

Fine-tuning

  • Overview
  • Prepare your dataset
  • Upload and validation
  • Start a training run
  • Watch a run
  • The quality gate
  • Use your model
  • Limits and pricing

Patterns

  • Confidence-gated routing
  • Fan-out
  • Guardrails
  • Control loops
  • Batch jobs

API reference

  • Overview
  • POST/v1/decide
  • GET/v1/models
  • POST/v1/uploads
  • Errors
  • Safety check
  • Rate limits

Sessions API

  • Sessions overview
  • POSTOpen a session
  • WSStream frames
  • DELEnd a session

Batch API

  • The batch object
  • POSTCreate a batch
  • POSTAdd requests
  • POSTFinalize a batch
  • GETRetrieve a batch
  • GETGet batch results
  • POSTCancel a batch
  • GETList batches

Pricing and billing

  • Pricing and billing
  • Refer & earn

Policies

  • Responsible use
  • Data and privacy
  1. docs
  2. /
  3. Get started

Boosters

A booster is a specialist model that reads your request's images before the decision and hands its reading to the model as evidence. Name up to 4 in boosters: age and ai_generated today. The readings come back in evidence, and each booster is priced per picture it reads: Human Age $0.024, AI-generated $0.006.

on this page10 sections
  1. Add a booster to a request
  2. Options
  3. What comes back
  4. How the model uses a reading
  5. When a booster cannot read
  6. Time
  7. What a booster costs
  8. Turning a booster off
  9. Where boosters work
  10. Errors
  11. What a booster never does

Some facts in a picture are hard for a general model: how old a person looks, or whether a photo was made by an image generator. A booster is a model trained for exactly one such reading. It reads the request's images first, and its reading is added to what DecisionNode reads. DecisionNode still answers every question itself, in the shapes you asked for.

  • Human Age (age). Estimates a person's age from a face in the picture, using the agemin.com age estimation model, ranked #1 by NIST for Child Online Safety (ages 13 to 16) on true positive rate. View the NIST report card · NIST results.
  • AI-generated (ai_generated). Whether a picture was made by an image generator, and which kind, using Trinity, the state-of-the-art AI image detection model from detector24.ai.
  • age

    Reads
    A picture of a person
    Adds to the decision
    How old the person is, with a range and a confidence. The largest face in the picture is read.
    Per picture
    $0.024
    Time budget
    800 ms
  • ai_generated

    Reads
    Any picture
    Adds to the decision
    How likely the picture was made by an image generator, which generator most likely when it reads as generated, and whether the file carries trusted Content Credentials (C2PA) and who signed them.
    Per picture
    $0.006
    Time budget
    800 ms
The boosters
BoosterReadsAdds to the decisionPer pictureTime budget
ageA picture of a personHow old the person is, with a range and a confidence. The largest face in the picture is read.$0.024800 ms
ai_generatedAny pictureHow likely the picture was made by an image generator, which generator most likely when it reads as generated, and whether the file carries trusted Content Credentials (C2PA) and who signed them.$0.006800 ms

Add a booster to a request#

List the boosters by name in a top-level boosters array, beside images and questions: "boosters": ["age", "ai_generated"]. Each one reads every image of the request.

curl https://api.decisionnode.com/v1/decide \
  -H "Authorization: Bearer $DECISIONNODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "decisionnode-latest",
    "state": {
      "account": {
        "id": "acc_8812",
        "product": "wine delivery",
        "country": "SE"
      }
    },
    "images": [
      {
        "id": "selfie",
        "url": "https://files.example.com/signups/8812/selfie.jpg"
      }
    ],
    "boosters": ["age", "ai_generated"],
    "questions": {
      "adult": {
        "type": "truth",
        "instructions": "Is the person in `selfie` 18 or older?"
      },
      "real_photo": {
        "type": "truth",
        "instructions": "Is `selfie` a real photograph, not an AI-generated picture?"
      }
    }
  }'
  • Up to 4 boosters a request, each named once. null and [] mean no boosters.
  • Boosters belong to the request, not to a question. Every question sees every reading, so say in each question which image it is about, by its id.
  • Every image form works: data, url and upload_id. A booster reads exactly the bytes the decision reads.
  • A request without boosters is answered exactly as before: nothing is added to it and nothing extra is billed.

Options#

Write a booster as an object instead of its name when it should read only some images, or when the request must not run without it. Below, age reads only the selfie and ai_generated reads both pictures and must answer: 3 booster calls, $0.036.

JSON
{
  "images": [
    {
      "id": "selfie",
      "url": "https://files.example.com/signups/8812/selfie.jpg"
    },
    {
      "id": "document",
      "url": "https://files.example.com/signups/8812/document.jpg"
    }
  ],
  "boosters": [
    {
      "name": "age",
      "images": ["selfie"]
    },
    { "name": "ai_generated", "require": true }
  ]
}

A booster object

namestringrequired
The booster's name: age or ai_generated. A bare string such as "age" is the same as {"name": "age"}.
imagesarray of image idsdefault every image
The ids of the request's images this booster reads. Leave it out to read them all. Naming fewer images costs fewer booster calls.
requirebooleandefault false
true: if this booster fails or runs out of time, the request fails with 529 booster_unavailable, which you retry. false: the decision runs without that reading, and evidence says why.
optionsobject
Settings of a booster. Neither booster takes a setting today, so a key in it is a 400.

What comes back#

The answers keep their shapes. The body gains evidence, one entry per booster you named, in your order, and usage gains two counts. The response also carries the x-decisionnode-boosters header.

{
  "model": "decisionnode-1.0",
  "answers": {
    "adult": { "type": "truth", "truth": 0.97 },
    "real_photo": { "type": "truth", "truth": 0.96 }
  },
  "evidence": {
    "age": {
      "version": "age-v3",
      "status": "ok",
      "latency_ms": 188,
      "billed_calls": 1,
      "results": [
        {
          "image": "selfie",
          "age_years": 34,
          "low": 29,
          "high": 39,
          "confidence": 0.88,
          "faces": 1
        }
      ]
    },
    "ai_generated": {
      "version": "ai_generated-v2",
      "status": "ok",
      "latency_ms": 342,
      "billed_calls": 1,
      "results": [
        {
          "image": "selfie",
          "generated": 0.03,
          "confidence": 0.94,
          "method": "inference",
          "top_generator": null,
          "c2pa_signer": null
        }
      ]
    }
  },
  "usage": {
    "input_tokens": 1121,
    "output_tokens": 0,
    "booster_tokens": 46,
    "boosters": 2
  }
}

evidence.<booster>

versionstring
The version of the booster that read, such as age-v3. Log it with the decision.
statusstring
ok, timeout, error, skipped. See When a booster cannot read.
latency_msinteger
How long the booster took.
billed_callsinteger
The calls of this booster billed on this request: one per image it read with status ok, every time a request uses it; 0 only for a booster that timed out, failed or was skipped, a picture it could not decode, and a refused request. Times the booster's price, it is what the booster cost.
resultsarray
One entry per picture, named by image. On ok, each carries the booster's fields, or "readable": false for a picture it could not decode. On timeout or error, one bare {"image": id} per picture it was meant to read. On skipped, empty.
Reading evidence
body = response.json()
for name, entry in body.get("evidence", {}).items():
    if entry["status"] != "ok":
        log.warning("booster %s: %s", name, entry["status"])  # decided without it
    for reading in entry["results"]:
        save_reading(decision_id, name, entry["version"], reading)
  • age

    Fields
    age_years, low, high, confidence, faces
  • ai_generated

    Fields
    generated, confidence, method, top_generator, c2pa_signer, c2pa
What each booster reports per image
BoosterFields
ageage_years, low, high, confidence, faces
ai_generatedgenerated, confidence, method, top_generator, c2pa_signer, c2pa

age reads the largest face in a picture: age_years with a likely range from low to high, a confidence, and faces, how many faces it found. A picture with no face comes back with faces 0 and no age. ai_generated gives generated, the probability that an image generator made the picture, and method: inference when it read the pixels, c2pa when the file's trusted Content Credentials declare it generated or edited by AI, which overrides the pixels and names the signer in c2pa_signer. top_generator names the likeliest generator only when a reading from the pixels says likely generated; a photograph like the selfie above reads null. Credentials that validate but are not trusted add "c2pa": "untrusted" and change nothing else. Every field and value is on the API reference.

  • usage.boosters

    What it counts
    The booster calls billed for this request: one per booster and image read
  • usage.booster_tokens

    What it counts
    The part of input_tokens the readings take, counted once per request
The usage counts a boosted request adds
FieldWhat it counts
usage.boostersThe booster calls billed for this request: one per booster and image read
usage.booster_tokensThe part of input_tokens the readings take, counted once per request

How the model uses a reading#

The readings are written after your state as short, fixed sentences, one per booster and image, each naming the picture by its number and id. The model reads them with the state, the images and the questions, as evidence. They are counted once per request, however many questions you ask, and their tokens are in usage.input_tokens and usage.booster_tokens.

  • A reading is evidence, not an answer. DecisionNode answers every question itself and may weigh a reading against what the picture and the state show.
  • Ask the question the reading informs. An age reading helps "Is the person in selfie 18 or older?" It does not answer it for you: your threshold on truth does.
  • Keep the reading for your records. evidence names the booster version that read, so a decision can be explained later.

When a booster cannot read#

  • ok

    What happened
    The booster read every picture; results has one reading per picture
    The decision
    Runs with the readings
    Billed
    Per picture read; not a picture it could not decode
  • timeout

    What happened
    No answer within the booster's 800 ms; results lists one {"image": id} per picture it was meant to read
    The decision
    Runs without it; with require: true the request is a 529
    Billed
    No: billed_calls 0
  • error

    What happened
    The booster failed; results lists the pictures as for a timeout
    The decision
    Runs without it; with require: true the request is a 529
    Billed
    No: billed_calls 0
  • skipped

    What happened
    None of the request's images is one this booster reads; results is empty
    The decision
    Runs without it
    Billed
    No
evidence.<booster>.status
StatusWhat happenedThe decisionBilled
okThe booster read every picture; results has one reading per pictureRuns with the readingsPer picture read; not a picture it could not decode
timeoutNo answer within the booster's 800 ms; results lists one {"image": id} per picture it was meant to readRuns without it; with require: true the request is a 529No: billed_calls 0
errorThe booster failed; results lists the pictures as for a timeoutRuns without it; with require: true the request is a 529No: billed_calls 0
skippedNone of the request's images is one this booster reads; results is emptyRuns without itNo

A booster that did not run still tells the model so, in its own line, so what the model read and what evidence says always agree. Within an ok booster, two readings say a picture gave nothing:

Pictures that gave no reading
{ "image": "selfie", "faces": 0 }
  • No face (Human Age): faces 0 and no age. It is billed like any reading: the booster looked.
  • Not decodable: "readable": false, a picture the booster could not decode. It is not billed.
  • Timed out or failed: the booster's status says so, results names each picture it was meant to read with nothing else, and billed_calls is 0.

Time#

Each booster has a time budget of 800 ms. The boosters of a request run side by side, before the model, so a boosted request takes at most the slowest booster's budget longer than the same request without boosters. latency_ms and the x-decisionnode-boosters header say what each one took.

The x-decisionnode-boosters header
x-decisionnode-boosters: age=ok:212,ai_generated=timeout:800

One entry per booster, in your order: its name, its status and its time in milliseconds. The header is on every response of a request that named boosters, errors included, so a 529 tells you which booster failed.

What a booster costs#

cost = input tokens × model price

+ sum of billed_calls × booster price

input tokens
usage.input_tokens, the readings included
billed_calls
evidence.<name>.billed_calls: one per image that booster read with status ok
booster price
that booster's price per call: age (Human Age) $0.024 and ai_generated (AI-generated) $0.006
  • Priced per call, by booster: age (Human Age) $0.024 and ai_generated (AI-generated) $0.006, drawn from your prepaid balance with the request's tokens. The first sample makes 2 calls, one of each booster on the one picture: $0.030.
  • A booster that timed out or failed is free, and so is a picture a booster could not decode ("readable": false). A Human Age reading of a picture with no face is billed.
  • Billed every time a request uses a reading, the same picture in a later request included: there is no discount for a picture read before.
  • A request the safety check refuses bills no booster call and carries no evidence.
  • A 529 after boosters ran bills the calls that read, since they happened, and your retry's readings are billed again. A 402 comes before any booster runs.

Booster spend shows under its own heading on the console's Usage page. Every price is on Pricing and billing.

Turning a booster off#

Every booster is on for a new workspace. An Owner or Admin can turn one off, or back on, on the console's Boosters page; other roles see the switches. A request that names a booster that is off gets 403 booster_not_enabled. A booster DecisionNode has turned off for your workspace shows as locked; write to us to change it.

Where boosters work#

  • POST /v1/decide

    Boosters
    Yes
  • Batch jobs

    Boosters
    Yes: each line takes boosters as a live request does, billed the same way
  • Fine-tuned models

    Boosters
    Yes, as on their base model
  • Sessions

    Boosters
    No: boosters on a session's open is 400 api_usage_error "boosters are not available on sessions"
Boosters by endpoint
WhereBoosters
POST /v1/decideYes
Batch jobsYes: each line takes boosters as a live request does, billed the same way
Fine-tuned modelsYes, as on their base model
SessionsNo: boosters on a session's open is 400 api_usage_error "boosters are not available on sessions"

Errors#

A boosted request has five errors of its own: booster_unavailable (529, retry it), booster_not_enabled (403), and booster_unknown, booster_input_mismatch and a malformed array's api_usage_error (400, fix the request).

  • 400

    Type
    api_usage_error
    When
    boosters is not an array, has more than 4 entries, names a booster twice, holds an entry that is neither a name nor an object with name, an object with a key other than name, images, require and options, or has a key in options. x-decisionnode-error says which
    What to do
    Fix the array
  • 400

    Type
    booster_unknown
    When
    A name that is not a booster
    What to do
    Use a name from the table above
  • 400

    Type
    booster_input_mismatch
    When
    A booster that reads images on a request without any, or an images entry that is not an image of the request
    What to do
    Add the image, or fix the id
  • 402

    Type
    insufficient_credit
    When
    The balance is empty; no booster ran
    What to do
    Add credit, then retry
  • 403

    Type
    booster_not_enabled
    When
    The booster is off for your workspace
    What to do
    Turn it on under Boosters, or leave it out
  • 529

    Type
    booster_unavailable
    When
    A booster with require: true failed or ran out of time
    What to do
    Wait Retry-After, then retry; the SDKs do
Errors of a boosted request
StatusTypeWhenWhat to do
400api_usage_errorboosters is not an array, has more than 4 entries, names a booster twice, holds an entry that is neither a name nor an object with name, an object with a key other than name, images, require and options, or has a key in options. x-decisionnode-error says whichFix the array
400booster_unknownA name that is not a boosterUse a name from the table above
400booster_input_mismatchA booster that reads images on a request without any, or an images entry that is not an image of the requestAdd the image, or fix the id
402insufficient_creditThe balance is empty; no booster ranAdd credit, then retry
403booster_not_enabledThe booster is off for your workspaceTurn it on under Boosters, or leave it out
529booster_unavailableA booster with require: true failed or ran out of timeWait Retry-After, then retry; the SDKs do
Two of the bodies
{
  "detail": {
    "error_type": "booster_not_enabled",
    "message": "The booster 'age' is not enabled for this workspace."
  }
}

What a booster never does#

  • It never answers a question, however sure it is, and never adds a question or an answer.
  • It never changes a request without boosters: the same request gets the same answer it got before boosters existed.
  • It never decides what the safety check refuses. The safety check judges the request as you sent it, never a reading.
  • It never keeps your images. The bytes are read for the call and not stored or logged; the request log records which boosters ran, their status and their time, never their readings.
  • It never reads more than the request's images: the same images, in the same workspace, under the same retention, at most 16 a request.

Readings about people

An age reading is an estimate from a picture, with a range and a confidence: one piece of evidence, not a document check. Decisions about people follow Responsible use.

nextIntroduction

DecisionNode is built and run by Bynn Intelligence, Inc.

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

on this page

  1. Add a booster to a request
  2. Options
  3. What comes back
  4. How the model uses a reading
  5. When a booster cannot read
  6. Time
  7. What a booster costs
  8. Turning a booster off
  9. Where boosters work
  10. Errors
  11. What a booster never does