Skip to main content
Decisions (Beta)

Create Decision

Synchronously execute a structured judgment based on custom context (state) or recent Session context.

The Decision API is currently in Beta. Interface definitions, response structures, and behavior may change in subsequent versions. Follow documentation updates and verify compatibility before using it in production.
POST /api/v1/forward/decisions

Request headers

HeaderRequiredDescription
AuthorizationYesBearer <PAT or SAT>. Supports administrator and Identity-level SATs.
Content-TypeYesapplication/json.
Idempotency-KeyNoReuse the original value when retrying the same logical operation. After trimming leading and trailing whitespace, it must be 1–256 bytes, contain no control characters, and must not be supplied more than once.
No additional Beta request header is currently required. This endpoint does not accept query parameters.

Request body parameters

ParameterTypeRequiredDescription
stateobjectEither this or session_idCustom context for the judgment, supplied as a non-empty JSON object that may contain text, structured data, and other content. The top-level state.session_context field is reserved and must not be supplied.
session_idstringEither this or stateAn accessible, unarchived Session ID within the current authentication scope. 1–256 bytes, with no leading or trailing whitespace, control characters, or /, \\, ?, #.
questionsarrayYesList of questions to evaluate.
Exactly one of state and session_id must be present; passing null is not equivalent to omission. Field names are case-sensitive. Additional protocol fields such as model and identity_id are not supported.

Question structure

ParameterTypeRequiredDescription
typestringYeschoice or score.
namestringNoQuestion name. When supplied, it must be non-empty and unique within the request, at most 128 bytes, and contain no control characters.
instructionsstringYesNon-empty judgment instructions describing the objective and rules.
choicesarrayRequired for choice2–32 options. score questions must not contain this field.
choices[].valuestring or booleanYesCandidate value. Strings must be non-empty, and values within a question must be unique. Numbers and null are not supported.
choices[].descriptionstringNoThe option's meaning or selection criteria.
levelsarrayRequired for score2–32 scoring levels. choice questions must not contain this field.
levels[].labelstringYesNon-empty level name.
levels[].scorenumberYesA finite numeric value for the level, either an integer or a decimal.
levels[].descriptionstringNoThe criteria for this level.

Input limits

  • The request body must be a single UTF-8 JSON object no larger than 1 MiB.
  • JSON nesting must not exceed 16 levels, with no more than 1,000 items per object or array. Duplicate JSON keys are not allowed.
  • Numbers must be within the finite double-precision floating-point range. Strings must not contain control characters such as NUL; text content may contain newlines, carriage returns, and tabs.
  • Custom business fields are allowed within state. The protocol structures for requests, questions, options, and scoring levels accept only the fields listed above.
  • For context processing and budget rules, see Input modes.

Example request

Judge custom context

Generate a key once for the same operation, then keep the key and original request body unchanged for retries:
IDEMPOTENCY_KEY="$(uuidgen)"

curl --silent --show-error --fail-with-body -X POST \
  "https://api.qoder.com/api/v1/forward/decisions" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -d '{
    "state": {"message": "My issue is resolved."},
    "questions": [{
      "type": "choice",
      "name": "resolved",
      "instructions": "Has the user confirmed resolution?",
      "choices": [{"value": true}, {"value": false}]
    }]
  }'

Score Session context

curl --silent --show-error --fail-with-body -X POST \
  "https://api.qoder.com/api/v1/forward/decisions" \
  -H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "session_id": "sess_xxx",
    "questions": [{
      "type": "score",
      "name": "completion",
      "instructions": "Evaluate how completely the user request has been fulfilled.",
      "levels": [
        {"label": "Incomplete", "score": 0, "description": "The requested result is missing."},
        {"label": "Partial", "score": 0.5, "description": "Only part of the request is fulfilled."},
        {"label": "Complete", "score": 1, "description": "All requested results are provided."}
      ]
    }]
  }'

Example response

HTTP 200 OK (custom context example)
{
  "id": "dec_xxx",
  "session_id": null,
  "source": "api",
  "status": "completed",
  "questions": [{
    "type": "choice",
    "name": "resolved",
    "instructions": "Has the user confirmed resolution?",
    "choices": [{"value": true}, {"value": false}]
  }],
  "answers": [{"type": "choice", "name": "resolved", "value": true}],
  "context": {
    "mode": "state"
  },
  "error": null,
  "created_at": "2026-10-26T10:00:00Z",
  "completed_at": "2026-10-26T10:00:02Z"
}
For the complete fields, see Decision object. Choice questions return type: choice and value; scoring questions return type: score and score. status: completed indicates that the judgment is complete. Determine whether the business objective was achieved from the answers.

Idempotent retries

  • An idempotency key applies within the current authentication scope. Retries must retain the same authentication scope, key, and raw request body bytes. Even if the JSON meaning is unchanged, changing field order or whitespace is treated as a different request body.
  • Same key and same request body: return the original Decision if it succeeded, or the original failure error if it failed. Neither reruns the judgment.
  • If the original request is still executing, return 409 decision_in_progress, with decision_id in the error. Query its details later.
  • If the same key is used with a different request body, return 409 idempotency_key_reused.
  • Use a new key for a new judgment, including reevaluation using the latest Session context. Reusing a key does not reread history or update the original result.
Records have a retention period. Idempotent replay must not be used as permanent deduplication storage. If results need to be retained long-term, save the Decision ID and required results yourself.

Errors

HTTPCodeTrigger
400invalid_decision_inputInvalid input mode, questions, options, scoring levels, or idempotency key; duplicate JSON keys; exceeded structural limits; or unknown protocol fields.
400—Query parameters, duplicate idempotency headers, or an empty idempotency header were supplied.
401—Credentials are missing, invalid, or expired.
403—The current credentials lack required access permissions, or the Workspace configuration does not meet requirements.
404—The Session does not exist, is inaccessible or archived, or its Identity is disabled or deleted.
409idempotency_key_reusedThe same key is associated with a different request body.
409decision_in_progressThe judgment associated with the same key is still executing.
413—The request body exceeds 1 MiB.
422decision_context_too_largeJudgment input exceeds the budget, or the model service rejects the input size.
422decision_context_unavailableThe Session has no usable judgment context.
402decision_quota_exhaustedThe judgment quota is exhausted or restricted.
429decision_rate_limitedThe judgment service is rate-limited. If Retry-After is present, wait according to its value.
499decision_cancelledThe judgment request was cancelled. A disconnected client may not receive this response.
500decision_internal_error or no CodeInternal service error.
502decision_context_read_failedReading Session history failed or returned an invalid structure.
502decision_invalid_upstream_response, decision_upstream_errorThe judgment service returned an invalid result or encountered another upstream error.
503decision_upstream_unavailable or no CodeJudgment capability is temporarily unavailable for the current caller or environment.
504decision_timeoutThe judgment exceeded its execution time limit.

HTTP error responses

After a request is accepted and a record is created, execution failure responses usually include error.decision_id. Errors before acceptance, such as parameter validation or authentication failures, do not create a Decision.
{
  "type": "error",
  "request_id": "req_xxx",
  "error": {
    "type": "api_error",
    "code": "decision_timeout",
    "message": "Decision deadline exceeded.",
    "decision_id": "dec_xxx"
  }
}
request_id is returned when available for troubleshooting. error.type is the broad error category, and error.code is an optional business error code. Entry-point authentication errors may use a different response structure. Use error.decision_id to query the record. The detail endpoint returns HTTP 200 for a failed record with status: failed; failures from the create endpoint return the corresponding non-2xx HTTP status.