Saanora Platform documentation

Send a record, such as a support ticket, an agent conversation or an invoice, together with typed questions about it. Clara returns a probability for every option you defined, for every question, in one call. You call it over HTTPS with one API key and pay from prepaid credit.

What the API does

You describe a decision as questions with fixed options. Clara reads the record and answers each question with probabilities over those options. It never writes free text: every answer is one of your options, and the probabilities always sum to 1. That makes the result safe to branch on in code.

There are three question types:

TypeUse it forYou define (criteria)You get back
noulYes/no questionsOptional: {"true": ..., "false": ...} (or yes/no keys) describing each side. Optional threshold on the question, a number from 0 to 1.noul: the probability of yes. With a threshold, also threshold and decision (true when noul is at least the threshold).
choicePicking one option from a setAn object of option id → short description, 2 to 255 options.choice (the most likely option id), probabilities for every option and confidence (0 for a uniform spread, 1 for certain).
scoreRating on an ordered scaleAn array of levels, lowest first, at least 2.score (the expected level index), probabilities and legend keyed by level index, and confidence (the most likely level's probability).

A typical integration acts on its own when a probability is high, sends the middle band to a person and declines when it is low. One request can carry 1 to 32 questions on Tier 1 and 64 from Tier 2.

Your first request

You need an account, credit and an API key. The Quickstart covers all three. Then keep the key in an environment variable on your server:

bash
export SAANORA_API_KEY="sk_sa_..."

This request asks two questions about one customer message: a yes/no question with a threshold, and a choice between three options.

curl https://api.saanora.com/v1/decisions \
  -H "Authorization: Bearer $SAANORA_API_KEY" \
  -H "Content-Type: application/json" \
  --max-time 120 \
  -d '{
    "model": "clara-1",
    "state": "Order A-1042, delivered Oct 5. Customer writes: the blender arrived with a cracked jar. I want my money back, not a new one.",
    "questions": {
      "damaged": {
        "type": "noul",
        "instructions": "Does the customer say the item arrived damaged?",
        "threshold": 0.9
      },
      "wants": {
        "type": "choice",
        "instructions": "What does the customer want?",
        "criteria": {
          "refund": "Their money back",
          "replacement": "A new item sent to them",
          "other": "Anything else"
        }
      }
    }
  }'

The response carries one answer per question, keyed by the ids you chose (damaged, wants):

200 OK
{
  "id": "dec_3b9e71c04f2a8d65e1c07b94",
  "object": "decision",
  "created": 1792491003,
  "model": "clara-1",
  "mode": "fast",
  "answers": {
    "damaged": { "type": "noul", "noul": 0.98, "threshold": 0.9, "decision": true },
    "wants": {
      "type": "choice",
      "choice": "refund",
      "probabilities": { "refund": 0.94, "replacement": 0.04, "other": 0.02 },
      "confidence": 0.91
    }
  },
  "usage": { "input_tokens": 170, "decisions": 2, "cost_usd": 0.000085 },
  "latency_ms": 88.7
}
FieldMeaning
idThe decision id, starting with dec_.
objectAlways "decision".
createdWhen the decision was made, in Unix seconds.
model, modeThe model that answered and the mode it ran in: fast (the default) or consistent.
answersOne answer per question, in the shape for its type. Here damaged.noul is 0.98, above the 0.9 threshold, so decision is true. wants.choice is refund with probability 0.94 out of three options, so confidence is (0.94 − 1/3) / (1 − 1/3) = 0.91.
usage.input_tokensBilled input tokens. The same number counts toward your tokens-per-minute limit.
usage.decisionsThe number of questions answered.
usage.cost_usdExactly what was deducted from your credit.
latency_msTime spent in the model, in milliseconds. The saanora-processing-ms header has the total time in the platform.
The first call after a quiet period. Clara scales down when idle, so after a quiet period it needs about a minute to start: the first request waits about 60–80 seconds and is then answered. Consistent mode follows about 50 seconds later; until then a consistent request gets 503 model_warming_up, never charged, with a Retry-After header saying how many seconds to wait. Retry after that wait, and keep a client timeout of 120 seconds. Later requests are fast. The retry loop on Errors handles it for you.

How a request flows

Every call to POST /v1/decisions (or POST /v1/systemone) goes through the same six steps. Credit moves at two of them: a hold before the model runs and the exact charge after it.

  1. 01
    API key
    Identifies your project and organization
  2. 02
    Request
    Validated and checked against your limits
  3. 03
    Hold
    Worst-case cost reserved from credit
  4. 04
    Model
    Clara answers every question
  5. 05
    Exact charge
    Only the tokens read are billed
  6. 06
    Response
    Answers, usage and headers
