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. API reference

Keys

Make, list, change and revoke Decisions-only keys for your devices from your provisioning server, with a Manage device keys key.

on this page6 sections
  1. Make a key
  2. The key object
  3. List keys
  4. Change a key
  5. Revoke
  6. Errors

Every route takes a key of the kind Manage device keys (any other kind gets 403 key_scope_denied) and acts on the Decisions-only keys of its workspace. Make that key in the console; keep it on your server. How the kinds differ is on API keys, and the whole flow on Keys on devices.

  • POST /v1/keys

    What it does
    Make a Decisions-only key. 201 with the key and its secret
  • GET /v1/keys

    What it does
    The keys, newest first: label=name:value (repeat it; all must match), device_id and status (active, the default, expired, revoked or all) filter, limit 1 to 200 (50 by default) and cursor
  • PATCH /v1/keys/{id}

    What it does
    Change its name, labels, limits, daily_spend_cap, expires_at or may_search_collections: see Change a key
  • DELETE /v1/keys/{id}

    What it does
    Revoke it, at once: {"id", "revoked": true}
  • POST /v1/keys/revoke

    What it does
    Revoke every active key whose labels match labels, at most 10,000 a call
Routes
Method and pathWhat it does
POST /v1/keysMake a Decisions-only key. 201 with the key and its secret
GET /v1/keysThe keys, newest first: label=name:value (repeat it; all must match), device_id and status (active, the default, expired, revoked or all) filter, limit 1 to 200 (50 by default) and cursor
PATCH /v1/keys/{id}Change its name, labels, limits, daily_spend_cap, expires_at or may_search_collections: see Change a key
DELETE /v1/keys/{id}Revoke it, at once: {"id", "revoked": true}
POST /v1/keys/revokeRevoke every active key whose labels match labels, at most 10,000 a call

Make a key#

JSON
{
  "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
}

Request body

namestringrequired
1 to 48 letters, digits, spaces, dots, dashes and underscores, unique among the workspace's active keys.
device_idstring
Your id for the device, 1 to 128 printable ASCII characters, not starting with a space, unique among the workspace's active keys.
labelsobject
Up to 16 names and values: a name of 1 to 32 characters of a-z, 0-9 and _ . -, a value of 1 to 64 characters.
limitsobject
requests_per_second and tokens_per_second, each a whole number from 1 to the workspace's own; left out or null, the workspace's limits apply.
daily_spend_capobject
{"usd"}, to two decimals and at most USD 1,000; left out, no cap.
expires_atstring
RFC 3339, at least a minute and at most 10 years ahead; left out, the key never expires.
may_search_collectionsbooleandefault false
Allow face_recognition.
201
{
  "key": {
    "id": "key_7c2e9a41b0d34f6e8a5c1d2b3e4f5a60",
    "name": "Kiosk 0412",
    "prefix": "dn_live_",
    "scope": "decide",
    "last4": "9f3a",
    "device_id": "kiosk-0412",
    "labels": { "store": "118", "fw": "2.4" },
    "limits": { "requests_per_second": 5, "tokens_per_second": 20000 },
    "daily_spend_cap": { "usd": 2 },
    "spent_today": { "usd": 0 },
    "expires_at": "2027-10-13T00:00:00Z",
    "may_search_collections": false,
    "status": "active",
    "created_by_key": { "id": "key_1f0e2d3c4b5a69788796a5b4c3d2e1f0" },
    "created_at": "2026-10-20T09:12:04Z",
    "last_used_at": null,
    "revoked_at": null
  },
  "secret": "dn_live_<64 hex digits>"
}
  • secret is shown once, in this answer. A retry with the same Idempotency-Key header and body within 24 hours returns the same key, as it is now, and its secret again, and makes no second key.
  • Only to the key that made it. A workspace's Idempotency-Key values are one namespace: another Manage device keys key sending the same one gets 409 idempotency_key_reused, as does the same key with another body, so give each provisioning server its own prefix. While the first call still runs, a repeat is 409 idempotency_in_progress with Retry-After: wait it out and send the same call again, with the same Idempotency-Key, never a new one.
  • Not once revoked. If the key has been revoked since, or its secret can no longer be shown, the replay is 409 key_not_replayable: "The key this Idempotency-Key made is revoked or its secret can no longer be shown: revoke it if it is not, then create a new key with a new Idempotency-Key."
  • Rate: a workspace's Manage device keys keys make at most 20 keys a second, in bursts of up to 200, and 50,000 a day; beyond that, 429 rate_limit_error with Retry-After. Keys made in the console count apart.

