Skip to main content
Artifacts are versioned code packages (zip files) that can be tested and deployed as automations. Uploading is a three-step process.

Step 1: Get upload URL

POST /api/artifacts/upload-url
Returns a presigned PUT URL for uploading a zip file to R2 storage.
curl -s -X POST "https://dashboard.floom.dev/api/artifacts/upload-url" \
  -H "Authorization: Bearer $API_KEY"
Response:
{
  "uploadUrl": "https://r2.example.com/presigned-put-url...",
  "r2Key": "artifacts/org123/uuid.zip"
}

Step 2: Upload the zip

PUT the zip binary to the uploadUrl from Step 1:
curl -s -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/zip" \
  --data-binary @project.zip
The zip should contain your Python files. Exclude __pycache__, .git, and manifest.json.

Step 3: Create artifact

POST /api/artifacts
Validates the uploaded zip, computes file hashes, and creates the artifact record. Body:
{
  "manifest": {
    "name": "My Automation",
    "description": "What it does",
    "inputs": [...],
    "outputs": [...],
    "secrets_needed": [],
    "python_dependencies": []
  },
  "entrypoint": "main.py",
  "r2Key": "artifacts/org123/uuid.zip"
}
FieldRequiredDescription
manifestYesManifest object (see Manifest format)
entrypointYesPath to the file with run() inside the zip (e.g., main.py or src/main.py)
r2KeyYesR2 key from Step 1
Response:
{
  "artifactId": "art_abc123"
}
Errors:
StatusCause
400Missing fields, validation error, no run() in entrypoint
413Zip exceeds 10MB

Download artifact code

GET /api/artifacts/:id/code
Returns a presigned download URL and file list for an existing artifact.
curl -s "https://dashboard.floom.dev/api/artifacts/$ARTIFACT_ID/code" \
  -H "Authorization: Bearer $API_KEY"
Response:
{
  "downloadUrl": "https://r2.example.com/presigned-get-url...",
  "fileList": [
    { "path": "main.py", "size": 1234, "hash": "abc..." },
    { "path": "utils/helpers.py", "size": 567, "hash": "def..." }
  ]
}