Skip to content
  • There are no suggestions because the search field is empty.

Originality Webhooks

Webhooks in Originality notify your systems when documents and reports change, so you can react to events instead of polling the API.

When a subscribed event occurs, Originality sends a signed HTTP POST to the endpoint you have configured. Each delivery is signed with HMAC-SHA256 so you can verify it came from us and was not altered in transit.

Webhook endpoints are configured per licence in the Originality user interface. They are not managed through the public API.

In this article:

  • How to configure Originality webhooks
  • Delivery behavior
  • Request structure
  • Available events
  • Troubleshooting

How to configure Originality webhooks

  1. In Originality, go to License settings > Webhooks tab.
  2. Select Add Webhook.
  3. Enter your Endpoint URL. It must be a valid HTTPS URL.
  4. Under Event Subscriptions, select the events you want to receive. All five are selected by default – deselect the ones you do not need, or use Clear all and pick individually.
  5. Select Create & Continue.
  6. The signing secret is displayed. Copy the secret and store it securely – it is only shown once.

You can configure up to five webhook endpoints per license. The limit applies to the license as a whole, not per user, so endpoints created by different administrators count towards the same total.

To change an endpoint URL or its subscriptions, edit the webhook in the same tab. The signing secret is not regenerated when you edit, and it cannot be displayed again – if you lose it, delete the webhook and create a new one.

Delivery behavior

At-least-once delivery. Your endpoint may receive the same event more than once. Use the X-Originality-Delivery-ID header to deduplicate, and make sure your handler produces the same result when it processes the same delivery twice.

No guaranteed ordering. Events are delivered from a queue and are not ordered. Do not assume document.created arrives before document.report.created for the same document. Where order matters, use the createdAt field and your own record of the document's state rather than arrival order.

Respond quickly. Return a 2xx status within 10 seconds. Any response outside the 2xx range, or no response at all, counts as a failed delivery. Acknowledge first and do the work on a background queue.

Retries. Failed deliveries are retried automatically with exponential back-off for up to 16 hours after the first attempt. After that the event is permanently discarded and will not be delivered again.

No delivery history. Originality does not store a log of webhook deliveries that you can inspect. If your endpoint is down beyond the retry window, those events are gone — if such case occurs, reconcile the affected documents through the API.

Request structure

Every delivery is a POST with a JSON body.

Headers

Header Description
Content-Type Always application/json.
User-Agent Always originality-hookshot/1.0. Useful for allow-listing our traffic.
X-Originality-Delivery-ID Identifies this delivery. Use it to deduplicate retried events.
X-Originality-Signature-256 HMAC-SHA256 of the raw request body, base64-encoded.
X-Originality-Resource The resource the event concerns: document or document.report.
X-Originality-Action What happened: created, updated or deleted.
X-Originality-Webhook-ID Which of your configured endpoints this was sent to. Useful when several endpoints share one handler.
X-Originality-Timestamp When the event was produced, in UTC.

Determining the event type. The body does not contain an event name. Combine the two headers to get the event type — X-Originality-Resource: document.report plus X-Originality-Action: created is document.report.created. Route on the headers, not on the shape of the body: document.report.created and document.report.deleted carry structurally identical bodies and differ only in whether report is populated.

Body

The body is the affected object itself, with no wrapping envelope:

{
  "id": 1637462,
  "filename": "Eigenvalues and Eigenvectors Problems 1.pdf",
  "createdAt": "2026-06-08T08:19:18.094412Z",
  "report": {
    "status": "complete",
    "score": 1,
    "opened": false
  },
  "context": null,
  "settings": {
    "analyze": true,
    "index": true
  }
}
Field Type Description
id integer The Originality document ID. Use this to correlate with your own records.

filename

string The submitted file name.
createdAt string When the document was created.
report object or null The report, when one exists. null before processing completes and after a report is deleted.
report.status string Terminal processing state — complete (report ready), available (indexed, no report produced) or failed (processing did not succeed).
report.score number The similarity score.
report.opened boolean Whether the report has been opened by a user.
context object or null Integration context, where the submitting system supplied one.
settings.analyze boolean Whether the document was analysed for similarity.
settings.index boolean Whether the document was indexed as a future source.

Available events

Document Created – Triggered when a new document is submitted. The report has not been produced yet, so report is null.

{
"id": 1234567,
  "filename": "LAE-Assign-Prob.pdf",
  "createdAt": "2026-06-09T06:36:00.528539141Z",
  "report": null,
  "context": null,
  "settings": {
    "analyze": true,
    "index": false
  }
}

Document Deleted – Triggered after a document has been fully removed, including its database record, stored files and vector data. Only the ID is sent, because nothing else remains.

{
"id": 1234567
}

Report Created – Triggered when processing reaches a terminal state — a successful similarity score, index-only completion, or a processing failure. Check report.status rather than assuming success: this event fires for failures too.

{
"id": 1234567,
  "filename": "Eigenvalues and Eigenvectors Problems 1.pdf",
  "createdAt": "2026-06-08T08:19:18.094412Z",
  "report": {
    "status": "complete",
    "score": 1,
    "opened": false
  },
  "context": null,
  "settings": {
    "analyze": true,
    "index": true
  }
}

Report Updated – Triggered when a report's similarity score changes, either because sentences were excluded or restored, or because a parallel analysis updated the result. A document can produce several of these over its lifetime, so treat the latest as authoritative rather than accumulating changes.

{
"id": 1234567,
  "filename": "image-20231017-154213.png",
  "createdAt": "2026-06-09T12:22:14.237115Z",
  "report": {
    "status": "complete",
    "score": 1,
    "opened": true
  },
  "context": null,
  "settings": {
    "analyze": true,
    "index": true
  }
}

Report Deleted – Triggered when a report is cleared for reprocessing, resetting the document to an in-progress state. The document itself remains; report returns to null. Expect a document.report.created for the same document once reprocessing finishes.

{
"id": 1234567,
  "filename": "Eigenvalues and Eigenvectors Problems 1.pdf",
  "createdAt": "2026-06-08T08:19:18.094412Z",
  "report": null,
  "context": null,
  "settings": {
    "analyze": true,
    "index": true
  }
}

Troubleshooting

  • Signature never matches. Check that you are hex-encoding the digest instead of base64, or you are hashing a re-serialised body instead of the raw bytes.

  • Events stopped arriving. Deliveries that fail for 16 hours are discarded permanently and are not resent when your endpoint recovers. Reconcile the gap through the API using the document IDs.
  • Duplicate events. Expected behaviour. Deduplicate on X-Originality-Delivery-ID.

  • Cannot tell which event arrived. Read X-Originality-Resource and X-Originality-Action. The body carries no event name.