The key object#

JSON
{
  "id": "key_7c2e9a41b0d34f6e8a5c1d2b3e4f5a60",
  "name": "Kiosk 0412",
  "prefix": "dn_live_",
  "scope": "decide",
  "last4": "9f3a",
  "device_id": "kiosk-0412",
  "labels": { "store": "118", "fw": "2.4" },
  "limits": { "requests_per_second": 5, "tokens_per_second": 20000 },
  "daily_spend_cap": { "usd": 2 },
  "spent_today": { "usd": 0 },
  "expires_at": "2027-10-13T00:00:00Z",
  "may_search_collections": false,
  "status": "active",
  "created_by_key": { "id": "key_1f0e2d3c4b5a69788796a5b4c3d2e1f0" },
  "created_at": "2026-10-20T09:12:04Z",
  "last_used_at": null,
  "revoked_at": null
}
idstring
key_ and 32 hex digits.
namestring
1 to 48 letters, digits, spaces, dots, dashes and underscores, unique among the workspace's active keys.
prefixstring
dn_live_, the start of the secret.
scopestring
decide for every key /v1/keys makes; the console's kinds are full, keys and publishable.
last4string
The secret's last four characters. The secret itself is returned once, when the key is made.
device_idstring or null
Your id for the device, 1 to 128 printable ASCII characters, not starting with a space, unique among the workspace's active keys.
labelsobject
Up to 16 names and values: a name of 1 to 32 characters of a-z, 0-9 and _ . -, a value of 1 to 64 characters.
limitsobject or null
The key's own rate limits, a second; null when the workspace's limits apply.
requests_per_secondinteger or null
Requests a second, a whole number from 1 to the workspace's own.
tokens_per_secondinteger or null
Input tokens a second, a whole number from 1 to the workspace's own.
daily_spend_capobject or null
{"usd"}, the most the key may spend in a day, to two decimals and at most USD 1,000; null for none. Resets at 00:00 UTC.
spent_todayobject or null
{"usd"}, what the key has spent since 00:00 UTC; null on a key without a cap.
expires_atstring or null
When the key stops working, RFC 3339, at least a minute and at most 10 years ahead; null for never. A Full access key's expiry is checked when a session's socket connects, and a socket already open keeps going until its session ends.
may_search_collectionsbooleandefault false
Whether the key may run face_recognition.
statusstring
active, expired or revoked.
created_by_keyobject or null
{"id"}, the Manage device keys key that made it through /v1/keys; null for one made in the console.
created_at, last_used_at, revoked_atstring or null
RFC 3339.

List keys#

GET /v1/keys?label=store:118&limit=50 answers {"items": [Key], "next_cursor"}; pass next_cursor as cursor for the next page, until it is null. Only Decisions-only keys are listed; a secret never is. Any other query parameter is 400 api_usage_error, "Unknown query parameter: <name>." There is no call that reads one key by its id: find a device's key with GET /v1/keys?device_id=kiosk-0412 (add status=all for one revoked or expired), or keep the key that POST /v1/keys and PATCH answer.

Change a key#

  • PATCH /v1/keys/{id} takes name, labels, limits, daily_spend_cap, expires_at and may_search_collections. A field left out stays as it is; labels is replaced whole, and null clears labels, limits, daily_spend_cap or expires_at. It answers the key.
  • device_id never changes: sending it is a 422 at ["body", "device_id"], "A key's device_id is set when it is made: revoke it and make another." Any other field is a 422 extra_forbidden, and an empty body a 400, "Nothing to change."
  • An expired key takes only a rename or a revoke: every other change is 409 key_expired, "This key has expired: make a new one. An expired key is never brought back." A revoked key is 409 already_revoked.

Revoke#

  • One key: DELETE /v1/keys/{id} answers {"id", "revoked": true}. A key already revoked is 409 already_revoked.
  • A group: POST /v1/keys/revoke with labels, a map every key must match, and optionally device_ids, up to 1,000 the keys must be among. It answers {"revoked": <count>, "more": <boolean>}, at most 10,000 a call. more is true while matching keys are left, which can happen with fewer than 10,000 when a key was in use at that moment: call it again until more is false. With "dry_run": true it revokes nothing and answers {"would_revoke": <count>, "more": <boolean>}, the count up to 10,000 and more when more keys match; dry_run must be a JSON boolean (a string such as "true" is a 422 bool_type, never read as false).
  • At once: the next call with a revoked key gets 401. A revocation cannot be undone.

