X-AlgoVoi-Signature header containing a UNIX timestamp and two HMAC components. algovoi-webhook-verifier validates the header, enforces replay protection, and returns the parsed event — with no runtime dependency on AlgoVoi infrastructure.
Verification steps
| Step | Check |
|---|---|
| 1 | X-AlgoVoi-Signature header present |
| 2 | Header matches t=<unix>,v1=<sha256hex>[,v2=<sha384hex>] |
| 3 | Timestamp within tolerance window (default 300 s) |
| 4 | v1 = HMAC-SHA256(secret, "{ts}." + raw_body) |
| 5 | v2 = HMAC-SHA384(HKDF-SHA256(secret, salt, info), "{ts}." + raw_body) — validated when present |
| 6 | Body is valid JSON object |
| 7 | type field is a known event type |
salt=b"algovoi-webhook-v2-pqc" and info=b"hmac-sha384-outbound", length 48 bytes.
Quick start
Framework integration
Error codes
| Code | Cause | HTTP suggestion |
|---|---|---|
MISSING_SIGNATURE | Header absent or blank | 400 |
MALFORMED_SIGNATURE | Header does not match format | 400 |
STALE_SIGNATURE | Timestamp outside tolerance window | 400 |
INVALID_SIGNATURE | HMAC mismatch — tampered body or wrong secret | 401 |
INVALID_PAYLOAD | Body is not a valid JSON object | 400 |
UNKNOWN_EVENT_TYPE | type field not in known set | 400 |
API reference
Python
WebhookVerificationError(code, message) on any failure. .code is one of the six ErrorCode literals. .message is a human-readable description.
TypeScript
WebhookVerificationError with .code (typed ErrorCode) and .message.
Webhook event shape
Supported event types
| Type | Description |
|---|---|
payment.confirmed | On-chain payment confirmed by the AlgoVoi facilitator |
Cross-validation vectors
13 fixtures invectors/valid/ (5) and vectors/invalid/ (8). Each vector is self-contained — it embeds the secret, raw body, and header so any language implementation can verify itself against the same corpus.
| Vector | Error code |
|---|---|
v01_payment_confirmed_v1v2 | — (valid) |
v02_payment_confirmed_v1_only | — (valid) |
v03_different_secret | — (valid) |
v04_minimal_payload | — (valid) |
v05_unicode_payload | — (valid) |
i01_missing_signature | MISSING_SIGNATURE |
i02_malformed_signature | MALFORMED_SIGNATURE |
i03_stale_signature | STALE_SIGNATURE |
i04_invalid_signature_v1 | INVALID_SIGNATURE |
i05_wrong_secret | INVALID_SIGNATURE |
i06_tampered_body | INVALID_SIGNATURE |
i07_invalid_payload_not_json | INVALID_PAYLOAD |
i08_unknown_event_type | UNKNOWN_EVENT_TYPE |
Test results
| Implementation | Tests | Result |
|---|---|---|
| Python unit | 34 | 34/34 |
| Python vectors | 13 | 13/13 |
| TypeScript unit | 32 | 32/32 |
| TypeScript vectors | 13 | 13/13 |
8-language cross-validation
104/104 agreements — all 8 language implementations produce byte-for-byte identical HMAC results and identical error-code verdicts across all 13 vectors.| Language | Vectors |
|---|---|
| Python | 13/13 |
| TypeScript | 13/13 |
| Go | 13/13 |
| Rust | 13/13 |
| Java | 13/13 |
| PHP | 13/13 |
| .NET | 13/13 |
| Ruby | 13/13 |
_attestations/2026-05-31-8-impl-cross-validation.md
See also
- Notifications — webhook delivery, retry schedule, and secret rotation
- Compliance receipt verifier — JWS compliance receipt verification
- Audit verifier — offline audit bundle verification
- Package suite — full open-source package listing