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, nothing 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…
  • 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
  • CLI
  • Playground
  • Console and keys
  • With coding agents
  • MCP server
  • Examples

Concepts

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

Models

  • DecisionNode MoE
  • DecisionNode 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
  • Keys on devices
  • Bill your customers per device
  • Publishable keys

Integrations

  • Home Assistant
  • MQTT bridge
  • ROS 2

API reference

  • Overview
  • POST/v1/decide
  • GET/v1/models
  • POST/v1/uploads
  • /v1/keys
  • GET/v1/keys/{key_id}/usage
  • GET/v1/usage
  • Errors
  • Safety check
  • Rate limits

Sessions API

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

Collections API

  • Overview
  • POSTCreate a collection
  • GETList collections
  • GETRetrieve a collection
  • DELDelete a collection
  • POSTEnroll a face
  • GETList items
  • PATCHUpdate an item
  • DELDelete an item

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
  • CLI
  • Playground
  • Console and keys
  • With coding agents
  • MCP server
  • Examples

Concepts

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

Models

  • DecisionNode MoE
  • DecisionNode 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
  • Keys on devices
  • Bill your customers per device
  • Publishable keys

Integrations

  • Home Assistant
  • MQTT bridge
  • ROS 2

API reference

  • Overview
  • POST/v1/decide
  • GET/v1/models
  • POST/v1/uploads
  • /v1/keys
  • GET/v1/keys/{key_id}/usage
  • GET/v1/usage
  • Errors
  • Safety check
  • Rate limits

Sessions API

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

Collections API

  • Overview
  • POSTCreate a collection
  • GETList collections
  • GETRetrieve a collection
  • DELDelete a collection
  • POSTEnroll a face
  • GETList items
  • PATCHUpdate an item
  • DELDelete an item

Pricing and billing

  • Pricing and billing
  • Refer & earn

Policies

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

Bill your customers per device

Your customers' devices call DecisionNode with keys of their own. Label each key with its customer, read every key's usage for the month in one call, and turn the rows into invoice lines.

on this page6 sections
  1. Give every device a labelled key
  2. Read the month
  3. Revoked keys are included
  4. Wait for as_of
  5. Turn rows into invoice lines
  6. Why the cost is what we charge you

Some products put DecisionNode on their customers' hardware: a drone's flight computer, a camera at a customer's site, a robot on a customer's floor, each calling the API itself rather than through your servers. Every call is metered on the key that made it, so with one key per device you can read each device's usage and cost for a month, and bill each of your customers for theirs. This guide builds on Keys on devices.

Give every device a labelled key#

Make each device's Decisions-only key with POST /v1/keys when the device enrolls, as on Keys on devices, and label it with what you bill by: the customer, and the plan the device is on. Labels are the filter of the month's read, and they are read as the key carries them now, not as it carried them when each call was made: a key whose labels you change mid-month bills its whole month to its new labels. So set them when the key is made, and when a device moves to another customer, give it a new key and revoke the old one.

A device's key, labelled
{
  "name": "Drone 0042",
  "device_id": "acme-drone-0042",
  "labels": { "customer": "acme", "plan": "pro" },
  "daily_spend_cap": { "usd": 5 }
}
  • One key per device, never shared: the key is the meter, so a key on two devices bills one customer for both.
  • A daily spend cap bounds what one device can cost you in a day if its key is copied, whatever you bill for it.

Read the month#

On the first of the month, read last month for each customer from your server, with a Full access or Manage device keys key: GET /v1/usage?start=2026-10-01T00:00:00Z&end=2026-11-01T00:00:00Z&label=customer:acme&status=all. You get one row per key used in the month, with its totals, newest key first. Follow next_cursor until it is null: a page can hold fewer keys than limit (Paging). end is exclusive, so a month runs from its first midnight to the next month's, in UTC.

One customer's month
curl -G https://api.decisionnode.com/v1/usage \
  -H "Authorization: Bearer $DECISIONNODE_MANAGE_KEY" \
  --data-urlencode "start=2026-10-01T00:00:00Z" \
  --data-urlencode "end=2026-11-01T00:00:00Z" \
  --data-urlencode "label=customer:acme" \
  --data-urlencode "status=all"
