Downloading Files - SuperAI Flows

Documentation Index

Fetch the complete documentation index at: /llms.txt

Use this file to discover all available pages before exploring further.

When SuperAI Flows processes documents, task outputs often include file references as gs:// URLs. These point to files stored in Google Cloud Storage, but you don’t need to understand GCS internals — the File API handles everything.

Example gs:// URL in a task output:

{
  "document_url": "gs://superai-file-upload-prod-eu/flows/255a17d0-5c21-47d9-8e0b-a08b48436f0a/documents/f8230da2-4136-4ffb-acfe-db9318970ea2"
}

Prerequisites

Quick start

Download a file in one command:

curl -f -L -H "X-API-Key: saf_your_api_key" \
  "https://flows.super.ai/api/files/download?uri=gs://superai-file-upload-prod-eu/flows/255a17d0-5c21-47d9-8e0b-a08b48436f0a/documents/f8230da2-4136-4ffb-acfe-db9318970ea2" \
  -o downloaded_file.pdf

Authentication

Both file endpoints require authentication. You can use either method:

Method Header Example
API Key (recommended) X-API-Key X-API-Key: saf_abc123...
JWT Token Authorization Authorization: Bearer eyJhbGci...

About API keys:

About JWT tokens:

Obtained by authenticating with your email and password. See the API Quickstart. Tokens expire after 1 hour and must be refreshed.

Two ways to download

Option 1: Direct download (GET)

Use GET /api/files/download for the simplest approach. This endpoint redirects you to a temporary signed URL.

curl -f -L -H "X-API-Key: $SAF_API_KEY" \
  "https://flows.super.ai/api/files/download?uri=gs://bucket/path/to/file" \
  -o output_file.pdf

If your URI contains special characters, URL-encode it first:

ENCODED_URI=$(printf '%s' "$GS_URL" | jq -sRr @uri)
curl -f -L -H "X-API-Key: $SAF_API_KEY" \
  "https://flows.super.ai/api/files/download?uri=$ENCODED_URI" -o file.pdf
Parameter Required Description
uri Yes The gs:// URL from your task output (URL-encoded)
redirect No Set to false to get JSON instead of a redirect (default: true)

Response: 302 redirect to a pre-signed download URL (valid for 1 hour).

Option 2: Resolve URL first (POST)

Use POST /api/files/resolve when you need the download URL for further processing or want to keep URIs out of server logs.

curl -X POST "https://flows.super.ai/api/files/resolve" \
  -H "X-API-Key: $SAF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"uri": "gs://bucket/path/to/file"}'
{
  "download_url": "https://storage.googleapis.com/bucket/path/to/file?X-Goog-Algorithm=...",
  "expires_at": "2025-01-15T15:00:00+00:00",
  "expires_in_seconds": 3600
}

Then download using the returned URL:

curl -o output_file.pdf "https://storage.googleapis.com/bucket/path/to/file?X-Goog-Algorithm=..."

Complete example: download after flow completion

This script executes a flow, waits for completion, and downloads any output files:

#!/bin/bash
set -e

# Configuration — use environment variables for API key
API_KEY="${SAF_API_KEY:-saf_your_api_key}"
FLOW_ID="your-flow-id"
BASE_URL="https://flows.super.ai"
MAX_ATTEMPTS=60  # 5 minutes timeout (60 * 5 seconds)

# 1. Create flow execution
echo "Starting flow execution..."
EXEC_RESPONSE=$(curl -s -X POST "$BASE_URL/api/flow-executions" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\n    \"flow_id\": \"$FLOW_ID\",\n    \"input\": {\n      \"filename\": \"invoice.pdf\",\n      \"mime_type\": \"application/pdf\",\n      \"document_url\": \"https://cdn.super.ai/invoice-example.pdf\"\n    }\n  }")

EXEC_ID=$(echo "$EXEC_RESPONSE" | jq -r .id)
if [ "$EXEC_ID" = "null" ] || [ -z "$EXEC_ID" ]; then
  echo "Failed to create execution. Response: $EXEC_RESPONSE"
  exit 1
fi
echo "Execution started: $EXEC_ID"

# 2. Wait for completion
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
  STATUS=$(curl -s "$BASE_URL/api/flow-executions/$EXEC_ID" \
    -H "X-API-Key: $API_KEY" | jq -r .status)
  echo "Status: $STATUS (attempt $((ATTEMPT + 1))/$MAX_ATTEMPTS)"

if [ "$STATUS" = "completed" ]; then break
  elif [ "$STATUS" = "failed" ]; then echo "Execution failed!"; exit 1; fi

ATTEMPT=$((ATTEMPT + 1))
  sleep 5
done

# 3. Get task outputs
RESULTS=$(curl -s "$BASE_URL/api/task-executions?flow_execution_id=$EXEC_ID" \
  -H "X-API-Key: $API_KEY")

# 4. Download any gs:// URLs from the output (requires jq)
echo "$RESULTS" | jq -r '.. | select(type == "string" and startswith("gs://"))' 2>/dev/null | while read -r GS_URL; do
  if [ -n "$GS_URL" ]; then
    FILENAME=$(basename "$GS_URL")
    ENCODED_URI=$(printf '%s' "$GS_URL" | jq -sRr @uri)
    if curl -f -L -H "X-API-Key: $API_KEY" \
      "$BASE_URL/api/files/download?uri=$ENCODED_URI" -o "$FILENAME"; then
      echo "Downloaded: $FILENAME"
    else
      echo "Failed to download: $FILENAME"
    fi
  fi
done

echo "Done!"

Error handling

Status Description Common causes
400 Bad Request URI doesn’t start with gs://, malformed URI, path traversal attempt
401 Unauthorized Missing or invalid API key / token
403 Forbidden File belongs to a different organization, invalid bucket
404 Not Found Flow doesn’t exist, you lack access, or the file was deleted from storage
500 Server Error Internal error generating download URL

Example error response:

{
  "error": {
    "message": "Access denied: you do not have access to this file",
    "code": "forbidden"
  },
  "request_id": "01K8KABR6S16YETA2SZPVBS9SP"
}

Include the request_id when contacting support for faster resolution.

Always use -f -L with curl on the GET endpoint: -L follows the redirect to the actual download URL, and -f makes curl return a non-zero exit code on HTTP 4xx/5xx errors instead of silently saving an error response as your output file.

Security

For sensitive files, prefer POST /api/files/resolve to keep URIs out of server access logs.

FAQ

What URI formats are supported?

Currently only gs:// URIs (Google Cloud Storage) are supported.

How long are download URLs valid?

Pre-signed URLs are valid for 1 hour. Request a new URL if your download fails after this time.

Can I download files from any flow?

No. You can only download files from flows that belong to your organization.

Do I need to parse the gs:// URL?

No — pass the full URI exactly as received from the task output.

Which endpoint should I use?

Use GET /api/files/download for simple downloads with curl. Use POST /api/files/resolve when you need the URL for programmatic use or want to keep URIs out of logs.

Need help? Email support@super.ai and include your request_id and flow ID.

API Quickstart