Errors#

  • 401

    Type
    authentication_error
    When
    The key is missing, unknown, expired (details.reason key_expired) or revoked
  • 403

    Type
    key_scope_denied
    When
    The key is not a Manage device keys key: a Full access key, "Keys are managed with a keys key, made in the console."; a Decisions-only key, "This key may only make decisions."
  • 404

    Type
    not_found_error
    When
    "Not found." No such key among the workspace's Decisions-only keys
  • 400

    Type
    api_usage_error
    When
    An unknown query parameter on the list; an empty PATCH body, "Nothing to change."
  • 409

    Type
    already_revoked
    When
    The key is already revoked
  • 409

    Type
    idempotency_key_reused
    When
    "This Idempotency-Key was already used with a different request." Another body, or another Manage device keys key of the workspace, with an Idempotency-Key already used
  • 409

    Type
    idempotency_in_progress
    When
    "A request with this Idempotency-Key is still running. Try again shortly." With Retry-After: wait, then send the same call with the same Idempotency-Key
  • 409

    Type
    key_not_replayable
    When
    A replayed create whose key is revoked or whose secret can no longer be shown: "The key this Idempotency-Key made is revoked or its secret can no longer be shown: revoke it if it is not, then create a new key with a new Idempotency-Key."
  • 409

    Type
    key_expired
    When
    A change to an expired key other than a rename: "This key has expired: make a new one. An expired key is never brought back."
  • 422

    Type
    a detail list
    When
    A field out of bounds: labels past their limits, an expires_at less than a minute or more than 10 years ahead, a cap over USD 1,000, a name already used (name_taken), a device_id already on an active key (device_id_taken), a device_id in a PATCH, a field the route does not take (extra_forbidden), a dry_run that is not a boolean (bool_type)
  • 429

    Type
    rate_limit_error
    When
    Keys made faster than the rate above: "Keys are being made faster than this workspace may: 20 a second, bursts of 200, 50,000 a day.", details.reason key_creation_rate, with Retry-After
  • 529

    Type
    overloaded_error
    When
    Keys cannot be made right now, with Retry-After: send the same call, with the same Idempotency-Key, after it
Errors of the Keys API
StatusTypeWhen
401authentication_errorThe key is missing, unknown, expired (details.reason key_expired) or revoked
403key_scope_deniedThe key is not a Manage device keys key: a Full access key, "Keys are managed with a keys key, made in the console."; a Decisions-only key, "This key may only make decisions."
404not_found_error"Not found." No such key among the workspace's Decisions-only keys
400api_usage_errorAn unknown query parameter on the list; an empty PATCH body, "Nothing to change."
409already_revokedThe key is already revoked
409idempotency_key_reused"This Idempotency-Key was already used with a different request." Another body, or another Manage device keys key of the workspace, with an Idempotency-Key already used
409idempotency_in_progress"A request with this Idempotency-Key is still running. Try again shortly." With Retry-After: wait, then send the same call with the same Idempotency-Key
409key_not_replayableA replayed create whose key is revoked or whose secret can no longer be shown: "The key this Idempotency-Key made is revoked or its secret can no longer be shown: revoke it if it is not, then create a new key with a new Idempotency-Key."
409key_expiredA change to an expired key other than a rename: "This key has expired: make a new one. An expired key is never brought back."
422a detail listA field out of bounds: labels past their limits, an expires_at less than a minute or more than 10 years ahead, a cap over USD 1,000, a name already used (name_taken), a device_id already on an active key (device_id_taken), a device_id in a PATCH, a field the route does not take (extra_forbidden), a dry_run that is not a boolean (bool_type)
429rate_limit_errorKeys made faster than the rate above: "Keys are being made faster than this workspace may: 20 a second, bursts of 200, 50,000 a day.", details.reason key_creation_rate, with Retry-After
529overloaded_errorKeys cannot be made right now, with Retry-After: send the same call, with the same Idempotency-Key, after it

The errors a Decisions-only key can meet on a decision, 403 key_scope_denied and 429 key_spend_cap_reached, are on Errors.

previousPOST /v1/uploadsnextKey usage

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. Make a key
  2. The key object
  3. List keys
  4. Change a key
  5. Revoke
  6. Errors