revision creates a new Version of that Record.
Prerequisites
- A running Quivr and a pinned push plugin. Pin a plugin or activate a registered plugin; write a push source if you need a new kind.
- For the offline example below, the Quivr checkout and local stack (
make dev). It pinsplugins/push-source, which declares theeventskind. Export its address and key witheval "$(make -s env)". curl(curl --version) andjq(jq --version). The key needscorpora:write,connectors:write,connectors:adminandcontent:readon the example’s Corpus. Audit counters needobservability:readon all Corpora.- For a provider-signed source, its provider account and signing secret. Deposit the secret as the instance’s credential, following the kind’s guide, such as X lists. Those external steps are examples, not replayed by the local stack.
Steps
The following requests use the offline sample and are replayed bymake verify.
Create a collection and source instance
Issue a token and push
Save the once-onlysecret in a private file, then use it for the sender’s authorization header. Give it to the third party through your secret-delivery channel. Keep the token ID for rotation and revocation.
202. Retrying the same idempotency key returns the cached answer while it is retained. Keep the request unchanged; the cache does not compare bodies. A correction uses a new revision and idempotency key.
Check it worked
Read the Receipt with your Quivr key until processing resolves:Give access
The route declares its authentication mode. Forquivr_key, grant the sender’s API key connector:push on the instance’s Corpus in the API key configuration. For instance_token, issue an instance token as above and manage it below. For signature, the sender signs requests and you deposit the provider credential following the kind’s guide.
Manage tokens
An instance token permits pushes to one instance’sauth: instance_token routes. It cannot authorize another instance, a quivr_key route, token administration or a normal API read. The operator’s Quivr key needs connectors:admin on the instance’s Organization and Corpus; other connector permissions do not grant token administration.
Quivr shows the secret once, stores only its hash and sends Cache-Control: no-store.
For example, rotate token A at 12:00 UTC and give replacement B to the sender. A works until its
valid_until at 12:05 UTC. A revoked or already-rotated token cannot rotate again (409 token_inactive); retrying cannot recover B’s secret or extend A’s overlap.
Revoking A leaves B valid: revoke every token ID that should lose access. If an issuance or rotation response is lost, list tokens, revoke the token whose secret you lost and create another.
Disabled instances refuse issuance and rotation; you can still list and revoke their tokens. Quivr removes bearer secrets and cookies before calling the plugin.
Set admission limits
Setpush_policy when you create the instance, separate from the plugin’s config. There is no policy-update endpoint. To replace the policy, disable the old instance first, create another on the same Corpus and Source Namespace, issue a new instance token if needed and deposit the provider credential again if needed, then give the sender the new URL. Only one instance can be enabled for that Corpus and namespace; pushes return 404 during the gap. The replacement has a new connector_id, so its URL changes and the old instance’s tokens cannot authorize it. It can override rate_per_second and burst, and restrict callers with allowed_cidrs. An empty allowlist allows any address. The deployment’s connector_push settings supply defaults and trusted_proxy_cidrs; see Configuration.
For example, not run: an instance policy admitting one documentation address range and a burst of ten requests:
X-Forwarded-For backwards through trusted hops to the first untrusted address. Malformed chains fail closed when an allowlist applies; trusting a sender-controlled proxy can defeat that allowlist.
Quivr bounds the body to 1 MiB, and the query and relative path to 8192 bytes each, before calling the plugin. Oversized requests return 413.
Quivr resolves the route before checking its instance token. Authentication and, for signed POSTs, freshness and replay checks run before JSON/schema validation. Schema validation precedes the IP allowlist. On bearer routes (quivr_key and instance_token), a cached answer is then returned before rate admission; other admitted requests consume the instance’s shared rate bucket. The push-checks diagram shows the complete order.
How retries behave
AnIdempotency-Key is a sender-chosen identifier for one delivery, called the delivery key below. Send one value, up to 256 bytes, nonblank and without line breaks. Use a new value for a new delivery.
On quivr_key and instance_token routes, Quivr caches a completed answer per instance and delivery key for connector_push.idempotency_ttl (24 hours by default). A completed plugin or processing 5xx answer is cached with its key like a success, including Retry-After; waiting does not clear it. After fixing the cause, retry with a new delivery key and the same item revisions.
For example, retry
push-guide-note-1 above with the same body: while cached, it returns the original Receipts without calling the plugin or consuming the rate bucket. Reusing that key for changed content also returns the old answer. Authentication, schema, IP and rate refusals leave no completed cached answer.
On signature POST routes, Quivr reserves fingerprints of the signature and, if present, the delivery key before schema validation. Repeating either during window_seconds returns 409 push_replayed. For example, after a successful signed delivery with a 300-second window, an immediate retry with the same signature is refused even if you change its delivery key.
Signature routes never use the response cache, including GET challenges. A refusal or failed processing normally releases the reservation. If cleanup fails or the request deadline expires, it remains until the window expires; retries return 409 meanwhile. After the reservation expires, a request with a signed timestamp is still refused once that timestamp is older than the window. Without a signed timestamp, the engine only prevents replay during the reservation window.
Stable Record Keys and revisions make already accepted items converge on their Receipts when processing is retried. A push may have stored some items before failing; a 202 Receipt tracks processing, not immediate search availability. Follow the life of a document for the path after acceptance.
Inspect attempts
Every attempt on an existing instance, including cached replies and GET challenges, recordsconnector.push.received for a 2xx answer or connector.push.refused otherwise. Audit events and counters commit together before Quivr sends the answer; audit failure returns 503. It does not undo items already accepted, so retry using stable item keys and revisions. No payload, client IP, raw key or credential enters that journal.
Read events with GET /v0/changes, or read GET /v0/admin/stats/connector-pushes with observability:read on all Corpora. It lists the largest 100 instance/outcome pairs and totals across all pairs. Use limit (1–100) to shorten that list or connector_id to read both outcomes of one instance; you cannot combine the filters.
Troubleshooting
Clean up
Revoke the example’s token when the sender no longer needs access, then removepush-token.json. Disable the instance to stop it. Records already collected remain searchable; disabling is permanent, so replacing the instance requires creating another on the same Source Namespace.
Next
- Write a push source for route declarations and provider challenges.
- Upgrade or switch a plugin for plugin operations.
- API key configuration for operator and sender permissions.