Quickstart
Create an API key in the Finic portal, send your first decision and read the answers.
There is no official SDK. Grayson is one HTTPS endpoint that takes and returns JSON, so any HTTP client works. The examples below use curl, Python with requests, and TypeScript with fetch (Node.js 18 or later).
Create an API key
Sign in to the Finic portal and create a key at portal.finic.ai/keys. The key starts with gsk_ and is shown only once, when you create it, so copy it then.
Keep it in an environment variable rather than in code:
export GRAYSON_API_KEY=gsk_…See Authentication for storing, rotating and revoking keys.
Send a decision
This request describes an account where the SIM changed, the password was reset over SMS, a new device logged in and a new payee received $2,400, all within ten minutes. It asks three questions: a noul (yes/no), a score and a choice.
curl https://api.finic.ai/v1/decide \
-H "Authorization: Bearer $GRAYSON_API_KEY" \
-H "Content-Type: application/json" \
--data @- <<'EOF'
{
"model": "grayson-1",
"state": {
"customer": { "id": "cus_4821", "customer_since": "2021-03-02" },
"events": [
{ "ts": "2026-09-14T15:02:11Z", "type": "sim_change", "detail": "Carrier reports a new SIM for the phone number on file" },
{ "ts": "2026-09-14T15:07:52Z", "type": "password_reset", "channel": "sms" },
{ "ts": "2026-09-14T15:09:40Z", "type": "login", "new_device": true },
{ "ts": "2026-09-14T15:12:03Z", "type": "p2p_out", "amount_usd": 2400.0, "payee_added": "2026-09-14T15:11:20Z" }
]
},
"questions": {
"is_fraud": {
"type": "noul",
"instructions": "Is the outbound P2P payment fraudulent?"
},
"ato_likelihood": {
"type": "score",
"instructions": "How likely is it that this account has been taken over?",
"levels": ["Very unlikely (under 10%)", "Unlikely (10-40%)", "Uncertain (40-60%)", "Likely (60-90%)", "Very likely (over 90%)"]
},
"action": {
"type": "choice",
"instructions": "What should happen to the outbound P2P payment?",
"options": {
"release": "Release the payment",
"hold": "Hold the payment and verify the customer through a channel other than the phone number",
"block": "Block the payment and lock the account"
}
}
}
}
EOFRead the answers
A successful call returns 200 with one answer per question, under the question's name. Probabilities are shortened to four decimals here; responses carry full precision.
{
"id": "dec_01J9QK2V7R4TBX8M3N5P6Q7R8S",
"model": "grayson-1",
"answers": {
"is_fraud": { "type": "noul", "value": true, "probability": 0.9137 },
"ato_likelihood": {
"type": "score",
"value": 3.355,
"level": "Very likely (over 90%)",
"probabilities": [0.0112, 0.0306, 0.0871, 0.3342, 0.5369]
},
"action": {
"type": "choice",
"value": "hold",
"probabilities": { "release": 0.0418, "hold": 0.8127, "block": 0.1455 }
}
},
"usage": { "input_tokens": 322 }
}is_fraudis anoul, a yes/no question.probabilityis P(yes).valueistruebecause the probability is at least 0.5, but your code should compareprobabilitywith a threshold you choose.ato_likelihoodis a score.probabilitieshas one entry per level, lowest first.levelis the most likely level, andvalueis the expected value on the default scale of 0 to 4: 0 × 0.0112 + 1 × 0.0306 + 2 × 0.0871 + 3 × 0.3342 + 4 × 0.5369 = 3.355.actionis a choice.probabilitiessums to 1 across the options, andvalueis the most likely option's key.usage.input_tokensis the size of the request as the model read it. The limit is 32,768.
Every response from the API, including errors, has an X-Request-Id header. Log it with the answers; support asks for it.