StepWhat happensIf it fails
1. API keyThe gateway reads the key from Authorization: Bearer sk_sa_... (or X-API-Key) and finds its project and organization. Key lookups are cached for 60 seconds, so a revoked key stops working within 60 seconds.401 missing_api_key, 401 invalid_api_key, 503 auth_unavailable; 402 insufficient_credit on Tier 0, which is sign-up only (API access starts at Tier 1)
2. RequestThe body must be valid JSON of at most 1 MB with a model, a state and valid questions within your tier's question limit. Then your organization's requests-per-minute and tokens-per-minute limits and the project's monthly spend limit are checked.413 request_too_large; 400 invalid_json, missing_model, missing_state, missing_questions or wrong_endpoint; 404 model_not_found; 422 too_many_questions, invalid_question_type, invalid_criteria or invalid_mode; 429 rate_limit_exceeded (with Retry-After); 429 project_spend_limit; 503 catalog_unavailable
3. HoldA hold covering the worst-case cost of the request is placed on your organization's credit. If the credit cannot cover it, nothing runs.402 insufficient_credit, 503 billing_unavailable
4. ModelClara reads the record and answers every question, in fast or consistent mode.503 model_warming_up while consistent mode starts after a quiet period (with Retry-After), 502 model_unavailable, 400 or 422 invalid_request when the model rejects the request
5. Exact chargeOnly the exact cost is deducted: billed input tokens at the model's input price. Output costs $0 and there is no per-decision fee. The rest of the hold returns to your balance.Not charged if the model step failed.
6. ResponseYou receive the answers and usage, plus headers: x-request-id, your remaining requests and tokens (x-ratelimit-*) and saanora-processing-ms.Errors carry x-request-id too.
Failed requests are free. A request that fails at any step costs nothing and does not count toward your tokens-per-minute limit. Because the hold covers the worst case, a request can get 402 insufficient_credit while your balance is still above what it would finally have cost: keep some headroom.

Core objects

ObjectWhat it isGood to know
OrganizationOwns the credit, the members and the rate-limit tier. Every user gets a personal organization when they sign up.Invite teammates by email. Each member has one role: owner, admin, developer, billing or reader. An organization always keeps at least one owner.
ProjectGroups API keys, usage and an optional monthly spend limit (UTC month). New organizations start with a Default project.Projects share the organization's credit and rate limits. Use one per environment or product. Archiving a project revokes its keys.
API keyA secret starting with sk_sa_ that authenticates requests. It belongs to exactly one project.Shown once when created and stored only as a SHA-256 hash. Keep it on your server. A revoked key stops working within 60 seconds.
ModelWhat answers the request, chosen per request with the model field.All models use the same keys, credit and limits. GET /v1/models lists the live ones.
CreditThe organization's prepaid balance in US dollars.Top-ups start at $5. Credit never expires and is shared by all projects. Polar is the merchant of record and handles checkout, taxes, receipts and invoices.
TierThe organization's limits: requests per minute, tokens per minute and questions per request.New organizations start on Tier 0, which is sign-up only: no API access. Your first top-up, from $5, moves you to Tier 1 at once (300 requests and 300K tokens per minute, 32 questions per request). Higher tiers apply automatically the moment both your total paid and the days since your first payment reach the next tier's bar.
Your records are not stored. The state and questions you send are processed in memory and never written to the database, so they are never used for training. Saanora stores only request metadata such as time, project, key, model, token count, cost and request id. See Data handling.

Base URL and endpoints

All endpoints are served from https://api.saanora.com over HTTPS. Requests and responses are JSON.

EndpointUse it for
POST /v1/decisionsAsk a model questions about a record. model is required.
POST /v1/systemoneThe same request body for clients written for the open System One format, such as JevBench. model is optional and defaults to clara-1.
GET /v1/modelsList the models your key can call right now.

Conventions

401 Unauthorized
{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "invalid or revoked API key",
    "param": null
  },
  "request_id": "req_5c1e9a0b7d3f42e8a61b9c04"
}

Models

ModelWhat it doesStatusInput / 1MOutput / 1M
Clara clara-1Typed decisions: a probability for every option you defineLive$0.50$0
Mark mark-1Language model behind Saanora ChatComing soonat launchat launch

Clara (clara-1) is Saanora's frontier decision model. It scores 93.55% on AgentDecisionBench tool routing and 94.9% on a held-out customer-service yes/no set, answers five questions about one record in about 0.1 s, and returns 0% malformed answers. It works in English only.

Mark (mark-1), the language model behind Saanora Chat, is coming soon. Until it opens, requests to it return 404 model_not_found.

To see which models your key can call, list them:

bash
curl https://api.saanora.com/v1/models \
  -H "Authorization: Bearer $SAANORA_API_KEY"
200 OK
{
  "object": "list",
  "data": [
    { "id": "clara-1", "object": "model", "owned_by": "saanora", "kind": "decision", "status": "live" }
  ]
}

Benchmarks, specifications and known limitations are on Models. Before you automate on Clara's answers, check them against a few hundred of your own labelled records.

What a request costs

Clara costs $0.50 per 1M input tokens. Output is $0 and there is no per-decision fee, so a request costs usage.input_tokens × $0.50 / 1,000,000. The example above read 170 tokens and cost $0.000085. The smallest top-up, $5, buys 10M input tokens, about 58,000 requests like it.

The mode changes what is billed:

Where to go next

If you want toRead
Make your first request step by stepQuickstart
Send, store, rotate or revoke API keysAuthentication
Look up every field, header and answer shapeAPI reference
Compare models, benchmarks and limitationsModels
Copy a complete recipe for triage, routing, moderation or invoicesGuides
Write better questions, pick thresholds and choose a modeBest practices
Handle an error code or retry safelyErrors
See your limits and how tiers riseRate limits
Invite your team, separate environments, cap spendOrganizations and projects
Add credit, find invoices, understand chargesBilling and credit
Know exactly what is stored about each requestData handling
Need help. Write to support@saanora.com with the x-request-id of any request you have a question about.