Skip to main content

Take action on moderation results

Connect moderation outcomes saved as metadata to downstream actions - with Workflow Agent or your own webhooks

Once moderation results are saved as structured metadata, they stop being just a record of what happened and become a trigger for what happens next. Because the outcome now lives on the asset itself, anything that can read Cloudinary metadata can act on it - automatically.

What you can automate

A few common examples:

  • Approved → set the asset's access control to public so it can go live.

  • Needs review → notify the right people on Slack, Microsoft Teams, email, or your task tracker so review doesn't wait on someone noticing.

What to do with rejected assets

Rejection doesn't have to mean a dead end. Depending on why the asset failed and who owns it, you can:

  • Send it back to whoever submitted it - notify the seller, contributor, or agency with the rejection reason attached, so they can fix and resubmit without anyone chasing them manually.

  • Move it to a quarantine folder - relocate rejected assets to a dedicated folder (for example /rejected or /pending-fix) so they're out of the way of production queries but still available for review.

  • Delete it - for clear-cut violations you never want stored, remove the asset outright. Worth pairing with a notification so the deletion isn't silent.

  • Fix it automatically with a transformation - crop out a problem area, blur a face, or change the background, instead of discarding an otherwise usable asset.

  • React to the specific rejection reason - the reason is saved as metadata too, so you can branch on it. If the reason is AI generated, add an "AI generated" overlay to the asset and keep using it, rather than blocking it the way you would a genuine policy violation.

Because the rejection reason is a separate metadata field from the result, you can treat "rejected" as a routing decision rather than a single fate - overlay one reason, quarantine another, delete a third.

The pattern is always the same: the metadata value decides the action.

Before you start: downstream automation only works if results are actually written to the assets. Turn on "Automatically write moderation result to Structured Metadata" in Settings, or save metadata manually after each run. See Save moderation results as metadata.

Option 1: Cloudinary Workflow Agent (no code)

Workflow Agent lets you build these automations inside Cloudinary, without writing or hosting anything. You describe the condition and the action - "when moderation result is Approved, make the asset public," "when moderation result is Rejected, move the asset to /rejected and email the contributor," "when the rejection reason is AI generated, apply the AI-generated overlay" - and the workflow runs whenever a matching asset appears.

This is the best starting point for most teams: transformations, access control changes, moving and deleting assets, tagging, routing, and notifications are all available as workflow steps, and everything stays in one place alongside your assets.

Option 2: Webhooks and your own service

If the action lives in your own systems - your CMS, PIM, seller portal, review queue, or approval service - you can connect moderation outcomes over the API instead.

When Moderation writes a result to an asset's structured metadata, that metadata change fires a Cloudinary webhook notification (resource_metadata_changed). Your endpoint receives the asset and its updated metadata, and can then do whatever your workflow requires - reopen the submission in your seller portal, file a task, or trigger your own cleanup.

Filtering to just the notifications you need

Metadata changes happen for all sorts of reasons, not only moderation - so a raw feed of resource_metadata_changed events will include plenty your service doesn't care about. Rather than receiving everything and discarding most of it, you can attach a filter to the webhook trigger so it only fires when the moderation fields are present or match a specific value.

Filters are written as JSONLogic expressions and configured on the Admin API trigger endpoint. Typical uses:

  • Fire only when the moderation status field changes to a particular value, such as approved or rejected.

  • Fire only for a particular rejection reason, so the "AI generated" flow and the "policy violation" flow hit different endpoints.

  • Fire only for assets in a particular folder - handy for keeping dev, test, and production callbacks separate without splitting environments.

Full details, including the request format and the supported expressions:

Tip: if you use custom structured metadata fields instead of Moderation's default ones, filter on your own field names. See "Moderation settings" for custom field mapping.

Which option should I use?

  • The action happens to the asset (transformations, access control, moving, deleting, tags, overlays) or is a notification → start with Workflow Agent.

  • The action happens in your own system, or depends on data Cloudinary doesn't hold → use webhooks with a filtered trigger.

The two aren't exclusive - many teams handle asset-level fixes in Workflow Agent and send the remaining cases to their own service.


Related articles

Did this answer your question?