همه صفحه‌ها

تصمیم‌ها (آلفا)

POST /v1/alpha/decisions یک وضعیت و مجموعه‌ای از پرسش‌های نوع‌دار می‌گیرد و برای هر پرسش یک پاسخ نوع‌دار برمی‌گرداند: یک احتمال (noul)، یک گزینهٔ برچسب‌دار (choice)، یا جایگاهی پیوسته روی نردبانی که خودتان می‌دهید (score). متن آزاد و استریم در کار نیست، پس کد شما مستقیماً روی پاسخ شرط می‌گذارد. تنها ورودی محاسبه می‌شود و خروجی رایگان است؛ هزینهٔ دقیق در usage.cost همان پاسخ برمی‌گردد — این فیلد در طرح‌وارهٔ ارائه‌دهنده اختیاری است، پس پاسخی که آن را نداشته باشد به‌جای صفر روی مبلغ رزروشده تسویه می‌شود. واژهٔ alpha در مسیر هشدار خود ارائه‌دهنده است: شکل این سرویس هنوز ممکن است تغییر کند.

POST/v1/alpha/decisionsاحراز هویت Bearer

Ask a decisions model typed questions

ALPHA. Send some state plus a map of typed questions, get one typed answer per question. Answers are values your code can branch on directly — never prose, and never streamed.

Supported models: typesafe/jev-1.13 (pinned) and ~typesafe/jev-latest (always resolves to the newest model in the Jev family). The tilde is part of the id upstream; Hormouz also accepts typesafe/jev-latest and jev-latest and canonicalises them for you. See GET /v1/models — note decisions models are deliberately absent from that list, because no OpenAI-compatible client can call them; browse them in the dashboard catalogue instead.

Three question types.

  • noul — returns noul, the probability in [0,1] that the condition holds. Gate an action on whatever threshold you choose. criteria is optional; when present it needs both true and false.
  • choice — picks one of the labels in criteria and returns it as choice, plus confidence and a probabilities map so a close call is visible rather than hidden. criteria is required and is an object of label -> description.
  • score — places the input on the ORDERED ladder you supply in criteria (an array, lowest first) and returns a CONTINUOUS score, plus legend mapping each index to its label. 1.99 means "almost entirely the third rung". criteria is required.

Billing: input tokens only — output is free. A hold is placed before the upstream call, sized from the size of the request; the exact cost from usage.cost is settled inline the moment the response arrives, and you are never charged more than the hold. There is no async settlement. usage.cost is optional in the provider's schema; a response that omits it is priced from its own token counts, which that schema does require, so the charge is the same either way.

Limits. The request body is capped at 1 MiB on this endpoint — lower than the 50 MiB the chat routes allow, because a decisions body is state plus a questions map. Repeating a top-level key is refused with 400: our parser resolves a duplicate to the first occurrence and the provider to the last, so we reject rather than price a body we cannot read the same way it will. A provider answer over 1 MiB is refused with 502 UPSTREAM_RESPONSE_TOO_LARGE, kept distinct from a plain UPSTREAM_ERROR because the answer was already generated and a blind retry costs money and fails identically.

Alpha: the request and response shapes are passed through from the provider unchanged, which is what lets you move existing code here by swapping the base URL — and also means they may change while this is in alpha. Pin a version and add a contract test before depending on it in production.

بدنه درخواستالزامی

فیلدنوعتوضیح
modelالزامیstring

Model id. Accepts typesafe/jev-1.13, ~typesafe/jev-latest, typesafe/jev-latest or jev-latest.

نمونه: typesafe/jev-1.13

stateالزامیobject

The content to judge — any JSON value. Typically a string, or an object of related context. Required, but may be empty: "", {}, [], 0 and false are all accepted, because each is something you can legitimately ask questions about. Only an ABSENT state is rejected.

questionsالزامیobject

Map of your own question name to a question. The names you choose are the keys you read back out of answers.

session_idstring

Optional grouping id for related requests, forwarded upstream as part of the body and used there for observability grouping. Hormouz neither reads nor strips it. Do not put anything sensitive in it.

userstring

Optional end-user identifier, forwarded upstream as part of the body. Hormouz neither reads nor strips it.

