curl --request POST \
--url https://api.example.com/v0/admin/backfills \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"idempotency_key": "<string>",
"corpus_id": "<string>",
"dry_run": true,
"accepted_after": "2023-11-07T05:31:56Z",
"accepted_before": "2023-11-07T05:31:56Z",
"registration_id": "<string>",
"spaces": [
"<string>"
],
"confirm_cost": false
}
'import requests
url = "https://api.example.com/v0/admin/backfills"
payload = {
"idempotency_key": "<string>",
"corpus_id": "<string>",
"dry_run": True,
"accepted_after": "2023-11-07T05:31:56Z",
"accepted_before": "2023-11-07T05:31:56Z",
"registration_id": "<string>",
"spaces": ["<string>"],
"confirm_cost": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
idempotency_key: '<string>',
corpus_id: '<string>',
dry_run: true,
accepted_after: '2023-11-07T05:31:56Z',
accepted_before: '2023-11-07T05:31:56Z',
registration_id: '<string>',
spaces: ['<string>'],
confirm_cost: false
})
};
fetch('https://api.example.com/v0/admin/backfills', 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.example.com/v0/admin/backfills",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'idempotency_key' => '<string>',
'corpus_id' => '<string>',
'dry_run' => true,
'accepted_after' => '2023-11-07T05:31:56Z',
'accepted_before' => '2023-11-07T05:31:56Z',
'registration_id' => '<string>',
'spaces' => [
'<string>'
],
'confirm_cost' => 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.example.com/v0/admin/backfills"
payload := strings.NewReader("{\n \"idempotency_key\": \"<string>\",\n \"corpus_id\": \"<string>\",\n \"dry_run\": true,\n \"accepted_after\": \"2023-11-07T05:31:56Z\",\n \"accepted_before\": \"2023-11-07T05:31:56Z\",\n \"registration_id\": \"<string>\",\n \"spaces\": [\n \"<string>\"\n ],\n \"confirm_cost\": false\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.example.com/v0/admin/backfills")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"idempotency_key\": \"<string>\",\n \"corpus_id\": \"<string>\",\n \"dry_run\": true,\n \"accepted_after\": \"2023-11-07T05:31:56Z\",\n \"accepted_before\": \"2023-11-07T05:31:56Z\",\n \"registration_id\": \"<string>\",\n \"spaces\": [\n \"<string>\"\n ],\n \"confirm_cost\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/admin/backfills")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"idempotency_key\": \"<string>\",\n \"corpus_id\": \"<string>\",\n \"dry_run\": true,\n \"accepted_after\": \"2023-11-07T05:31:56Z\",\n \"accepted_before\": \"2023-11-07T05:31:56Z\",\n \"registration_id\": \"<string>\",\n \"spaces\": [\n \"<string>\"\n ],\n \"confirm_cost\": false\n}"
response = http.request(request)
puts response.read_body{
"registration_id": "<string>",
"spaces": [
"<string>"
],
"versions": 1,
"segments": 1,
"input_tokens": 1,
"estimated_seconds": 1,
"duration_basis": "rate",
"confirmation_required": true,
"estimated_cost_usd": 1
}{
"operation_id": "<string>",
"kind": "<string>",
"state": "queued",
"counters": {},
"errors": [
{
"code": "<string>",
"message": "<string>",
"retryable": true,
"field": "<string>",
"resync_url": "<string>"
}
],
"progress": 0.5,
"previous_operation_id": "<string>",
"corpus_id": "<string>",
"result": {
"projection_generation_id": "<string>"
},
"backfill": {
"registration_id": "<string>",
"spaces": [
"<string>"
],
"estimate": {
"registration_id": "<string>",
"spaces": [
"<string>"
],
"versions": 1,
"segments": 1,
"input_tokens": 1,
"estimated_seconds": 1,
"duration_basis": "rate",
"confirmation_required": true,
"estimated_cost_usd": 1
},
"accepted_after": "2023-11-07T05:31:56Z",
"accepted_before": "2023-11-07T05:31:56Z",
"plan_id": "<string>",
"checkpoint": "<string>"
}
}{
"code": "<string>",
"message": "<string>",
"retryable": true,
"field": "<string>",
"resync_url": "<string>"
}Request backfill
Reprocess a Corpus’s past Versions with the active ingestion plugin, to fill vector spaces of the generation the Corpus is routed to, typically a new evaluation space. The scope is the Corpus and, optionally, a window on when Quivr accepted its Versions. Only Versions whose segments all hold a vector in the served space and miss one in a target space are processed; live enrichment fills the target spaces for newer Versions once the backfill has started. A dry run is required. dry_run true answers 200 with the estimate and records it under the idempotency key. The same body with dry_run false then accepts the backfill as a queued Operation (202, Location). Without a dry run recorded under that key and scope, the answer is 409 dry_run_required. An estimated cost above the deployment’s backfill.max_cost_without_confirmation needs confirm_cost true, otherwise 409 cost_confirmation_required. The same key with another scope is 409 idempotency_conflict, and an accepted key replays its Operation. A Corpus whose previous backfill has not finished is 409 backfill_in_progress. The backfill runs on its own task queue at the deployment’s backfill.rate, pinned to the Pipeline Plan active when it starts. It can be paused, resumed and canceled, and resumes from its checkpoint after a restart. It never creates Record Versions or content events. Versions whose projected segments the plugin would cut differently are skipped and counted (segmentation_differs), and a rebuild re-segments them. Requires plugins:admin, on a key of the Corpus’s Organization that grants the Corpus.
curl --request POST \
--url https://api.example.com/v0/admin/backfills \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"idempotency_key": "<string>",
"corpus_id": "<string>",
"dry_run": true,
"accepted_after": "2023-11-07T05:31:56Z",
"accepted_before": "2023-11-07T05:31:56Z",
"registration_id": "<string>",
"spaces": [
"<string>"
],
"confirm_cost": false
}
'import requests
url = "https://api.example.com/v0/admin/backfills"
payload = {
"idempotency_key": "<string>",
"corpus_id": "<string>",
"dry_run": True,
"accepted_after": "2023-11-07T05:31:56Z",
"accepted_before": "2023-11-07T05:31:56Z",
"registration_id": "<string>",
"spaces": ["<string>"],
"confirm_cost": False
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
idempotency_key: '<string>',
corpus_id: '<string>',
dry_run: true,
accepted_after: '2023-11-07T05:31:56Z',
accepted_before: '2023-11-07T05:31:56Z',
registration_id: '<string>',
spaces: ['<string>'],
confirm_cost: false
})
};
fetch('https://api.example.com/v0/admin/backfills', 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.example.com/v0/admin/backfills",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'idempotency_key' => '<string>',
'corpus_id' => '<string>',
'dry_run' => true,
'accepted_after' => '2023-11-07T05:31:56Z',
'accepted_before' => '2023-11-07T05:31:56Z',
'registration_id' => '<string>',
'spaces' => [
'<string>'
],
'confirm_cost' => 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.example.com/v0/admin/backfills"
payload := strings.NewReader("{\n \"idempotency_key\": \"<string>\",\n \"corpus_id\": \"<string>\",\n \"dry_run\": true,\n \"accepted_after\": \"2023-11-07T05:31:56Z\",\n \"accepted_before\": \"2023-11-07T05:31:56Z\",\n \"registration_id\": \"<string>\",\n \"spaces\": [\n \"<string>\"\n ],\n \"confirm_cost\": false\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.example.com/v0/admin/backfills")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"idempotency_key\": \"<string>\",\n \"corpus_id\": \"<string>\",\n \"dry_run\": true,\n \"accepted_after\": \"2023-11-07T05:31:56Z\",\n \"accepted_before\": \"2023-11-07T05:31:56Z\",\n \"registration_id\": \"<string>\",\n \"spaces\": [\n \"<string>\"\n ],\n \"confirm_cost\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v0/admin/backfills")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"idempotency_key\": \"<string>\",\n \"corpus_id\": \"<string>\",\n \"dry_run\": true,\n \"accepted_after\": \"2023-11-07T05:31:56Z\",\n \"accepted_before\": \"2023-11-07T05:31:56Z\",\n \"registration_id\": \"<string>\",\n \"spaces\": [\n \"<string>\"\n ],\n \"confirm_cost\": false\n}"
response = http.request(request)
puts response.read_body{
"registration_id": "<string>",
"spaces": [
"<string>"
],
"versions": 1,
"segments": 1,
"input_tokens": 1,
"estimated_seconds": 1,
"duration_basis": "rate",
"confirmation_required": true,
"estimated_cost_usd": 1
}{
"operation_id": "<string>",
"kind": "<string>",
"state": "queued",
"counters": {},
"errors": [
{
"code": "<string>",
"message": "<string>",
"retryable": true,
"field": "<string>",
"resync_url": "<string>"
}
],
"progress": 0.5,
"previous_operation_id": "<string>",
"corpus_id": "<string>",
"result": {
"projection_generation_id": "<string>"
},
"backfill": {
"registration_id": "<string>",
"spaces": [
"<string>"
],
"estimate": {
"registration_id": "<string>",
"spaces": [
"<string>"
],
"versions": 1,
"segments": 1,
"input_tokens": 1,
"estimated_seconds": 1,
"duration_basis": "rate",
"confirmation_required": true,
"estimated_cost_usd": 1
},
"accepted_after": "2023-11-07T05:31:56Z",
"accepted_before": "2023-11-07T05:31:56Z",
"plan_id": "<string>",
"checkpoint": "<string>"
}
}{
"code": "<string>",
"message": "<string>",
"retryable": true,
"field": "<string>",
"resync_url": "<string>"
}Authorizations
API key, not necessarily a JWT. Server derives Organization, permitted actions and Corpus scope; every resource access is authorized.
Body
1 - 2001true reports the estimate and records it; false starts the backfill a dry run with the same key and scope preceded.
Only Versions Quivr accepted at or after this time; absent, from the first.
Only Versions Quivr accepted before this time; absent, up to now.
The ingestion plugin registration to run; absent, the active plan's. Another one is 409 registration_not_active.
1The vector spaces to fill, which the plugin declares and the deployment serves or evaluates; absent, the deployment's evaluation spaces the plugin owns.
1 - 8 elements1Accept an estimated cost above the deployment's backfill.max_cost_without_confirmation.
Response
The dry run's estimate, recorded under the key.
11Versions in scope that miss a vector in a target space.
x >= 0Their segments, which the plugin embeds.
x >= 0Estimated tokens the plugin embeds, one per four code points of segment text.
x >= 0How long the backfill should take, at the deployment's backfill.rate or the recent throughput, whichever is slower.
x >= 0What the duration comes from.
rate, recent_backfills, recent_plugin_calls The cost exceeds backfill.max_cost_without_confirmation, so starting the backfill needs confirm_cost.
Estimated cost in US dollars, rounded up to the cent, of the target spaces that declare an input_price in the plugin manifest; a space without one adds nothing. Absent when none declares one, so the cost is unknown.
x >= 0