diff --git a/v3/expert-models/webhooks.mdx b/v3/expert-models/webhooks.mdx
index c156955..265655b 100644
--- a/v3/expert-models/webhooks.mdx
+++ b/v3/expert-models/webhooks.mdx
@@ -14,7 +14,7 @@ import { TechArticleSchema } from "/snippets/TechArticleSchema.mdx";
proficiencyLevel="Intermediate"
keywords={["Eden AI", "AI API", "expert models", "multi-provider"]}
datePublished="2026-05-06T00:00:00Z"
- dateModified="2026-05-07T00:00:00Z"
+ dateModified="2026-07-10T00:00:00Z"
/>
Webhooks let you receive results from async Universal AI jobs via HTTP callbacks instead of polling. When a job completes, Eden AI sends a signed `POST` request to the URL you provided.
@@ -40,7 +40,7 @@ Every webhook request Eden AI sends includes these headers:
| ------------------------- | ---------------------- | ---------------------------------------------------------------------- |
| `Content-Type` | `application/json` | Body is always JSON. |
| `User-Agent` | `EdenAI/Ai-Features` | Identifies the sender. |
-| `X-Edenai-Webhook` | `true` | Flag marking the request as an Eden AI webhook. |
+| `X-EdenAI-Webhook` | `true` | Flag marking the request as an Eden AI webhook. |
| `X-Edenai-Signature` | `a8f3...` (hex) | RSA PKCS1 v1.5 signature of the payload. |
| `X-Edenai-Hash-Algorithm` | `SHA256` | Hash algorithm used to produce the signature. |
@@ -80,20 +80,30 @@ Every webhook request Eden AI sends includes these headers:
## Signature Verification
-Every webhook is signed with Eden AI's RSA private key so you can verify it was not forged or tampered with in transit.
-
-
-Ask Eden AI support for the webhook **public key** (`webhook_rsa.pub.pem`) and store it with your service configuration.
-
+Every webhook is signed with Eden AI's RSA private key so you can verify it was not forged or tampered with in transit. Verify each request against Eden AI's **public key** below. Save it as `edenai_webhook_rsa.pub.pem` next to your handler — this is the file the examples load.
+
+```text edenai_webhook_rsa.pub.pem
+-----BEGIN PUBLIC KEY-----
+MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA2fQneVfTrhkDdlvqs2Vi
+T0tZ9PCkL0vHanZMc+6YyvvewIQRp1bH8Q13gYDf0t/tCKhVJqnPQ7qXekhtBrC1
+uMAf/qDhUhkKB0w9Xt5DXbEZaxFQjrlDSHwcWdhH+BOAVDxQvaDuWveS8/kEIuo8
+x/QLNOVTrUSKnjXnnqZ2k6OeD0WHv/6bLqPjFxdwL+4hi0nw1O57IfW7Oqzcd5JF
+X1Aq8nU4N0P8PEetUl84LKCiiT801wKOksUJUtjGHqdtOqP4g0Vk0w5BtBDPVPyF
+eQNLpALTxeG2WUtNtOiZCl0757K6dY13FYR86e7KUlQzaZhy2vBKtghi5Rf03puk
+8fTS8zuO5LSX9GmHxZ1aywIvx6kcjp52S52/q6ZdXuTe+0DCxjoFCnJ3C/6cNphE
+pZggShdZUtJFo85ImMRAesD0+hjeHuhqGuis/i1JOHzYcSpKVCaksujrscR+m7Id
+1XrF/DY4gF8hizGHsEcurP+A6epUblTDtg/F0foYfitfAgMBAAE=
+-----END PUBLIC KEY-----
+```
The signature is built as follows:
-1. The payload is serialized with canonical JSON (sorted keys, 2-space indent, UTF-8).
-2. `sha256(canonical_json_bytes)` is computed and its **hex digest** is taken.
-3. That hex digest is signed with RSA PKCS1 v1.5 / SHA-256.
-4. The hex-encoded signature is sent in `X-Edenai-Signature`.
+1. The payload is serialized to **canonical JSON**: keys sorted alphabetically, 2-space indent, UTF-8 with non-ASCII characters left as-is (not `\u`-escaped). This is exactly `orjson.dumps(payload, option=OPT_INDENT_2 | OPT_SORT_KEYS)`.
+2. `sha256(canonical_json_bytes)` is computed and its **hex digest** (a 64-character string) is taken.
+3. That hex digest string is signed with RSA PKCS1 v1.5 over SHA-256.
+4. The signature is hex-encoded and sent in the `X-Edenai-Signature` header.
-To verify, reproduce the same canonical JSON before hashing — do **not** re-serialize with default formatting.
+The delivered request body is compact JSON, so you must re-serialize it into the canonical form above before hashing — do **not** hash the raw body, and do **not** re-serialize with default formatting.
## Example
@@ -244,6 +254,8 @@ To verify, reproduce the same canonical JSON before hashing — do **not** re-se
Do **not** re-serialize the parsed JSON with defaults (e.g. `JSON.stringify(obj)` or `json.dumps(obj)` without `sort_keys=True, indent=2`) — any difference in spacing, key ordering, or unicode escaping will make the signature fail to verify.
+
+Number formatting differs across languages too: a whole-number float in the payload (for example a `1.0` confidence score) serializes as `1.0` on the Eden AI side but as `1` with JavaScript's `JSON.stringify`, which breaks verification. If your payloads can contain such values, verify from a Python service or normalize the numbers before hashing.
## Retry Behavior