Quickstart (v2)

From zero to an explained prediction in about five minutes โ€” no signup. Every call below runs against the live read-only sandbox (the aito-demo dataset as rep2 collections). Copy, paste, run.

  • Base URL: https://shared.aito.ai/db/aito-demo/env/v2/api/v2/
  • Read key: yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi (public, read-only)

1. Run your first query

A _query filters and projects rows โ€” the same from / where / select you'll later use as evidence for inference.

curl -X POST \
  'https://shared.aito.ai/db/aito-demo/env/v2/api/v2/_query' \
  -H 'x-api-key: yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi' \
  -H 'Content-Type: application/json' \
  -d '{ "from": "products", "where": { "name": { "$match": "milk" } },
        "limit": 2, "select": ["name", "price"] }'
{ "offset": 0, "total": 6, "hits": [
  { "name": "Pirkka Finnish semi-skimmed milk 1l", "price": 0.81 },
  { "name": "Pirkka Finnish nonfat milk 1l", "price": 0.75 } ] }

2. Make your first prediction

_predict ranks the values of a field by probability, conditioned on the evidence in where. Here: route an invoice to a GL account from its text.

curl -X POST \
  'https://shared.aito.ai/db/aito-demo/env/v2/api/v2/_predict' \
  -H 'x-api-key: yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi' \
  -H 'Content-Type: application/json' \
  -d '{ "from": "invoices", "where": { "Description": { "$match": "cloud services" } },
        "predict": "GLCode", "select": ["$value", "$p"], "limit": 3 }'
{ "offset": 0, "total": 10, "hits": [
  { "$p": 0.833, "$value": "E002" },
  { "$p": 0.044, "$value": "R001" },
  { "$p": 0.034, "$value": "E001" } ] }

total is 10: every GL account is a candidate, and limit only decides how many come back. The evidence in where changes each account's probability; it never removes accounts โ€” see Predict: candidates and $f.

E002 at 83% is a number you can act on: set a threshold ($p > 0.8 โ†’ auto-post, anything lower โ†’ a person). On this invoice table the probabilities are conservative: measured with _evaluate on 26 held-out invoices, predictions made at about 82% confidence were right 100% of the time โ€” Aito under-states rather than over-states its confidence here. That is a small sample; measure your own data the same way before you pick a threshold.

The same call from Python

The Python SDK ships a v2 client (available since aitoai 0.7.0):

pip install aitoai
from aito.v2 import Client

client = Client('https://shared.aito.ai/db/aito-demo',
                'yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi', env='v2')

res = client.predict(from_table='invoices',
                     where={'Description': {'$match': 'cloud services'}},
                     predict='GLCode', limit=3)
print(res.total)
for hit in res:
    print(hit.value, round(hit.probability, 3))
10
E002 0.833
R001 0.044
E001 0.034

3. See why

Add "$why" to select and every candidate carries its factor tree โ€” the base rate, the normalizers, and the lift each piece of evidence contributed.

curl -X POST \
  'https://shared.aito.ai/db/aito-demo/env/v2/api/v2/_predict' \
  -H 'x-api-key: yg4rTlXkqDzm4y8gPeY75HCKaNwfbTQ2si64ONTi' \
  -H 'Content-Type: application/json' \
  -d '{ "from": "invoices", "where": { "Description": { "$match": "cloud services" } },
        "predict": "GLCode", "select": ["$value", "$p", "$why"], "limit": 1 }'
{
  "offset": 0,
  "total": 10,
  "hits": [
    {
      "$p": 0.833,
      "$value": "E002",
      "$why": {
        "type": "product",
        "factors": [
          {
            "type": "baseP",
            "value": 0.1081,
            "proposition": {
              "GLCode": {
                "$has": "E002"
              }
            }
          },
          {
            "type": "product",
            "factors": [
              {
                "type": "normalizer",
                "name": "exclusiveness",
                "value": 1.0048
              },
              {
                "type": "normalizer",
                "name": "trueFalseExclusiveness",
                "value": 1
              }
            ]
          },
          {
            "type": "relatedPropositionLift",
            "proposition": {
              "$group": [
                {
                  "Description": "cloud"
                },
                {
                  "Description": "services"
                }
              ]
            },
            "value": 7.6643
          },
          {
            "type": "relatedPropositionLift",
            "proposition": {
              "Description": "cloud"
            },
            "value": 1
          },
          {
            "type": "relatedPropositionLift",
            "proposition": {
              "Description": "services"
            },
            "value": 1
          }
        ]
      }
    }
  ]
}

Read the tree as a product of factors: the base rate for E002 is 10.8% (baseP). The words cloud and services occur together in this data, so Aito reads them as one piece of evidence โ€” the $group โ€” which raises the base rate 7.7ร— (relatedPropositionLift); the single words then add nothing of their own (lift 1.0), so the pair is not counted twice. The normalizers scale the result against the other candidates, and the factors multiply out to the 0.833 you saw above. No model to train, no pipeline to deploy โ€” the prediction and its explanation are computed from the live rows at query time. See Inference for the full grammar of the factor tree.

The responses on this page are not pasted by hand: a test runs these exact calls on the sandbox's data, and the page prints what it recorded โ€” rounded, otherwise as returned. The page describes the engine of the docs version you are reading, so the live sandbox can differ slightly while it runs an older release.

4. Try more, in the browser

The Playground runs these same calls against this env with JSON highlighting and timing โ€” a faster loop than curl. Then browse the Use Cases for the full patterns (GL coding, support triage, tagging, market basket, search, analytics), each with runnable queries.

5. Load your own data

When you're ready to leave the sandbox: with a read-write key, branch an environment, declare your tables as collections, and batch-load. The aito-demo upload-data.js script is a complete worked example.

Need an instance and key? Run the free Docker image on your own machine. It serves the v2 API on port 9005, and the keys are the ones you pin:

export AITO_KEY=$(openssl rand -hex 24)        # read-write key: keep it
export AITO_READ_KEY=$(openssl rand -hex 24)   # read-only key
docker run -d --name aito -p 127.0.0.1:9005:9005 -v aito-state:/io/state \
  -e READ_WRITE_APIKEY="$AITO_KEY" -e APIKEY="$AITO_READ_KEY" \
  ghcr.io/aitohq/aito

The Docker page has the full recipe, the configuration and the free-tier row limits. Hosted v2 instances are still provisioned on request: email support@aito.ai.

Running locally? The base URL is http://127.0.0.1:9005, with no /db/โ€ฆ path (for example http://127.0.0.1:9005/api/v2/_query). The key is the READ_WRITE_APIKEY you pinned with -e. If you started the container without keys, it generated a pair: read it from the volume with docker exec aito cat /io/state/.aito-api-keys. Do not rely on docker logs: from v2.11.2 the log shows the keys in full only on first boot, and masked after that.

# creates the env, defines "type": "collection" tables, batch-loads data
AITO_URL=https://your-instance.aito.ai/db/your-db \
AITO_API_KEY=<read-write-key> \
node upload-data.js

From Python, the same three steps are create_collection, upload_entries and optimize โ€” see Python SDK: load your own data.

See CollectionDb for the ingest endpoints, Schema Design for the type system, and Common Errors when something doesn't behave.

Next steps

  • Use Cases โ€” what teams build, end to end
  • Python SDK โ€” the same calls as a typed Python client
  • Query Reference โ€” every operator and query type
  • Inference โ€” how prediction and $why work
  • Sandbox โ€” the full read-only dataset and endpoints