Asset pages now show an asset's events and the webhook deliveries they produced, and the asset list can filter for flagged content and sub-assets.
·5 min read
Portal
Webhooks
Events
When an integration misbehaves, the investigation often starts from one file. Your app uploaded it, CalmLens classified it, and your webhook handler should have heard about it. If the handler never ran, the cause could be on either side: the asset is still processing, it failed, the event was never raised, or the event was raised and your endpoint rejected it.
Before this release, answering that meant checking the asset in one place, the project's events in another and your webhook settings in a third. In 2026.1 the asset page puts those records together, so you can follow a single asset from upload to delivery without leaving it.
Start from the asset ID
Every asset has an ID, and the portal page for it lives at /portal/assets/<assetId>. The create call returns the asset, so record its id next to your own record when you submit content:
externalId is optional. When you set it, the asset page shows it beside the asset ID, which helps when someone reports a problem in terms of your own identifiers rather than ours.
What the asset page shows
The details panel has the asset ID, external ID, name, type, status and visibility, plus the processing options it was submitted with. If moderation has finished, the classification results sit above it with a score for each category.
Below that is an Activity panel with the asset's milestones:
Created: when CalmLens accepted the upload.
Updated: when the asset record last changed.
Processed: when classification finished. Until then this reads Pending.
Storage deleted: shown only once the stored content has been removed.
If Created is set and Processed still says Pending, classification hasn't finished. An event for the result can't have been sent yet, so there is nothing to debug on the webhook side.
Events for this asset only
Under the milestones is an event log limited to this asset. CalmLens records an event when something happens to an asset (it is uploaded, classified or flagged, for example), and each event stores the ID of the asset it concerns. The asset page asks for the project's events with an assetId==<id> filter, so you see only this asset's events, newest first.
The table works like the project-wide event log. You can sort by type, severity or time, and filtering by severity is combined with the asset filter, so a severity filter still only searches this asset's events.
Every event goes to your enabled webhook destinations, subject to each destination's event type selection, and the webhook body carries the event's ID and the asset ID. The event in this table is the same one your handler should have received.
Webhook deliveries for those events
A delivery is the record of sending one event to one webhook destination. The asset page looks up deliveries whose event belongs to this asset and lists them in a Webhook deliveries panel with the event type, delivery status, the HTTP status your endpoint returned, the error message if there was one, and when the delivery was created.
That gives you three cases to tell apart:
No event in the log: CalmLens hasn't raised the event yet, or the asset is still processing. Check the milestones and status.
An event, but no delivery for it: the event exists, but no enabled destination subscribed to its type received it. Check the destination's event selection in your webhook settings.
A delivery with a failed status: the event reached your endpoint and was refused. The response code and error message say what your endpoint returned.
The panel covers up to 100 of the asset's events and shows up to 50 deliveries. For wider questions, such as every failure for one destination, use the webhook settings instead.
The page reads all of this when it loads. Use the Refresh button in the header to reload the asset, its sub-assets and its deliveries without leaving the page. The event log reloads as well when the asset has changed.
Parents and sub-assets
Some uploads produce more than one asset. When CalmLens processes a document or a website, the images it extracts become sub-assets, each with its own classification, events and asset page, and each pointing back to the original through parentId.
A sub-asset's page links to its parent. A parent's page lists its sub-assets in a paged grid. If a document's result traces back to one image inside it, you can open that image and read its events and deliveries on its own page.
Filtering the asset list
The main asset list in the portal gets two filters in this release, alongside a switch between table and grid views.
All assets and Flagged only switch between everything in the project and assets that moderation rejected. Include sub-assets is off by default, so the list shows only top-level uploads, and extracted images don't push the files you submitted off the first page. Turn it on to see every asset in one list.
The portal remembers your view and filter choices in a cookie, so the list looks the same when you come back.
These filters are ordinary filter expressions on the asset list endpoint, so you can run the same queries from your own code:
That returns the first page of rejected top-level assets, the same set the portal shows with Flagged only selected and sub-assets hidden. The pagination and filtering guide lists the supported operators.
The webhooks guide covers setting up destinations, choosing event types and verifying signatures.
We use essential cookies to keep you signed in and the site secure. With your permission, we'll also use functional cookies to remember preferences such as your layout and documentation language, and to offer Google One Tap sign-in. We don't use analytics or advertising cookies. Manage cookies