JavaScript guide

OpenAI Decisions API in JavaScript

OpenAI has not published an SDK for its Decisions API — there is no client.decisions.create to copy. This page shows working JavaScript for this site's endpoint — a callable OpenAI Decisions API alternative that serves decisions-1 and follows the same constrained-decision pattern.

Updated

Make the call

One POST to /api/v1/decisions with a Bearer key. The body is model, state, and questions — 1 to 6 questions, each typed noul, choice, or score. Set DECISIONS_API_KEY to a key from the dashboard.

Use fetch — the same API in Node 18+, Deno, and browsers. Keep a timeout on every call (AbortSignal.timeout); a hung decision should fail fast, not stall the pipeline.

JavaScript

const res = await fetch('https://decisions-api.net/api/v1/decisions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'decisions-1',
    state: 'I was charged twice for my subscription this morning.',
    questions: {
      refund: {
        type: 'noul',
        instructions: 'Is the customer asking for money back?',
      },
    },
  }),
})
const { answers } = await res.json()
console.log(answers.refund.noul)

Read the probabilities

answers comes back keyed by your question ids. A noul answer is the probability the statement is true. A choice answer carries the winning choice, a probability for every option, and a confidence value — use confidence, not just the winner, to decide whether to auto-act.

JavaScript

// noul: probability the statement is true
if (answers.refund.noul >= 0.8) routeToRefunds()

// choice: winning label + per-option probabilities + confidence
const team = answers.team
console.log(team.choice, team.probabilities, team.confidence)

Timeouts and retries

429 and 502 are worth a short backoff retry — failed calls are not billed. 402 means the balance is empty: top up, do not retry. 422 is a validation error; the message names the field, so fix the body instead of retrying.

JavaScript

async function decide(body, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    const res = await fetch('https://decisions-api.net/api/v1/decisions', {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.DECISIONS_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
      signal: AbortSignal.timeout(30000),
    })
    if (res.status === 429 || res.status === 502) {
      await new Promise(r => setTimeout(r, 2 ** i * 1000))
      continue
    }
    if (res.status === 402) throw new Error('out of credits')
    if (!res.ok) throw new Error(`decision call failed: ${res.status}`)
    return (await res.json()).answers
  }
  throw new Error('decision call failed')

Keep the provider behind one function

Callers should see a function that takes text and returns a label — not HTTP details. When OpenAI opens its Decisions API you swap the inside of decide() and keep every call site unchanged. The question text, options, and thresholds all carry over.

JavaScript

// Keep the decision behind one function. Swap the HTTP layer
// when OpenAI publishes its schema — callers never change.
export async function routeTicket(text) {
  const answers = await decide({
    model: 'decisions-1',
    state: text,
    questions: {
      team: {
        type: 'choice',
        instructions: 'Which team should own this ticket?',
        criteria: {
          payments: 'Checkout or billing.',
          frontend: 'Rendering or browser behavior.',
          account: 'Login or permissions.',
        },
      },
    },
  })
  const team = answers.team
  return team.confidence >= 0.7 ? team.choice : 'triage'
}

FAQ

Is there an official OpenAI SDK example for the Decisions API?

No. OpenAI has not published SDK methods or a request schema for its Decisions API — anything showing client.decisions.create is invented. This page uses plain HTTP, which is what any provider SDK would wrap anyway.

Can I use axios or an HTTP client instead of fetch?

Yes — the endpoint is a plain HTTPS POST. Axios, undici, or got work the same; keep the timeout and status handling identical.

How do I send structured context?

state accepts a JSON object or array, not just a string — pass dicts directly in the json body and the model reads them as context.

Run a decision from the browser

Skip the setup — run a real call in the playground with 2 free credits for new visitors.