"harbour strike" AND (ferry OR port) NOT football. Quivr records each catch as a Match with the words that matched, and sends it to your webhook. The first-party alerts plugin decides the matches. How alerts work explains the objects this page creates.
Prerequisites
- The
alertsplugin pinned. The local stack pins it; elsewhere see Pin a plugin. QUIVR_API_URLand aQUIVR_API_KEYwithmonitoring:readandmonitoring:write, pluscontent:writeto add the test article below. The first request creates a Corpus, which needscorpora:writeand a key not limited to some Corpora; with another key, use an existing Corpus id instead. The local stack’smake envkey has all of these.QUIVR_DESTINATION: the id of a webhook destination the operator configured for your Organization. Destinations live in Quivr’s configuration, never in API requests. The local stack’smake envsets one that delivers nowhere.
Write the query
- Operators are written in capitals;
and,orandnotin lower case are ordinary words.NOTbinds tighter thanAND, which binds tighter thanOR. - Case, accents and punctuation are ignored:
grevefinds “Grève”. - Words match whole, and there is no stemming:
strikedoes not find “strikes”. List the forms you need,strike OR strikes. - Terms search the
titleandbodyParts. source:,origin:(clientorconnector),producer:,connector:andconnector_kind:filter on metadata Quivr always has. Other names, such asauthor:, work once the operator maps them (below).
Turn it into an expression
Quivr stores a query as a JSON tree, which it validates when you save the alert, so a malformed query is refused at once. An unmapped metadata field is still valid syntax but never matches (see Filter on your own metadata). The plugin ships the parser. From aquivr checkout:
all, any and not map to “all of these words”, “any of these words” and “none of these words”.
Save the alert
These requests use a Corpus of their own:alerts plugin as evaluator. Give it an owner when the alert belongs to one of your application’s users: Quivr echoes it on every Match and webhook, so you can route each alert, and GET /v0/subscriptions?owner=user-123 lists that user’s alerts.
POST /v0/subscription-previews.
Read what matched
Add an article that matches:NOT are never listed. evidence.details has the same facts as JSON.
Receive the webhook
For each Match, Quivr sends aPOST to the destination’s URL. The body only references what happened; fetch the Match with GET /v0/matches/{match_id} to read its evidence:
408, 429 and 5xx answers are retried with growing delays, from 1 second up to 5 minutes, for 24 hours; any other answer stops the retries. These are defaults the operator can change, and a Retry-After header on a 429 or 503 sets the next delay. GET /v0/deliveries/{delivery_id} shows a delivery’s state and its attempts.
When an article that matched is corrected or withdrawn, the same receiver gets a follow-up: match.corrected, match.no_longer_matches or match.withdrawn. Corrections and withdrawals says which ones store a new Match.
Verify the signature
Check the signature on the raw body before you parse it. Requests follow Standard Webhooks: thewebhook-signature header holds v1, and a base64 HMAC-SHA256 of webhook-id, webhook-timestamp and the raw body, joined by dots. The key is the destination’s secret, whsec_ followed by base64. The operator sets it in Quivr’s configuration and gives it to you. The header can hold several signatures separated by spaces; accept the request when one of them matches.
This Python function takes the headers as a dictionary with lower-case names. It accepts only v1 signatures, skips malformed ones, and refuses a request whose timestamp is more than five minutes old; every retry carries a fresh timestamp. It was run by hand against Quivr’s public test vector and against altered copies of it.
401 when it returns False. That answer is permanent, so Quivr stops retrying that webhook. With a wrong secret, every webhook is refused this way; the Matches stay listable through the API.
Deduplicate
Delivery is at least once: a webhook can arrive twice, for example when your answer is lost on the way back. A retry sends the samewebhook-id, which is the body’s event_id, and the same body. Each event, follow-ups included, has its own id. Store the ids you have handled for at least the retry window, 24 hours by default, and answer 2xx without acting again when one comes back. Record an id only after you have acted on the event, so a crash before then gets the webhook again.
A complete receiver in Python
A complete receiver in Python
This receiver uses only the standard library. It verifies each webhook with the
verify function above, acts on each event once, and acknowledges with 204. It was run by hand with signed test requests: a valid one, a repeat and a forged one. Quivr refuses loopback and private addresses by default, so put the receiver behind the public URL of the destination the operator configured. Keep the handled ids in your database rather than in memory, so they survive a restart, and give them a unique constraint if two copies can arrive at the same time.GET /v0/matches?subscription_id=… to recover first matches and corrections that still matched. Corrections that no longer match and withdrawals create notices without new Matches: an application that already follows the change feed from a saved position, with a key that has changes:read, finds them there for as long as the operator keeps events, 7 days by default.
Change or stop an alert
Filter on your own metadata
Ask your operator to map the metadata fields your alerts use, such asauthor or category. A list field matches when one of its values does. A name the operator has not mapped never matches.
Timing
A keyword alert is decided as soon as the article becomes searchable, before its vectors are computed. Set{"wait_for_enrichment": true} in the Subscription’s evaluator.configuration to wait for them.
For operators
Moving existing alerts to a new version of the alert rule, and abandoning evaluations whose old rule cannot be restored, are operator tasks: see Upgrade an alert rule and Retire alert evaluations.Next
- Meaning alerts: match articles by subject rather than by words.
- How alerts work: what happens between a new article and your webhook.