Create a decision

POST /v1/decide answers every question in the request about one state.

POST https://api.finic.ai/v1/decide

Takes a state and a set of named, typed questions, and returns a probability distribution for every question. For background, see State, Questions and Answers and probabilities.

Headers

HeaderValue
AuthorizationRequired. Bearer gsk_…. See Authentication
Content-Typeapplication/json

Request body

FieldTypeDescription
modelstringRequired. grayson-1. An unknown model returns 404 model_not_found
statestring, object or arrayRequired. Everything the questions are about. No schema. A string must not be blank. Objects and arrays are read as compact JSON, with key order kept
questionsobjectRequired. 1–128 questions, keyed by name. Names match ^[A-Za-z_][A-Za-z0-9_]{0,63}$

Unknown fields are rejected, at the top level and in every question.

Question

FieldTypeApplies toDescription
typestringAllRequired. noul (yes/no), choice, multi_choice or score
instructionsstringAllRequired. The question, in words. Must not be blank
optionsobjectchoice, multi_choiceRequired. 2–255 entries of key: description. Keys match the name pattern. Descriptions must not be blank and must be unique, ignoring case and whitespace. A choice reads them together, in order; a multi_choice asks about each one separately
levelsarray of stringsscoreRequired. 2–32 levels, lowest first. Must not be blank and must be unique, ignoring case and whitespace
valuesarray of numbersscoreOptional. One finite number per level, strictly increasing. Defaults to 0, 1, …, K−1

Response

A successful call returns 200 with:

FieldTypeDescription
idstringThe decision's id, starting with dec_
modelstringThe model that answered, grayson-1
answersobjectOne answer per question, keyed by question name
usage.input_tokensintegerTokens the model read. See How tokens are counted

Every response from the API, including errors, has an X-Request-Id header. Include it when you contact support.

Answer

Every answer has type, repeating its question's type, plus these fields:

TypeFieldTypeDescription
noulvaluebooleanprobability >= 0.5
probabilitynumberP(yes), from 0 to 1
choicevaluestringThe most likely option's key
probabilitiesobjectOne entry per option, in request order, summing to 1
multi_choicevaluesarray of stringsKeys of the options with probability of at least 0.5, in request order
probabilitiesobjectP(option applies) for each option, in request order. Independent, so they need not sum to 1
scorevaluenumberThe expected value: the sum of P(level) × the level's value
levelstringThe most likely level
probabilitiesarray of numbersOne entry per level, lowest first, summing to 1

Probabilities are not rounded. Nothing is generated: a response has no text beyond these fields.

Example

Save the request body below as request.json, then send it:

curl https://api.finic.ai/v1/decide \
  -H "Authorization: Bearer $GRAYSON_API_KEY" \
  -H "Content-Type: application/json" \
  --data @request.json
{
  "model": "grayson-1",
  "state": {
    "account": {
      "id": "acct_8812",
      "opened": "2026-08-30",
      "kyc": {
        "name": "Dana Ruiz",
        "dob": "1994-03-11",
        "ssn_last4": "4410"
      }
    },
    "events": [
      {
        "ts": "2026-09-20T02:14:09Z",
        "type": "login",
        "ip": "203.0.113.4",
        "device_id": "d_77a1",
        "new_device": true
      },
      {
        "ts": "2026-09-20T02:16:40Z",
        "type": "email_change",
        "old": "dana.r@example.com",
        "new": "dr8812@example.net"
      },
      {
        "ts": "2026-09-20T02:21:03Z",
        "type": "ach_out",
        "amount": 4900.0,
        "counterparty": "External bank account x9921",
        "memo": "rent"
      }
    ],
    "support_notes": "Customer called 9/21 saying they never changed their email and don't recognize the transfer."
  },
  "questions": {
    "is_fraud": {
      "type": "noul",
      "instructions": "Is this account engaged in or the victim of fraud?"
    },
    "ato_signs": {
      "type": "noul",
      "instructions": "Are there signs of account takeover?"
    },
    "primary_typology": {
      "type": "choice",
      "instructions": "What is the most likely primary fraud typology?",
      "options": {
        "ato": "Account takeover",
        "synthetic_id": "Synthetic identity",
        "mule": "Money mule activity",
        "first_party": "First-party / bust-out",
        "none": "No fraud indicated"
      }
    },
    "typologies_present": {
      "type": "multi_choice",
      "instructions": "Which of these fraud typologies are present on this account?",
      "options": {
        "ato": "Account takeover",
        "synthetic_id": "Synthetic identity",
        "mule": "Money mule activity",
        "first_party": "First-party / bust-out",
        "scam": "Authorized push payment scam"
      }
    },
    "risk": {
      "type": "score",
      "instructions": "How risky is the outbound ACH transfer?",
      "levels": [
        "very low",
        "low",
        "medium",
        "high",
        "very high"
      ]
    }
  }
}

The response, with probabilities shortened to two decimals (responses carry full precision):

{
  "id": "dec_01J8Z4Q7XK3MZ6T2W9D5HC0N4E",
  "model": "grayson-1",
  "answers": {
    "is_fraud": {
      "type": "noul",
      "value": true,
      "probability": 0.92
    },
    "ato_signs": {
      "type": "noul",
      "value": true,
      "probability": 0.94
    },
    "primary_typology": {
      "type": "choice",
      "value": "ato",
      "probabilities": {
        "ato": 0.88,
        "synthetic_id": 0.02,
        "mule": 0.05,
        "first_party": 0.03,
        "none": 0.02
      }
    },
    "typologies_present": {
      "type": "multi_choice",
      "values": [
        "ato",
        "mule"
      ],
      "probabilities": {
        "ato": 0.93,
        "synthetic_id": 0.04,
        "mule": 0.61,
        "first_party": 0.03,
        "scam": 0.07
      }
    },
    "risk": {
      "type": "score",
      "value": 3.46,
      "level": "very high",
      "probabilities": [
        0.01,
        0.02,
        0.07,
        0.3,
        0.6
      ]
    }
  },
  "usage": {
    "input_tokens": 587
  }
}

risk.value is the expected value on the default scale of 0 to 4: 0 × 0.01 + 1 × 0.02 + 2 × 0.07 + 3 × 0.3 + 4 × 0.6 = 3.46.

On this page