Build a first media automation flow from blocks
Build a first MediaFlows automation by picking the trigger before anything else, starting from a PowerFlow template rather than a blank canvas, wiring blocks by their contracts, and putting retry and failure branches only on blocks that call outside the platform. Version one handles one asset end to end; every case comes later.
Before you start
You need a Cloudinary product environment with MediaFlows enabled — the Free plan qualifies as of 2026-08-18, per Cloudinary’s pricing page — and one real asset you can upload repeatedly without caring what happens to it. Not a folder of assets. One. The whole method below depends on watching a single asset go through the flow and being able to say exactly which block did what to it.
You also need to know, in one sentence, what the flow does. ‘Tag new uploads with the product SKU from the filename and move them to the catalogue folder’ is a flow. ‘Handle our incoming media’ is not; it is a backlog, and a canvas will not turn it into a flow for you.
If you have not yet decided whether a visual flow is the right tool at all — as against a webhook handler you write yourself — settle that first: a hosted visual automation against a hand-written webhook handler covers the conditions under which each wins.
Steps
-
Choose the trigger, and only then think about the logic.
A flow starts from a trigger and everything downstream is shaped by it, so this is not a form field you fill in on the way past. Cloudinary’s guide to building a flow walks through picking the trigger before placing any other block, and that ordering is the correct one for a reason it does not spell out: per-asset work and batch work need different error handling even when the transformation logic is identical.
A flow fired once per uploaded asset can afford to fail loudly and stop — one asset is affected, the event can be replayed, and nothing else was in flight. A flow fired over a batch (a folder, a CSV, a scheduled sweep) cannot stop on the first bad row, because the other 400 rows were fine and stopping loses them. The batch flow needs per-item isolation and a place to park failures; the per-asset flow does not, and adding it there is dead weight. If you pick the logic first and bolt a trigger on afterwards, you discover this at the point where the flow half-processed a batch and you cannot tell which half. The trigger types available to a hosted media automation go through what each trigger implies for the shape downstream.
For a first flow, pick the per-asset trigger — an upload event — even if the eventual job is a batch. It is the smaller error surface, and step 5 depends on it.
-
Start from a template, not an empty canvas.
Cloudinary ships PowerFlows — prebuilt flows for the common shapes: moderation, user-generated-content deletion, multilingual alt text, CSV-driven upload. One of them is close to what you want more often than not, and if none is close, one of them still has the trigger and the wiring pattern you need. Open the nearest one, read it block by block, and change the blocks that differ.
This is also how you should think about the build-versus-buy question for the flow itself. The comparison worth making is never ‘a blank canvas versus writing code’ — it is ‘an adapted template versus writing code’, because the template is what you would actually start from. A template that gets you 80% of the way changes the arithmetic on whether the last 20% is worth doing in a canvas at all; the point where a media automation should become code is about locating that line, and it moves depending on how good the nearest template is.
If the natural-language route (EasyFlows) is on the table, note that it produces a flow too — the choice between drawing the canvas and describing it is a separate decision, covered in low-code canvas flows against no-code natural-language flows. For a first flow the canvas is the better teacher, because you see the blocks.
-
Wire the blocks by their contracts, not by what you imagine they do.
A flow is a set of functional blocks wired into a sequence. The unit of work is therefore a block’s contract — what it accepts, what it emits, what it does when the input is not what it expected — rather than a line of code. This changes what ‘reading the flow’ means. You do not read logic; you read interfaces, and the block reference is the document that states them.
Practically: for each block you place, look up its inputs and outputs before you connect it, and check that the previous block actually emits the field the next block consumes. The most common first-flow failure is not a wrong block; it is a right block fed a field that is present in the trigger payload for one asset type and absent for another. That is a contract mismatch, and it is invisible on the canvas because the wire draws fine either way. Reading the reference costs minutes; discovering it in production costs an incident.
Resist adding a block whose purpose you cannot state as an input-to-output transformation. If a block is there ‘in case’, it is a contract you have not read yet.
-
Put the retry path and the failure branch on the blocks that leave the platform — and nowhere else.
Blocks that operate on the asset inside Cloudinary — a transformation, a tag, a move, a metadata write — run against the platform’s own state and either succeed or fail deterministically for a given input. Blocks that call outside the platform — an HTTP request to your PIM, a post to a social API, a webhook to your own service, a third-party model — are the ones that fail non-deterministically: timeouts, rate limits, a 502 from the other side. Those are where a retry path belongs, and those are where a failure branch belongs.
Doing this everywhere is the mistake it looks like. A retry on an internal block retries something that will fail identically the second time, and a failure branch on every block turns a five-block flow into fifteen and hides the two branches that matter. Put the retry and the failure branch on the external calls, route the failure branch somewhere a person will actually look, and leave the internal blocks bare. Error handling and retries in a hosted media automation goes further into what the failure branch should do with what it catches; for the first version, ‘tag the asset and stop’ is enough.
For a first flow that has no external call at all, this step is a no-op, and that is a feature. Notice that the moment you add one, the retry and the branch come with it.
-
Make version one do one thing, end to end, for one asset.
Upload the single asset from the prerequisites. Watch it enter at the trigger, pass through each block, and arrive at the state you described in one sentence before you started. Then upload it again and confirm the same result. That is version one, and it should be the whole of version one.
A flow that handles every case before it has handled one is the no-code equivalent of premature abstraction. The canvas makes it cheap to add a branch for the PNG case, the video case, the missing-SKU case, and the case where marketing uploads to the wrong folder — and each of those branches is a contract you have not tested, feeding a block you have not read the reference for, on a path no asset has yet taken. When the flow misbehaves, you will not know which of nine untested branches is at fault. Get one asset through one path, confirm it, and add the second case only when a second real asset demands it. The cases you were sure would arrive often do not.
Save the working version before you touch it again. A visual canvas has no diff by default; version control for automations built on a visual canvas covers how to keep the one-asset version recoverable once you start extending it.
Done looks like this
One asset, uploaded, arrives at the described end state every time, and you can name the trigger, list each block with its input and output, and point to the exact block — if any — where an external call is retried and where its failure goes. The flow was adapted from a named PowerFlow, and the blocks that differ from it are the ones that carry the job you specified in one sentence. There is no branch for a case no asset has yet exercised. Everything past that is version two.
Sources
- Cloudinary's pricing pagecloudinary.com
- guide to building a flowcloudinary.com
- PowerFlowscloudinary.com
- block referencecloudinary.com
See also
How to run a one-off bulk media migration from a spreadsheet using a published CSV upload flow: validation, metadata, rate limits and resumable rows.
How to export media asset metadata to CSV for review in a spreadsheet, filter it with search expressions, and round-trip edits back without losing the thread.
A symptom-first checklist for a CMS media plugin that stops delivering: separate upload, storage and delivery, then test the URL outside the CMS.
How a commerce integration ties assets to products, defines renditions, handles variant sprawl, and what happens to media when a product is deleted.