Skip to main content
Updated Oct 23, 2026

Download to Storage

Use this action when you want to download a file from an external URL and stream it directly into your company storage.

Best for​

  • Files too large for the HTTP request action's 5 MB response cap — this action streams up to 500 MB without buffering the file in memory
  • Saving a remote file once, then reusing its stored reference or signed URL in later steps
  • Importing media (images, videos, audio, documents) from external systems

Main fields​

FieldWhat it does
HTTP URLCEL expression resolving to the download URL. Only GET requests are made, and only public HTTP(S) URLs are allowed
PurposeOptional. Only certain values are kept as the file's purpose; see the note below
HTTP headersOptional request headers, for example for authentication. Keys and values are CEL expressions — pair with Resolve Variables to load secrets
File NameOptional CEL expression for the stored file name. Falls back to the response's Content-Disposition header, then the URL path, then a generated name
Content typeOptional CEL expression for the MIME type. Auto-detected from the response Content-Type header or the file extension when omitted
CategoryStores the file as images, videos, audios, or documents. Auto-detected from the content type when omitted
PublicControls whether the stored file should be openly accessible (off by default)

About Purpose: the kept values are workflow_storage_upload (the default), action_response_media, dynadata, storage_manual_upload, whatsapp_catalog_product_image, template_message_media, chat_media_upload and scheduled_message_media. Any other value is stored as workflow_storage_upload, but still appears in the step log. Avatar and icon purposes (contact_avatar, company_logo, user_avatar, autochat_integration_avatar, autochat_widget_icon) are not honoured, so a workflow cannot fill those fields. Use dynadata for a file you'll attach to a record's file field.

What later steps can use​

  • workflow.step(N).status
  • workflow.step(N).file
  • workflow.step(N).signedUrl
  • workflow.step(N).contentType
  • workflow.step(N).size

workflow.step(N).file contains the stored object (bucket, fullPath, name, metadata), and workflow.step(N).signedUrl is a temporary download URL valid for about 15 minutes.

Tips​

  • Downloads are capped at 500 MB — larger transfers are aborted with download_size_limit_exceeded.
  • The downloaded bytes count toward your storage quota, and the step fails with storage_quota_exceeded when the download would not fit.
  • A non-2xx response fails the step (http_client_error or http_server_error), and the whole download must finish within 5 minutes.
  • Nothing is left behind on failure: a partially stored file is cleaned up automatically.
  • Use Create Storage Signed URL (actions/media/storage/signed-url) later when you need a fresh download link after the initial one expires.
  • Content type is normalized when the file is stored, and the step's contentType output shows the stored value. Renderable or unsafe types (HTML, SVG, XML and +xml types, multipart, comma-separated lists, malformed values) are stored as application/octet-stream. Documents are stored without parameters and must be a supported document type (PDF, plain text, CSV, JSON, ZIP, Word, Excel, PowerPoint or RTF), otherwise application/octet-stream. Images are stored without parameters. Audio and video keep only the codecs parameter, so audio/ogg; codecs=opus stays usable for voice notes. Passing contentType=maps.get(workflow.step(0),'headers.content-type') still works; the value is just normalized.