200 OK
{
  "period": {
    "start": "2026-10-01T00:00:00Z",
    "end": "2026-11-01T00:00:00Z"
  },
  "as_of": "2026-11-01T00:00:00Z",
  "items": [
    {
      "key": {
        "id": "key_3b8f0d6e2a914c7b9e5f1a2c4d6e8f01",
        "name": "Drone 0042",
        "scope": "decide",
        "device_id": "acme-drone-0042",
        "labels": { "customer": "acme", "plan": "pro" },
        "status": "active",
        "created_at": "2026-09-02T08:14:00Z",
        "revoked_at": null,
        "expires_at": null
      },
      "totals": {
        "requests": 12480,
        "free_tier_requests": 0,
        "input_tokens": 68640000,
        "image_tokens": 49920000,
        "video_tokens": 0,
        "booster_calls": 0,
        "cost": { "usd": 2.88288, "model_usd": 2.88288, "boosters_usd": 0 }
      }
    },
    {
      "key": {
        "id": "key_9d1c5e7a3b2f4e6d8c0a1b3e5f7a9c20",
        "name": "Drone 0017",
        "scope": "decide",
        "device_id": "acme-drone-0017",
        "labels": { "customer": "acme", "plan": "pro" },
        "status": "revoked",
        "created_at": "2026-08-11T10:02:00Z",
        "revoked_at": "2026-10-19T16:40:00Z",
        "expires_at": null
      },
      "totals": {
        "requests": 5210,
        "free_tier_requests": 0,
        "input_tokens": 28655000,
        "image_tokens": 20840000,
        "video_tokens": 0,
        "booster_calls": 0,
        "cost": { "usd": 1.20351, "model_usd": 1.20351, "boosters_usd": 0 }
      }
    }
  ],
  "next_cursor": null
}

Revoked keys are included#

status=all, which is also the default, keeps every key the month used, so a device revoked or expired during the month still has its row, with what it did before: Drone 0017 above was revoked on the 19th and is billed for its 5,210 requests. Its usage stays readable after it is revoked: usage is kept indefinitely. Pass status=active only when you want today's fleet, not the month's.

Wait for as_of#

Usage is folded in every minute, from calls at least two minutes old, and as_of says how far the figures are complete. It never passes the period's end: wait until it equals end before you invoice. For a month that is normally a few minutes after 00:00 UTC on the 1st, and from then on the month's figures do not change: usage is dated when it is recorded, and nothing arrives late in a past hour. The one exception is a rebuild of past hours, during which as_of steps back to the first of them. The samples above refuse to invoice before as_of reaches end; run them again later. See as_of.

Turn rows into invoice lines#

Each row is a line: key.name or key.device_id says which device, key.labels which customer and plan, and totals what it did. Charge your own price: per request, per token, per device a month, or your cost plus a margin. At USD 0.002 a request, the month above reads:

  • Drone 0042

    Requests
    12,480
    Cost to you
    USD 2.88288
    Invoice line
    USD 24.96
  • Drone 0017

    Requests
    5,210
    Cost to you
    USD 1.20351
    Invoice line
    USD 10.42
Acme's October, at USD 0.002 a request
DeviceRequestsCost to youInvoice line
Drone 004212,480USD 2.88288USD 24.96
Drone 00175,210USD 1.20351USD 10.42
  • Keep money exact. cost.usd is in whole micro-dollars, at most 6 decimals: read it as a decimal (Python's Decimal, Go's json.Number), not a float, and round only the invoice's own total.
  • Group by label in your own code when one invoice spans several labels: read once per customer, or once for every key and group the rows by key.labels.customer.
  • Several months, or a day by the hour: granularity=month or day adds buckets to each row (and holds a page to 100 keys); one key's own figures are at GET /v1/keys/{key_id}/usage.

Why the cost is what we charge you#

totals.cost is what your workspace is charged for the key's calls in the period: refused and failed calls, and the free tier's model part, at 0, and a capped key's answers at most what was reserved for them. On a prepaid workspace it is the list price as metered: what your balance was drawn down by, and your usage page's spend. On a workspace invoiced at a negotiated rate, it is the invoice's own arithmetic at the month's rate: summed over your keys, it matches the usage on your invoice, each answer's usage.cost, and your usage page's spend, which on such a workspace runs a couple of minutes behind. An invoice's workspace-wide lines (reserved capacity, collection storage, and the credit for usage drawn before invoicing began) are in no key's figures. Totals are priced per key, month and model, and each bucket and split on its own sums: at list prices they add up exactly; at a negotiated rate a part can differ from its share by a micro-dollar. So the rows of a month add up to what that month's usage costs your workspace, and what you invoice above it is your margin.

  • The free tier, where your workspace has one, makes the first requests of each day (it renews at 00:00 UTC) cost 0 on whichever keys made them; each row's free_tier_requests counts them. If your price is your cost plus a margin, price from requests and tokens instead, so the free tier lowers your costs and not one customer's bill.
  • A capped key's answer never costs more than was reserved for it: an answer that would cost more is cut to the reservation, and the difference is ours. The rows count the tokens billed for it.

Every parameter and field is on GET /v1/usage and GET /v1/keys/{key_id}/usage.

previousKeys on devicesnextPublishable keys

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. Give every device a labelled key
  2. Read the month
  3. Revoked keys are included
  4. Wait for as_of
  5. Turn rows into invoice lines
  6. Why the cost is what we charge you