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

Keys on devices

Give every device its own Decisions-only key from your provisioning server, with its own limits, spend cap and expiry, and revoke one device or a whole group by label.

on this page9 sections
  1. Provision a device
  2. Make a Manage device keys key
  3. Make the device's key when it enrolls
  4. Hand the secret to the device once
  5. Decide from the device
  6. Pictures from a device
  7. Limits, spend cap and expiry
  8. Revoke
  9. Fleet operations with labels

A device that decides on its own (a camera, a kiosk, a robot) needs a key on the device. Give it a Decisions-only key of its own, made by your provisioning server when the device enrolls. The device can then make decisions and list the models, and nothing else; your server keeps the only key that can make more. Why this matters is on API keys.

Provision a device#

  1. 1

    Make a Manage device keys key#

    In the console, under API keys, create a key of the kind Manage device keys. Keep it on your provisioning server, in a secret manager or an environment variable such as DECISIONNODE_MANAGE_KEY. It can make, change and revoke Decisions-only keys, and it cannot make a decision.

  2. 2

    Make the device's key when it enrolls#

    When a device asks for a key, your server first checks it your own way (its serial number, a certificate, a sign-in of yours), then calls POST /v1/keys for it. Send an Idempotency-Key of that enrollment: a retry within 24 hours returns the same key and secret instead of making a second one. A replay goes only to the Manage device keys key that made the key, and a workspace's Idempotency-Key values are one namespace, so if several provisioning servers make keys, give each its own prefix.

    curl -X POST https://api.decisionnode.com/v1/keys \
      -H "Authorization: Bearer $DECISIONNODE_MANAGE_KEY" \
      -H "Idempotency-Key: enroll-kiosk-0412" \
      -H "Content-Type: application/json" \
      -d '{"name":"Kiosk 0412","device_id":"kiosk-0412","labels":{"store":"118","fw":"2.4"},"limits":{"requests_per_second":5,"tokens_per_second":20000},"daily_spend_cap":{"usd":2},"expires_at":"2027-10-13T00:00:00Z","may_search_collections":false}'
  3. 3

    Hand the secret to the device once#

    Send the secret over your own channel to that device alone, and store it in the device's secure storage. Never log it. Keep the key's id on your server, to change or revoke it later.

  4. 4

    Decide from the device#

    The device uses the SDK, or plain HTTPS, with its own key.

    from decisionnode import DecisionNode, Image, truth
    
    dn = DecisionNode(api_key=read_device_secret())  # this device's Decisions-only key
    
    d = dn.decide(
        images=[Image("counter", path="/run/camera/latest.jpg")],
        questions={"waiting": truth("Is a customer waiting at the counter?")},
    )
    d["waiting"].truth  # 0.91

Never on a device

Neither the Manage device keys key nor a Full access key ever goes on a device, in firmware or in an app. A device asks your server for its key; it never calls /v1/keys itself.

Pictures from a device#

A Decisions-only key cannot make uploads (POST /v1/uploads is 403 key_scope_denied), so a device sends its pictures inline or by url, inside the decision. Inline takes up to 25 MiB a request, far more than a camera frame. The SDKs upload a request's local pictures once they reach their inline threshold, 512 KiB in all by default: on a device, raise it (inline_threshold in Python, dn.WithInlineThreshold in Go, inlineThreshold in PHP) so every picture goes inline.

Limits, spend cap and expiry#

  • Rate limits. limits sets the key's own requests and input tokens a second, each a whole number from 1 to the workspace's own (null clears both). Over them, a 429 rate_limit_error with Retry-After, as for any key. Set them a little above what the device really needs.
  • Daily spend cap. daily_spend_cap is the most the key may spend in a day, {"usd": 2.0} to two decimals and at most USD 1,000, and spent_today what it has spent so far. Past it, every call is 429 key_spend_cap_reached, "This key's daily spend cap of USD 2.00 is reached. It resets at 00:00 UTC.", with details resets_at, cap and spent, and Retry-After up to 00:00 UTC. Treat it as a stop, not a retry: report it to your server, which can raise the cap or replace the key.
  • The cap counts each request at its worst case until it is answered. Every request reserves its largest possible cost before it runs, and the key is charged the real cost once it is answered. So a key near its cap is refused a little early, by up to one request's worst case, and a capped key can have only about its cap divided by one request's worst-case cost in flight at once: with a very low cap and many calls at the same time, 429 key_spend_cap_reached can come before the day's real spend reaches the cap. Set the cap with headroom over what you expect to spend.
  • A capped key's answer never costs more than was reserved for it. If an answer would cost more (one priced as another version than the one reserved for, or more tokens than the model's context, as the model reports them), its cost is cut to the reservation and DecisionNode absorbs the difference. The answer's usage.cost, the usage page, per-key usage, the invoice and a prepaid balance all carry the cut amount, and the usage page and per-key usage count the tokens billed; the answer's own token counts stay as the model reported them, so on such an answer its tokens times the price come to more than its usage.cost.
  • Expiry. expires_at is at least a minute and at most 10 years ahead. After it the key answers 401 authentication_error with details.reason key_expired: do not retry, provision the device again. An expired key's settings cannot change (409 key_expired): it is replaced, never extended. A device_id belongs to one active key at a time, so to renew, revoke the old key and make the new one in the same provisioning call.

Face search is opt-in

A Decisions-only key cannot use the face_recognition booster unless you tick May search your face collections when you create it or edit it (may_search_collections through /v1/keys); without it the request gets 403 key_scope_denied. Anyone holding such a key can search your collections and read the matches, so tick it only for a device that runs face recognition.

Revoke#

Revoke one key by its id, or every key whose labels match all the labels you name. Count a group first with dry_run. One call revokes at most 10,000 keys, and more is true while matching keys are left, which can happen with fewer when a key was in use at that moment: call again until more is false. A revocation is immediate and cannot be undone: the next call with the key gets 401.

Revoke one key, or a group
curl -X DELETE https://api.decisionnode.com/v1/keys/key_7c2e9a41b0d34f6e8a5c1d2b3e4f5a60 \
  -H "Authorization: Bearer $DECISIONNODE_MANAGE_KEY"
What a group's revoke answers
{ "would_revoke": 37, "more": false }

Fleet operations with labels#

  • Labels are names and values, such as {"store": "118", "fw": "2.4"}: a label per site, per hardware batch or per firmware version lets you act on exactly the group a problem touches.
  • Find keys. GET /v1/keys?label=store:118 lists the keys of one store; repeat label to match them all (?label=store:118&label=fw:2.4), or ?device_id=kiosk-0412 for one device's key.
  • Move a device. PATCH /v1/keys/{id} with new labels moves it to another group without touching its secret.
  • A stolen batch of hardware. Revoke its label in one call, then provision the replacements as new devices.
  • In the console, Revoke by label does the same: Count keys first, then Revoke N keys.
  • Bill by label. GET /v1/usage?start=...&end=...&label=customer:acme reads every key's usage and cost for a period in one call, revoked keys included, so a label per customer is also an invoice per customer: Bill your customers per device.

Every field and route is on the /v1/keys reference.

previousControl loopsnextBill your customers per device

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. Provision a device
  2. Make a Manage device keys key
  3. Make the device's key when it enrolls
  4. Hand the secret to the device once
  5. Decide from the device
  6. Pictures from a device
  7. Limits, spend cap and expiry
  8. Revoke
  9. Fleet operations with labels