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
$whywork - Sandbox โ the full read-only dataset and endpoints