نمونه

پاسخ‌ها

200

One typed answer per question.

{
  "id": "gen-dec-1789738314-X5e5eKGQdvR9rblyX250",
  "model": "typesafe/jev-1.13-20260917",
  "provider": "TypeSafe",
  "answers": {
    "is_bug": {
      "type": "noul",
      "noul": 0.96
    },
    "team": {
      "type": "choice",
      "choice": "payments",
      "confidence": 0.75,
      "probabilities": {
        "account": 0,
        "frontend": 0.16,
        "payments": 0.84
      }
    },
    "urgency": {
      "type": "score",
      "score": 1.99,
      "confidence": 0.99,
      "legend": {
        "0": "Can wait for the next release",
        "1": "Should be fixed this week",
        "2": "Blocking revenue right now"
      },
      "probabilities": {
        "0": 0,
        "1": 0.01,
        "2": 0.99
      }
    }
  },
  "usage": {
    "cost": 0.000019992,
    "input_tokens": 476,
    "output_tokens": 70
  }
}
400

The request body or query parameters are invalid. Check the error.code and error.message fields for details. Codes the gateway emits at 400:

  • BAD_REQUEST: generic malformed JSON / missing required field.
  • INVALID_TOOLS: the tools array, plugins field, or model's :online suffix uses an unsupported shape. The response names the offender and links to the supported form. See the dedicated InvalidTools response below for the three triggers and migration hints.
  • UNSUPPORTED_TOOL: a built-in tool (file_search, code_interpreter, computer_use, mcp) whose pricing dimension is not yet wired into the gateway hold estimator.
  • INVALID_AUDIO_FORMAT: input_audio.format value is not in the supported set. The envelope lists every supported codec name. The gateway accepts both short names (wav, webm) and full MIME aliases (audio/wav, audio/webm); anything else fails fast at admission. See API guide §8b.
  • AUDIO_NOT_SUPPORTED_ON_RESPONSES: input_audio content part sent to POST /v1/responses. The Responses API has no audio content type today; resend to POST /v1/chat/completions instead.
401

Authentication failed. Either the Authorization header is missing, the key format is invalid, or the key doesn't match any active account.

{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Authentication required",
    "status": 401
  }
}
402

Insufficient credits.

409

Idempotency key conflict: you sent the same Idempotency-Key with a different request body.

413

Request body exceeded the 1 MiB limit for this endpoint.

429

Too many requests. Back off and retry after a short delay. Check the Retry-After header for guidance.

499

Your HTTP client cancelled the request before the gateway finished. No charge: the hold has been released. The most common cause is a 30 s default client timeout against a model whose p95 latency is 45-60 s; bump your client timeout to 120 s.

Retries with the same Idempotency-Key will replay this 499 forever (the prior outcome is "you cancelled"). For an actual re-attempt, mint a fresh Idempotency-Key. See docs/CUSTOMER_ERROR_HANDLING.md §3 for the full contract.

{
  "error": {
    "code": "CLIENT_CLOSED",
    "message": "Client disconnected before response",
    "status": 499
  }
}
500

Unexpected server error. Please retry with exponential backoff. If the issue persists, contact your admin.

502

The upstream AI provider is temporarily unavailable. Retry with exponential backoff (1s, 2s, 4s) using the same Idempotency-Key: if the upstream actually completed the work and only the response failed, the gateway replays the cached success without a second charge. Holds are released automatically on upstream failures.

503

The upstream AI provider is temporarily unavailable. Retry with exponential backoff (1s, 2s, 4s) using the same Idempotency-Key: if the upstream actually completed the work and only the response failed, the gateway replays the cached success without a second charge. Holds are released automatically on upstream failures.

504

The gateway's 120 s upstream deadline elapsed before the upstream provider produced a response. Retry with the same Idempotency-Key so a delayed-but-eventually-successful upstream call can be replayed instead of re-charged. Consider switching to a faster model or capping max_tokens if this recurs.

{
  "error": {
    "code": "UPSTREAM_TIMEOUT",
    "message": "Upstream did not respond before timeout",
    "status": 504
  }
}

به‌روزرسانی: 2026-10-13