curl --request PATCH \
--url https://api.vainona.ai/v1/namespaces/{ns}/groups/{name} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"aggregate": {
"count": true,
"count_where": {},
"sum": [
"<string>"
],
"avg": [
"<string>"
],
"min": [
"<string>"
],
"max": [
"<string>"
],
"quantiles": [
"<string>"
]
},
"keep_keys": "<string>",
"confirm": false
}
'import requests
url = "https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}"
payload = {
"aggregate": {
"count": True,
"count_where": {},
"sum": ["<string>"],
"avg": ["<string>"],
"min": ["<string>"],
"max": ["<string>"],
"quantiles": ["<string>"]
},
"keep_keys": "<string>",
"confirm": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
aggregate: {
count: true,
count_where: {},
sum: ['<string>'],
avg: ['<string>'],
min: ['<string>'],
max: ['<string>'],
quantiles: ['<string>']
},
keep_keys: '<string>',
confirm: false
})
};
fetch('https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'aggregate' => [
'count' => true,
'count_where' => [
],
'sum' => [
'<string>'
],
'avg' => [
'<string>'
],
'min' => [
'<string>'
],
'max' => [
'<string>'
],
'quantiles' => [
'<string>'
]
],
'keep_keys' => '<string>',
'confirm' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}"
payload := strings.NewReader("{\n \"aggregate\": {\n \"count\": true,\n \"count_where\": {},\n \"sum\": [\n \"<string>\"\n ],\n \"avg\": [\n \"<string>\"\n ],\n \"min\": [\n \"<string>\"\n ],\n \"max\": [\n \"<string>\"\n ],\n \"quantiles\": [\n \"<string>\"\n ]\n },\n \"keep_keys\": \"<string>\",\n \"confirm\": false\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"aggregate\": {\n \"count\": true,\n \"count_where\": {},\n \"sum\": [\n \"<string>\"\n ],\n \"avg\": [\n \"<string>\"\n ],\n \"min\": [\n \"<string>\"\n ],\n \"max\": [\n \"<string>\"\n ],\n \"quantiles\": [\n \"<string>\"\n ]\n },\n \"keep_keys\": \"<string>\",\n \"confirm\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"aggregate\": {\n \"count\": true,\n \"count_where\": {},\n \"sum\": [\n \"<string>\"\n ],\n \"avg\": [\n \"<string>\"\n ],\n \"min\": [\n \"<string>\"\n ],\n \"max\": [\n \"<string>\"\n ],\n \"quantiles\": [\n \"<string>\"\n ]\n },\n \"keep_keys\": \"<string>\",\n \"confirm\": false\n}"
response = http.request(request)
puts response.read_body{
"name": "<string>",
"key": "<string>",
"aggregate": {
"count": true,
"count_where": {},
"sum": [
"<string>"
],
"avg": [
"<string>"
],
"min": [
"<string>"
],
"max": [
"<string>"
],
"quantiles": [
"<string>"
]
},
"keep_keys": "<string>",
"status": "building",
"created_at": "2023-11-07T05:31:56Z",
"match": {},
"template": "<string>",
"job_id": "<string>",
"readers": [
"<string>"
],
"live_keys": 1,
"warnings": [
"group_over_cap"
],
"as_of": 1,
"rows": [
{
"key": "<string>",
"values": {}
}
]
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}Add aggregates or change keep_keys
aggregate adds to the group’s aggregates (existing ones never
change meaning, and cannot be removed while a judgment reads them);
it starts a group_build job for the new ones. When judgments read
the group, adding one would move their projections, so without
confirm: true it returns their estimate and changes nothing.
keep_keys needs no confirm. A namespace cannot change a group it
inherits (conflict).
curl --request PATCH \
--url https://api.vainona.ai/v1/namespaces/{ns}/groups/{name} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"aggregate": {
"count": true,
"count_where": {},
"sum": [
"<string>"
],
"avg": [
"<string>"
],
"min": [
"<string>"
],
"max": [
"<string>"
],
"quantiles": [
"<string>"
]
},
"keep_keys": "<string>",
"confirm": false
}
'import requests
url = "https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}"
payload = {
"aggregate": {
"count": True,
"count_where": {},
"sum": ["<string>"],
"avg": ["<string>"],
"min": ["<string>"],
"max": ["<string>"],
"quantiles": ["<string>"]
},
"keep_keys": "<string>",
"confirm": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
aggregate: {
count: true,
count_where: {},
sum: ['<string>'],
avg: ['<string>'],
min: ['<string>'],
max: ['<string>'],
quantiles: ['<string>']
},
keep_keys: '<string>',
confirm: false
})
};
fetch('https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'aggregate' => [
'count' => true,
'count_where' => [
],
'sum' => [
'<string>'
],
'avg' => [
'<string>'
],
'min' => [
'<string>'
],
'max' => [
'<string>'
],
'quantiles' => [
'<string>'
]
],
'keep_keys' => '<string>',
'confirm' => false
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}"
payload := strings.NewReader("{\n \"aggregate\": {\n \"count\": true,\n \"count_where\": {},\n \"sum\": [\n \"<string>\"\n ],\n \"avg\": [\n \"<string>\"\n ],\n \"min\": [\n \"<string>\"\n ],\n \"max\": [\n \"<string>\"\n ],\n \"quantiles\": [\n \"<string>\"\n ]\n },\n \"keep_keys\": \"<string>\",\n \"confirm\": false\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"aggregate\": {\n \"count\": true,\n \"count_where\": {},\n \"sum\": [\n \"<string>\"\n ],\n \"avg\": [\n \"<string>\"\n ],\n \"min\": [\n \"<string>\"\n ],\n \"max\": [\n \"<string>\"\n ],\n \"quantiles\": [\n \"<string>\"\n ]\n },\n \"keep_keys\": \"<string>\",\n \"confirm\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.vainona.ai/v1/namespaces/{ns}/groups/{name}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"aggregate\": {\n \"count\": true,\n \"count_where\": {},\n \"sum\": [\n \"<string>\"\n ],\n \"avg\": [\n \"<string>\"\n ],\n \"min\": [\n \"<string>\"\n ],\n \"max\": [\n \"<string>\"\n ],\n \"quantiles\": [\n \"<string>\"\n ]\n },\n \"keep_keys\": \"<string>\",\n \"confirm\": false\n}"
response = http.request(request)
puts response.read_body{
"name": "<string>",
"key": "<string>",
"aggregate": {
"count": true,
"count_where": {},
"sum": [
"<string>"
],
"avg": [
"<string>"
],
"min": [
"<string>"
],
"max": [
"<string>"
],
"quantiles": [
"<string>"
]
},
"keep_keys": "<string>",
"status": "building",
"created_at": "2023-11-07T05:31:56Z",
"match": {},
"template": "<string>",
"job_id": "<string>",
"readers": [
"<string>"
],
"live_keys": 1,
"warnings": [
"group_over_cap"
],
"as_of": 1,
"rows": [
{
"key": "<string>",
"values": {}
}
]
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}{
"error": {
"code": "invalid_request",
"message": "<string>",
"details": {
"suggested_context": {
"recipe": {
"fields": [
"<string>"
],
"last_n": {},
"window": {},
"max_tokens": 2,
"related": {},
"group": {},
"previous": {
"fields": [
"<string>"
],
"anchor": "<string>"
}
},
"cost_per_answer": 1,
"whole_state_cost_per_answer": 1,
"sampled_documents": 2,
"excluded": [
{
"path": "<string>",
"reason": "id"
}
]
}
}
}
}Authorizations
An organization API key. Keys carry a role (read_write or
read_only) and may be restricted to a namespace prefix such as
acme/*, or to one namespace such as acme/prod/tenant_1. A prefix
matches on a / boundary: acme/prod/tenant_1* covers
acme/prod/tenant_1 and everything under acme/prod/tenant_1/,
never acme/prod/tenant_12.
Headers
Returns the original response verbatim while the node still caches it. Correctness never depends on it.
1Path Parameters
A namespace name, or a template prefix ending in /* (§7.7), with any
/ sent as %2F: acme%2Fprod%2Ftenant_123 or acme%2Fprod%2F*.
A namespace name, or a template prefix: a namespace path ending in
/*, such as acme/prod/*, which every namespace under acme/prod/
inherits judgments from (§7.7). Up to 256 bytes.
1 - 256^[A-Za-z0-9._:/-]+(/\*)?$A judgment, attribute or threshold name. Names are path segments in field references, so they never contain ..
1 - 128^[A-Za-z0-9_-]+$Body
At least one of aggregate and keep_keys.
Aggregates to add. Existing ones stay as they are.
Show child attributes
Show child attributes
A whole number and a unit (s, m, h or d), such as 7d or 1h.
^[1-9][0-9]*[smhd]$Required to add an aggregate when judgments read the group; without it, the response is their estimate.
Response
The group with the change applied, or the readers' estimate when it needs confirm.
- Option 1
- Option 2
Relations (§6.5.3). A group, its status and, on get in a namespace, its rows.
A judgment, attribute or threshold name. Names are path segments in field references, so they never contain ..
1 - 128^[A-Za-z0-9_-]+$^attributes\.[A-Za-z0-9_-]+$Relations (§6.5.3). What the group keeps per key value, over the
documents matching match, exact as of the last merge. At most 8
paths in total. quantiles keeps a mergeable sketch per path, which
position reads and GET reports as p50, p90 and p99. count_where
counts documents by plain judgments' answers, with the roll-up rules;
sum and avg over answers are invalid_request.
Show child attributes
Show child attributes
A whole number and a unit (s, m, h or d), such as 7d or 1h.
^[1-9][0-9]*[smhd]$building until its group_build job has computed the aggregates, then ready. Judgments that read it wait for it.
building, ready RFC 3339, UTC.
Entities, E1 (§6.5). Which documents something applies to, by their
attributes. Each key is an attribute path; a value is equality, and a
list of values is In, as in query filters. Keys combine with And.
Show child attributes
Show child attributes
Present when the group is inherited, the template prefix it comes from.
1 - 256^[A-Za-z0-9._:/-]+(/\*)?$The group_build job, while it runs.
The judgments that read the group. Deleting it is conflict while there are any.
A judgment, attribute or threshold name. Names are path segments in field references, so they never contain ..
1 - 128^[A-Za-z0-9_-]+$Live key values now; null on a template's prefix path.
x >= 0group_over_cap: more than 1,000 live key values, so its readers read stale (group_over_cap) until key values age out past keep_keys.
group_over_cap The seq of the merge the rows are exact at. Absent from lists and on a template's prefix path.
x >= 0On get in a namespace, one row per live key value, the largest count first. Null on a template's prefix path, absent from lists.
1000Show child attributes
Show child attributes