Webhooks

Signed notices when jobs finish and when things happen in your centre, with retries and replays.

Set up an endpoint

  1. In Settings → Developer API → Webhooks, add an HTTPS URL and choose the events you want (job.completed by default).
  2. Copy the signing secret. It is shown once; saving a new URL can issue a new one.
  3. Answer with any 2xx status within 5 seconds. Do slow work after you reply.

What arrives

A small JSON notice with ids only, never learner work or marks. Fetch the details with your key.

A job.completed noticeJSON
{
  "id": "wh_3f1c9a7e…",
  "type": "job.completed",
  "created_at": "2026-10-21T09:30:41+00:00",
  "sandbox": false,
  "data": {
    "job_id": "job_01JB7Q8M4X2V9R",
    "status": "succeeded",
    "product": "marking",
    "result_path": "/v1/jobs/job_01JB7Q8M4X2V9R"
  }
}

Other event types (such as marking.approved or enrolment.created) use the same envelope. See events.

Verify every delivery

Each request carries X-EduMark-Signature: t=<unix seconds>,v1=<hex> and X-EduMark-Event-Id. The signature is an HMAC-SHA256 of <t>.<event id>.<raw body> with your secret. Reject anything older than five minutes, and verify against the raw bytes before parsing.

Verify a webhook
# EduMark POSTs JSON to your HTTPS endpoint with:
#   X-EduMark-Signature: t=1729503000,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
#   X-EduMark-Event-Id:  wh_3f1c9a…   (deduplicate on this; delivery is at least once)
# The signature is HMAC-SHA256 of "<t>.<event id>.<raw body>" with your webhook secret.
# Answer 2xx within 5 seconds. Failed deliveries retry after 1 min, 5 min, 30 min, 2 h and 6 h.

Retries and replays

Delivery is at least once: deduplicate on the event id. If your endpoint fails, EduMark tries again after 1 minute, 5 minutes, 30 minutes and 2 hours (five tries in all), then stops; after five failures in a row your team gets an email. You can see every delivery in the console and replay any of them.

NextFiles and uploads