The following 6-minute video shows how to use the Unstructured API to work with webhooks:
For Unstructured webhooks, Unstructured is the sender,
and your solution is the receiver. Some popular receiver solutions include
AWS Lambda,
Azure Functions,
Google Cloud Run,
Zapier,
Slack,
Svix, and
Webhook.site.
The receiver provides a unique URL, called the
webhook URL, to receive the data that Unstructured sends.
Behind the scenes, when specific events happen in Unstructured, Unstructured automatically calls the webhook URL by using an HTTP POST operation and
passes JSON payloads related to those events to the receiver. The receiver then processes the payload and decides what to do with the data.
Because webhooks are event-driven, some event must first be triggered to begin generating the related data to be sent. In
Unstructured, these webhooks can be triggered whenever a job that is associated with its target workflow does
one or more of the following:
- Is scheduled to start running later (programmatically, an event type of
job.scheduled) - Has begun running (
job.in_progress) - Has stopped running (
job.stopped) - Has failed (
job.failed) - the job either failed to initialize and did not process any files, or all files failed to process. When all files fail, the payload includesreason: "All files failed to process"andcounts_final: true. - Has completed (
job.completed) - the job initialized and finished processing, including cases where some (but not all) files failed. The payload includesnum_docs,num_docs_succeeded,num_docs_failed, andcounts_final.
job.completed and job.failed HTTP POST approximately 10 seconds after a job finishes, allowing time for per-file count fields in the payload to reflect the final result. Other events (job.scheduled, job.in_progress, job.stopped) are sent immediately.
When a webhook is configured to deliver event-driven notification data payloads from a sender to a receiver, this configuration
is called a notification channel. For Unstructured webhooks, notification channels can be created and managed at the following levels:
-
At the workspace level, known as a workspace-scoped notification channel. This allows any job that is associated with a
workspace in an Unstructured account to trigger the webhook. This can be useful, for example, for routing pager requests to a team of on-call engineers in an
IT operations center whenever a job fails across the workspace.
Each Let’s Go or Pay-As-You-Go account has one and only one workspace.An Unstructured Business account can have multiple workspaces.
- At the workflow level, known as a workflow-scoped notification channel. This allows any job that is associated only with the target workflow in an Unstructured account to trigger the webhook. This can be useful, for example, for emailing a department’s data analyst when a long-running job for a specific workflow has completed, allowing them to begin working with the latest output.
Unstructured Pipelines allows only limited creation, viewing, and management of webhooks, as follows (learn how):
- Webhooks for a personal Unstructured workspace. Each personal Unstructured account has one and only one personal Unstructured workspace.
- Webhooks for a workspace within an Unstructured Business account.
Payload schema and examples
Every webhook delivers an HTTP POST with a JSON body containing a top-level envelope and ajob object with event-specific details.
Top-level fields
| Field | Type | Description |
|---|---|---|
event_id | string | Unique identifier for this notification delivery. |
type | string | Event type: job.scheduled, job.in_progress, job.stopped, job.completed, or job.failed. |
timestamp | string | ISO 8601 UTC timestamp when the event was dispatched. |
tenant_id | string | UUID of the Unstructured account that owns the job. |
job | object | Job details. See the job object fields table below. |
Job object fields
| Field | Type | Present on | Description |
|---|---|---|---|
job_id | string | All events | UUID of the job. |
workflow_id | string | All events | UUID of the workflow the job belongs to. |
workflow_name | string | All events | Display name of the workflow. |
status | string | All events | Job status at time of event: SCHEDULED, IN_PROGRESS, STOPPED, COMPLETED, or FAILED. |
job_type | string | All events | How the job was triggered: scheduled or ephemeral. |
created_at | string or null | All events | ISO 8601 UTC timestamp when the job was created. |
completed_at | string or null | All events | ISO 8601 UTC timestamp when the job reached a terminal state. null for non-terminal events. |
processing_time_ms | integer or null | All events | Elapsed time from creation to terminal state, in milliseconds. null for non-terminal events. |
num_docs | integer or null | All events | Total files discovered for the job. null until counts are reported. |
num_docs_succeeded | integer or null | All events | Files that processed successfully. null until counts are reported. |
num_docs_failed | integer or null | All events | Files that failed to process. null until counts are reported. |
counts_final | boolean | job.completed, job.failed | true if all file processing counts are complete. false if the polling window closed before all file processing counts were accounted for. Only present on job.completed and job.failed events. |
reason | string | job.failed (all files failed) | Reason for failure. Value: "All files failed to process". Only present when all files failed, not set for init failures. Check num_docs to distinguish the two cases: null indicates the job failed before processing any files. |
When
counts_final is false, the polling window closed before all file processing counts were accounted for. Unstructured determines completeness by checking whether num_docs_succeeded + num_docs_failed equals num_docs. To confirm final counts, call Get processing details for a job.Examples
job.completed — all files succeeded
job.completed — all files succeeded
All files processed successfully.
num_docs_succeeded equals num_docs, num_docs_failed is 0, and counts_final is true.job.completed — partial failure (some files failed)
job.completed — partial failure (some files failed)
num_docs_failed is set to 1, indicating one file failed while the rest succeeded. The job still reports as job.completed.job.failed — all files failed
job.failed — all files failed
Every file in the job failed to process.
num_docs_failed equals num_docs, reason is set, and counts_final: true confirms the counts are complete.job.failed — failed to initialize
job.failed — failed to initialize
The job could not start. No files were processed, so
num_docs fields are null and counts_final is false.Verify webhook requests
Your receiver application can verify incoming webhook requests to check that the payload originated from Unstructured and was not tampered with in transit. Use the webhook secret to verify incoming requests. If you suspect that the secret has been compromised, rotate it to a new value. The following Python example reads the webhook ID, timestamp, and signature from the request headers and checks that the timestamp is within an acceptable time window. Next, it recomputes the expected HMAC-SHA256 signature from the webhook ID, timestamp, and raw request body using the notification channel secret. It then compares the computed signature to the versioned signature in the request header. If the values match, the request can be trusted as originating from Unstructured and as not having been tampered with in transit.Python
Python
Requirements
To create, view, and manage webhooks, Unstructured provides a set of Representational State Transfer (REST) endpoints. You can call these endpoints through standard REST-enabled utilities, tools, programming languages, packages, and libraries. To call the Unstructured API’s webhook operations, you must have an Unstructured API URL and a valid Unstructured API key. To get your Unstructured API URL, do the following:-
If you do not already have an Unstructured account, sign up for free.
After you sign up, you are automatically signed in to your new Unstructured Let’s Go account, at https://platform.unstructured.io.
To sign up for a Business account instead, contact Unstructured Sales, or learn more.
-
If you have an Unstructured Let’s Go, Pay-As-You-Go, or Business SaaS account and are not already signed in, sign in to your account at https://platform.unstructured.io.
For other types of Business accounts, see your Unstructured account administrator for sign-in instructions, or request support.
-
Get your Unstructured API URL:
a. After you sign in to your Unstructured Let’s Go, Pay-As-You-Go, or Business account, click API Keys on the sidebar.
b. Copy the value of Unstructured API Endpoint to your system’s clipboard.For a Business account, before you click API Keys, make sure you have selected the organizational workspace you want to get the API URL for. Learn more.
-
If you do not already have an Unstructured account, sign up for free.
After you sign up, you are automatically signed in to your new Unstructured Let’s Go account, at https://platform.unstructured.io.
To sign up for a Business account instead, contact Unstructured Sales, or learn more.
-
If you have an Unstructured Let’s Go, Pay-As-You-Go, or Business SaaS account and are not already signed in, sign in to your account at https://platform.unstructured.io.
For other types of Business accounts, see your Unstructured account administrator for sign-in instructions, or request support.
-
Get your Unstructured API key:
a. After you sign in to your Unstructured Let’s Go, Pay-As-You-Go, or Business account, click API Keys on the sidebar.
b. Click Generate API Key.For a Business account, before you click API Keys, make sure you have selected the organizational workspace you want to create an API key for. Each API key works with one and only one organizational workspace. Learn more.
c. Follow the on-screen instructions to finish generating the key.
d. Click the Copy icon next to your new key to add the key to your system’s clipboard. If you lose this key, simply return and click the Copy icon again.

