Event Subscriptions

Receive webhook push notifications when processing reaches a terminal state

Event subscriptions let Plextera push product events to your webhook endpoint. Use them when your integration should react to completed, failed, or rejected processing without polling.

When to use events

PatternRecommended for
Polling onlySimple backend integrations, local testing, or flows where delayed processing is acceptable.
Events onlyProduction integrations that need push notifications and lower API traffic.
Events plus pollingRobust production integrations. Use events for the normal path and polling as a fallback status check.

A common production pattern is: subscribe to terminal events, process webhook deliveries immediately, and periodically poll resources that have not completed after an expected time window.

Available events

EventDelivered whenPayload
document-insights.extraction.completedA document extraction reaches COMPLETED.Full extraction with output.
document-insights.extraction.failedA document extraction reaches FAILED.Extraction state with error.
document-insights.extraction.rejectedA document extraction reaches REJECTED.Extraction state with error.
workflow.run.completedA workflow run reaches COMPLETED.Full workflow run with step outputs.
workflow.run.failedA workflow run reaches FAILED, or is closed in Plextera Studio (CLOSED).Workflow run state with error.

Closing a run in Plextera Studio is treated as a failure outcome for event delivery: subscribers of workflow.run.failed receive an event whose run status is CLOSED. Check the status field in the payload if your handler needs to distinguish the two.

Setup

1

Create an event subscription

Call POST /event-subscriptions with:

  • endpointUrl - the HTTPS URL Plextera should POST events to.
  • eventTypes - one or more event types to subscribe to.
  • signingSecret - a secret used to sign deliveries.
  • filters - optional filters for workflow events, for example a specific workflow ID.
$curl -X POST https://api.plextera.com/api/public/v1/event-subscriptions \
> -H "Authorization: api-key YOUR_API_KEY" \
> -H "Content-Type: application/json" \
> -d '{
> "endpointUrl": "https://example.com/webhooks/plextera",
> "eventTypes": [
> "document-insights.extraction.completed",
> "document-insights.extraction.failed",
> "document-insights.extraction.rejected"
> ],
> "signingSecret": "whsec_your_secret"
> }'

Document Insights subscriptions rarely need filters — the event types already select what is delivered. The response omits filters when none are configured.

2

Implement your webhook endpoint

Your endpoint must:

  • Accept POST requests with a JSON body.
  • Read the raw request body for signature verification.
  • Return a 2xx status within 15 seconds — acknowledge first, then process the event asynchronously. Slow responses time out and count as failed deliveries.
  • Handle duplicate deliveries safely.
3

Verify the signature

Verify the X-Plextera-Signature header before trusting the event payload.

Event payload model

Every event uses a common envelope:

1{
2 "eventId": "evt_01JY7M9QWBWCPMZK5QJ7RSE9P4",
3 "eventType": "document-insights.extraction.completed",
4 "occurredAt": "2026-04-07T10:22:00Z",
5 "apiVersion": "v1",
6 "data": { ... }
7}

The data field contains the event-specific payload. See the Event Reference for complete schemas and examples.

Delivery headers

Every webhook delivery includes:

HeaderDescription
X-Plextera-Delivery-IdUnique ID for this delivery attempt.
X-Plextera-Event-IdID of the event, stable across retry attempts.
X-Plextera-Event-TypeEvent type string.
X-Plextera-Event-Occurred-AtISO 8601 timestamp when the event occurred.
X-Plextera-Api-VersionAPI version, for example v1.
X-Plextera-SignatureHMAC-SHA256 signature for payload verification.

Verifying signatures

Each delivery is signed using the signingSecret you provided when creating the subscription. This confirms the delivery came from Plextera and that the payload was not modified.

Signature format:

X-Plextera-Signature: t=<unix timestamp>,v1=<hex hmac-sha256>

Verification steps:

  1. Extract t and v1 from the header.
  2. Construct the signed payload: <t>.<raw request body>.
  3. Compute HMAC-SHA256 using your signingSecret.
  4. Compare the computed signature with v1 using a constant-time comparison.
  5. Optionally reject old timestamps for replay protection.
1import hashlib
2import hmac
3import time
4
5
6def verify_signature(
7 payload: bytes,
8 header: str,
9 secret: str,
10 max_age_seconds: int = 300,
11) -> bool:
12 parts = dict(p.split("=", 1) for p in header.split(","))
13 timestamp = int(parts["t"])
14 signature = parts["v1"]
15
16 if abs(time.time() - timestamp) > max_age_seconds:
17 return False
18
19 signed = f"{timestamp}.".encode() + payload
20 expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
21 return hmac.compare_digest(expected, signature)

The signing secret is write-only. Plextera never returns it in API responses. Store it securely and rotate it by updating the subscription with a new signingSecret.

Retry and idempotency

  • The same eventId may be delivered more than once.
  • Your webhook handler should be idempotent. Store processed eventId values or use your own deduplication key.
  • If a document is reprocessed after a terminal state, a later terminal state can produce a new event.

Inspect deliveries

Use GET /event-subscriptions/{subscriptionId}/deliveries to see what Plextera actually sent to your endpoint - newest first, with an optional status filter (pending, retrying, delivered, failed).

$curl "https://api.plextera.com/api/public/v1/event-subscriptions/sub_.../deliveries?status=failed" \
> -H "Authorization: api-key YOUR_API_KEY"

Each delivery shows its status, attemptCount, the last HTTP responseStatusCode your endpoint returned, the last error, and nextAttemptAt for scheduled retries. This is the fastest way to debug a misbehaving webhook endpoint: if deliveries are retrying or failed, the response code and error tell you why.