Ask filters
POST https://api.tiny.plus/v2/ai/filter
Turns a plain-English question into the query parameters for a record list. Send "won projects over 50k that Maya is on", get back record_status=won, fee_value=>50000 and staff=<Maya's id>, ready to put on GET /v2/projects.
It doesn't read or return any records itself — you run the list. It reads your account's fields, labels, statuses, tags and team so the words map to your setup.
Request
Send a JSON body:
curl -X POST "https://api.tiny.plus/v2/ai/filter" \
-H "Authorization: Bearer {{user_access_token}}" \
-H "Content-Type: application/json" \
-d '{
"flavour": "projects",
"q": "won projects over 50k this year that Maya is on, biggest first"
}'flavour
Required. The record type to build a filter for, such as projects or contacts.
q
Required. The question, 1 to 500 characters.
current_filters
Optional. A filter already in force, as a {field: value} object in the list grammar. Ask refines it and returns the whole new set — this is how you follow up "…and only the ones I own".
client
Optional label for your integration, recorded in tiny+'s AI log.
Response
query
The parameters to send to GET /v2/{flavour}: field conditions, tags_{id}, custom_{id}, me, staff and sort. {} when nothing in the question could be used.
explanation
One sentence describing the filter, in the account's own labels.
assumptions
The readings Ask had to make — worth showing the user so they can correct one.
unresolved
Parts it couldn't map, each {phrase, reason} — for example a name that matches no team member.
confidence
high (a clean mapping), medium (it made assumptions), or low (something's unresolved, or the query is empty).
chips
The filter as a list of {key, label}, for showing it back to the user.
source
model for a fresh answer, cache for a repeat within the account.
explanation, assumptions and chips are model-written and use your account's labels. Escape them before putting them in HTML.
Applying the filter
If the response has a
reason, run the fallback search (below).Otherwise, show the user the
explanation,chips,assumptionsand anythingunresolved.When
queryisn't empty and theconfidenceis good enough for you, send its entries as query parameters onGET /v2/{flavour}. URL-encode the values —>,<,!, spaces and|all need it — and add your ownlimit,startandfields.To refine, send that
queryback ascurrent_filterswith the next question.
An empty query ({}) filters nothing, so a GET with it returns every record. Check confidence and unresolved before applying a filter, rather than sending an empty one.
When Ask falls back
If Ask is switched off, over a limit, or the model can't help, you still get 200 — with query: null and a reason, plus a fallback telling you to run a plain search:
reason is one of disabled (Ask isn't on for the account), capped (a rate limit is used up), timeout, overloaded, refusal, invalid or error. In every case, run GET {fallback.endpoint}?q={fallback.q}.
Limits and errors
Ask draws on your account's AI allowance, with a per-minute limit as well. When either is used up, the response is the capped fallback above. The numbers are on the Fair use page.
flavour missing, not a string, or not an API record type
400 {"error": "'flavour' must name a record type this account exposes to the API."}
q missing or blank
400 {"error": "'q' is required."}
q over 500 characters
400 {"error": "'q' is limited to 500 characters."}
current_filters not an object
400 {"error": "'current_filters' must be an object of field=value pairs."}
Missing or invalid token
401, in the OAuth error shape
Last updated
Was this helpful?