Contents
Webhooks - Plugixa Exam
A webhook tells another system that something happened here, without it having to ask.

The events
| Event | Fires when |
|---|---|
| Attempt submitted | A candidate hands a paper in |
| Attempt graded | Marking finishes, automatic or by a person |
| Certificate issued | Somebody earns one |
Signing
Every request is signed with HMAC-SHA256 using the secret on the endpoint.
Verify the signature at the other end. An unsigned or unverified webhook endpoint is a URL anybody who learns it can post to, and the payload says somebody passed an exam. Verifying is the whole point of the signature.
The address is checked
The URL you enter goes through an SSRF guard: private and loopback addresses are refused, so the plugin cannot be talked into posting your exam results to a service on your own network by somebody who can edit a webhook but should not reach it. Requests time out after eight seconds.
There is an override, and it is off.
webhooks_allow_privatelifts the block on private addresses. It exists for the legitimate case - a receiver on the same host - and it should stay off unless that is genuinely what you are doing, because switching it on is what makes the paragraph above stop being true.
Like LTI and AI drafting, this contacts nothing until an administrator enters an address. There is no default endpoint.
Retries and the delivery log
A failed delivery is retried, and every attempt is recorded. When somebody says “we never got it”, the log says whether it was sent, what came back, and how many times it was tried.
Troubleshooting
| Symptom | Usual cause |
|---|---|
| Nothing is delivered | No endpoint is registered, or the Webhooks capability is off. |
| The receiver rejects the signature | It is verifying a different body than the one sent. Sign the raw body, before any parsing. |
| The address is refused on save | The SSRF guard blocked it. Private and loopback addresses are refused unless webhooks_allow_private is on. |
| Duplicate deliveries | Retries. Make your receiver idempotent; the payload carries the attempt id. |
What to do next
- Pull data instead of receiving it: API Tokens.
- React in PHP on the same site: Hooks.
- Send grades to an LMS: LTI 1.3.