Skip to content

Work with files in a run

Who this is for: people who write workflows that make reports, read exports or send files by email.

Before you start: you need the Edit workflows permission (edit_workflow) to change a workflow, and the View runs permission (view_runs) to download a run’s files. Every role can view runs.

A step can store a file, called an artifact: a CSV export, a PDF report or a zip file from a supplier. Later steps in the same run use it as ${{ artifacts.<name> }}, and you can download it from the run page. This page shows how.

Use a built-in action, or a script step.

- id: overdue
name: Build the overdue list
uses: platform/csv.build@v1
with:
rows: ${{ steps.fetch.outputs.items }}
filename: overdue.csv

In a script step, call ctx.artifacts.put("overdue.csv", text, { contentType: "text/csv" }). See the host API.

A file name has letters, digits, ., _ and -, and starts with a letter or a digit. A run can’t store two files with the same name.

By default, csv.build puts a ' in front of any text cell that starts with =, +, -, @, a tab or a line break, so a spreadsheet never runs it as a formula.

When a supplier sends a zip file, unpack it with unzip. Every file inside becomes a file of the run.

- id: unpack
name: Unpack the order export
uses: platform/unzip@v1
with:
artifact: "${{ artifacts['orders.zip'] }}"
prefix: in-

Folders in the archive become part of the name: 2026/orders.csv becomes in-2026_orders.csv. Archives that try to write outside the run, that unpack to far more than their size, or that hold links or passwords are refused before any file is stored.

To pack files into one zip file, use zip.

List the files under attachments in email.send.

- id: mail
name: Email the report
uses: platform/email.send@v1
with:
to: [finance@example.com]
subject: Overdue invoices
text: The list is attached.
attachments: ["${{ artifacts['overdue.csv'] }}"]

An email can carry 10 files and 20 MB of attachments. A file name in an email is cleaned of characters that mail programs misread. A file keeps a type such as CSV, PDF or PNG only when its contents agree. Anything else, web pages and SVG images included, is attached as a plain download, so it never opens inside the mail program.

To fetch a file from SharePoint or OneDrive into the run, use ms365.download-file. To file a run’s file there, use ms365.upload-file. To email it from a shared mailbox in Microsoft 365, use ms365.send-mail. They need a Microsoft 365 connection.

- id: upload
name: File the report in SharePoint
uses: library/ms365.upload-file@v1
connections:
graph: m365
with:
site: contoso.sharepoint.com:/sites/Finance
folder_path: Reports/2026
file: "${{ artifacts['overdue.csv'] }}"
  1. Open Runs and select the run.
  2. Under Files, select Download next to the file.

The file is always saved, never opened in the browser. A file that has expired is no longer listed. With an API token you can download it from GET /api/v1/runs/{run_id}/artifacts/{artifact_id}.

A run’s files are kept as long as your plan keeps run logs, unless your plan sets a separate time for files. After that, the file and its contents are deleted within the hour, and a download answers “not found”. Files count toward your plan’s storage. See Limits per plan.

A test run’s files belong to that test run. A retry of a test run can’t continue from a production run, or the other way round, so a test never picks up production files.

What you see What to do
artifact_too_large The file, or all of the run’s files together, is over the limit. Split the work into smaller files or fewer steps.
limit_exceeded The run already stored 100 files. Pack them with zip first.
artifact_exists Two steps made a file with the same name. Give one another filename, or use prefix with unzip.
quota_exceeded Your company’s storage is full. Older files free their space when they expire.
invalid_input from unzip The file is not a zip file, it is damaged or password protected, it holds a link, or two files in it would get the same name.