Group webhook deliveries by identity within a time window and decide: process, dedupe, retry, reconcile or abstain
Given previously seen deliveries (identity, receivedAt, payload or digest, handling outcome) and a new incoming one, finds earlier deliveries with the same identity inside the window and returns process (none), dedupe (same payload already processed), retry (earlier ones all failed), reconcile (an earlier one is in flight or unknown, or the same identity arrives with a different payload) or abstain (times or payload evidence missing, or the only history for this identity is dated after the incoming delivery). Also lists duplicate groups and payload conflicts in the history. A delivery exactly windowSeconds old is still inside the window. status pass = process, dedupe or retry; fail = reconcile; unknown = abstain. Holds no state: the caller supplies the history.
What you get
Avoids double-processing a replayed webhook and surfaces the replay that carries different data.
Call it
Send the JSON body below to https://agents.writerslogic.com/api/v1/dedup-window. An unpaid request answers 402 with the price and how to pay; a request that fails with a 5xx status is not charged.
curl -i -X POST https://agents.writerslogic.com/api/v1/dedup-window \
-H 'content-type: application/json' \
-d '{"history":[{"id":"d1","identity":"evt_9","receivedAt":"2026-11-04T10:00:00Z","payload":{"amount":5},"outcome":"processed"}],"incoming":{"identity":"evt_9","receivedAt":"2026-11-04T10:00:30Z","payload":{"amount":5}},"windowSeconds":300}'
Input
| Field | Type | Required | Description |
|---|---|---|---|
history | array<object>; max 500 items | yes | |
incoming | object | yes | |
windowSeconds | integer; 1..2592000 | yes | |
windowMode | string; one of "from-first", "sliding" | no | from-first (default): a group's window starts at its first delivery. sliding: each delivery extends the window. |
Example request body
{
"history": [
{
"id": "d1",
"identity": "evt_9",
"receivedAt": "2026-11-04T10:00:00Z",
"payload": {
"amount": 5
},
"outcome": "processed"
}
],
"incoming": {
"identity": "evt_9",
"receivedAt": "2026-11-04T10:00:30Z",
"payload": {
"amount": 5
}
},
"windowSeconds": 300
}
Result
The response is { "data": ..., "_provenance": ... }. data carries these fields; _provenance is a signed W3C Verifiable Credential with a C2PA-style manifest, checked free at POST /api/v1/verify-provenance.
| Field | Type | Required | Description |
|---|---|---|---|
status | string; one of "pass", "fail", "unknown", "unsupported" | no | pass: every rule held. fail: a rule was violated (see witnesses). unknown: the input lacks the evidence to decide. unsupported: outside what this engine covers. Missing evidence is never a pass. |
decision | string; one of "process", "dedupe", "retry", "reconcile", "abstain" | no | |
reason | string | no | |
matchedIds | array<string> | no | History entries (id or index) in the window for this identity. |
groups | array<object> | no | History identities seen more than once inside one window. |
incomingDigest | string | no | |
witnesses | array<object> | no | |
versions | object | no | Every semantic dependency of this answer (engine, tables and their as-of dates, tokenizer, calendar, rounding profile). |
limits | array<string> | no | |
deterministic | boolean | no | Always true: pure code, no model. |
Pay and connect
Available through: x402 (USDC on Base), MCP. MCP clients reach it through the execution-safety-kit package.
Machine-readable
- This agent as JSON (schemas, example, OpenAPI operation)
- Free signed sample response
- OpenAPI 3.1 · Catalog · Index of every agent