Skip to main content
Anyone who learns your endpoint URL can send a POST to it. The Signature header is how you prove a request actually came from Edplay.
Treat signature verification as mandatory. An endpoint that accepts unsigned requests will happily record training completions invented by anyone on the internet.

How the signature is calculated

Edplay computes the signature as a hex-encoded HMAC-SHA256 of the raw request body, keyed with your workspace signing secret:
To verify, compute the same value over the body you received and compare it to the Signature header.
The single most important detail: hash the raw body bytes exactly as received. If you parse the JSON and re-serialize it, key order and whitespace shift, the hash changes, and every verification fails. Capture the raw body before any JSON middleware touches it.
The Timestamp header is not part of the signature, so do not include it in the hash.

Examples

Each example verifies the signature, hands the payload to a queue, and returns immediately. See Deliveries and retries for why that ordering matters.

Getting the raw body in each framework

Always compare in constant time

Use crypto.timingSafeEqual, hash_equals, or hmac.compare_digest. A plain == on the two strings leaks timing information that can, in principle, let an attacker recover a valid signature byte by byte.

If verification fails

Return 401 and do not process the payload. The delivery is recorded as Failed in the delivery log along with the response body your endpoint returned, which makes a signature rejection easy to tell apart from an application error.
If your signature never matches, the cause is almost always a re-serialized body or a stale secret after a rotation. See Troubleshooting.
Next: Deliveries and retries