Skip to main content
The Decisions API answers a set of typed questions over the same context. Instead of free-form text, it returns a probability, one of a named set of options, or a score on an ordered scale, so a caller can branch on the result without parsing prose. Use the same each::labs API key and base URL as the rest of each::api:
The Decisions API is in alpha. Its request and response contract may change without notice while it is stabilized, so avoid depending on it in production yet. Contact us if you want to build against it.

Model and routing

Send one of the supported model IDs below as the model. each::labs routes the request through the LLM Router to OpenRouter. You call a single each::labs endpoint; provider selection and credentials stay on our side, and usage is billed to your each::labs account. Unlike chat completions, this is not an OpenAI-compatible operation and has no corresponding OpenAI SDK method. Call it directly over HTTP.

Supported models

The list of decision models changes as models are added or retired, so read it from the API instead of hard-coding it:
Every id in the response is accepted as model. Use it exactly as returned. The examples below use typesafe/jev-1.13; replace it with another listed ID to select that model.

Endpoint

A request is answered synchronously: one call evaluates every question and returns the answers in the response body. There is no prediction to poll.

Authentication

Pass a standard API key as a Bearer token:

Request body

The body takes model, state, questions, and an optional images field. Any other field is rejected. Each question is an object with a type, instructions, and — depending on the type — criteria: instructions and every criteria value accept a string, an object, or an array. The response preserves your question names as the keys of answers.
Streaming, asynchronous mode, provider overrides, webhooks, and client-supplied metadata or source are not supported on this endpoint. For asynchronous runs and webhooks, run Decisions as a model instead. Sending them — or an X-Provider or webhook header — returns 400. Organization, user, execution, and source identity are always taken from the authenticated key.

Images

Models that read images also evaluate images sent with the request. Pass them in images. Each entry can be an image URL, a base64 data URL, or plain base64:
each::labs downloads URLs and sends every image to the model as a base64 data URL. You can also put images inside a state array as image_url items; text items are plain strings:
The url can be an image URL, a base64 data URL, or plain base64. each::labs also accepts these shapes and converts them before calling the model:
  • A Responses-style part: { "type": "input_image", "image_url": "https://..." }.
  • image_url given as a plain string instead of an object.
  • An image part nested inside an object, such as "state": { "photo": { "type": "image_url", ... } }. The image moves to its own state item, and [image 1] is left in its place so your text can still refer to it.
  • Send state as a JSON array, not as a string that contains JSON. A string is read as text, so the model never sees the image and the base64 is billed as input tokens. Such a request returns 400.
  • Images must be PNG, JPEG, or WebP. Send up to 16 images per request, each under 5 MB and 12 MB in total. A URL must be public http or https.
  • Only some decision models read images, for example cloudflare/clef, cloudflare/clef-flash, typesafe/jev-1.13, and liquid/d1. A text-only model reads the image as text. Model limits also apply: Clef works best with images under about 300 KB. Jev accepts PNG and JPEG with each side between 256 and 1568 px and 78,400 to 2,458,624 px in total; smaller images return 400.

Example

Response

Answer fields

Every answer carries the question’s type. The remaining fields depend on it:

Usage

When the upstream returns a decision id, it is included in the response.

Run as a model

Decisions is also available as the eachlabs-decisions model, so you can run it like any other each::labs model: through POST /v1/prediction, in the playground, and as a step in a workflow. The input takes the same model, state, questions, and images fields as the request body above. In the playground, upload files in the Images field.
The call returns a prediction ID. Poll GET /v1/prediction/{id}, or pass a webhook_url, until status is success. The output has the same answers, model, and usage fields as a direct response:
An unsupported input.model returns 400 with a message naming the ID.

In a workflow

Add an eachlabs-decisions model step, then branch on or pass along its answers with a $. reference to $.<step_id>.primary.answers.<question>:
A later step reads the selected option with $.decide.primary.answers.color.choice.

Error responses

Errors use the same shape as the rest of each::api:
Last modified on October 21, 2026