GitHub Actions Upload Artifact to Public URL with cURL
GitHub Actions artifacts are good for storing files from a workflow run. They are not always the right shape when you need a public URL for a customer, a stakeholder, a webhook, or an external system.
If your workflow produces an HTML report, PDF, screenshot, ZIP, or release file and you need a direct public link, upload it to FilePost with cURL during the workflow.
Why Not Just Use GitHub Artifacts?
GitHub's artifact system is built for workflow storage and sharing between jobs. GitHub documents artifact retention and configurable retention periods for workflow artifacts. That is useful, but it is not the same as a permanent public CDN URL.
Use GitHub artifacts for developer workflow storage. Use FilePost when another system needs a normal HTTPS link.
Official reference: GitHub docs: store and share data with workflow artifacts.
Step 1: Add Your API Key as a Secret
In your repository settings, add a secret named FILEPOST_API_KEY. Never hardcode the key in the workflow file.
Step 2: Upload the File
This example uploads an HTML report and writes the resulting URL to the GitHub step summary.
name: Upload report
on:
workflow_dispatch:
jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build report
run: |
mkdir -p dist
echo "<h1>CI report</h1>" > dist/report.html
- name: Upload report to FilePost
env:
FILEPOST_API_KEY: ${{ secrets.FILEPOST_API_KEY }}
run: |
URL=$(curl -sS -X POST https://filepost.dev/v1/upload \
-H "X-API-Key: $FILEPOST_API_KEY" \
-F "file=@dist/report.html" | jq -r '.url')
echo "REPORT_URL=$URL" >> "$GITHUB_ENV"
echo "### Public report URL" >> "$GITHUB_STEP_SUMMARY"
echo "$URL" >> "$GITHUB_STEP_SUMMARY"
Step 3: Use the URL Later in the Workflow
After the upload step, later steps can read $REPORT_URL. For example, send it to a webhook:
- name: Notify external system
run: |
curl -sS -X POST https://example.com/webhook \
-H "Content-Type: application/json" \
-d "{\"report_url\":\"$REPORT_URL\"}"
Upload a ZIP Build Output
- name: Zip build output
run: zip -r build.zip dist/
- name: Upload ZIP to FilePost
env:
FILEPOST_API_KEY: ${{ secrets.FILEPOST_API_KEY }}
run: |
curl -sS -X POST https://filepost.dev/v1/upload \
-H "X-API-Key: $FILEPOST_API_KEY" \
-F "file=@build.zip"
Upload a Temporary Preview
If the URL should expire, use the base64 endpoint only when your file is already a string. For a normal file on disk, keep using multipart. FilePost supports expiration on upload flows that include expires_in; use it for generated previews that should disappear later.
Good CI Use Cases
- Playwright screenshot bundles for a failed test run.
- HTML coverage reports for a pull request comment.
- Generated PDFs that need approval outside GitHub.
- ZIP files from a release pipeline.
- Static preview assets that should be shared in Slack or Linear.
Troubleshooting
jq: command not found
GitHub's Ubuntu runners normally include jq, but if your runner does not, install it or use a small Node/Python parser. The upload still works; parsing the URL is the only part that needs jq.
401 invalid API key
Check that the secret name is exactly FILEPOST_API_KEY and that the workflow has access to repository secrets. For pull requests from forks, GitHub restricts secrets by design.
413 file too large
Check your FilePost plan limit. Free supports 50 MB, Starter supports 200 MB, and Pro supports 500 MB per file.
Upload CI files to a public CDN URL
Use one cURL command in GitHub Actions and share reports, screenshots, and build files outside GitHub.
Get Your API Key