Make one real URL before you keep reading

Upload a file up to 10 MB. The public URL works immediately, with no password or credit card. Executable files require email verification.

Turn a Webhook Attachment into a Public CDN URL

· 6 min read

A webhook often contains a file URL, but that URL may be private, short-lived, or accessible only to the sender's account. If another service needs a public link, validate the incoming request and copy the bytes to a host that is meant to serve them.

FilePost reduces that storage step to one authenticated request. The response includes a public url, a stable file_id, and the file metadata you need for a database row, CRM field, Slack message, or follow-up webhook.

Choose the recipe that matches the webhook payload

Incoming valueWhat your handler doesFilePost endpoint
Multipart attachmentForward the file streamPOST /v1/upload
Temporary file URLDownload, validate, then forward the bytesPOST /v1/upload
Base64 stringForward filename, content type, and base64 data as JSONPOST /v1/upload/base64

Multipart attachment example

This FastAPI handler receives a file and immediately turns it into a FilePost URL:

import os
import httpx
from fastapi import FastAPI, UploadFile

app = FastAPI()

@app.post("/webhooks/file")
async def receive_file(file: UploadFile):
    contents = await file.read()
    async with httpx.AsyncClient(timeout=30) as client:
        response = await client.post(
            "https://upload.filepost.dev/v1/upload",
            headers={"X-API-Key": os.environ["FILEPOST_API_KEY"]},
            files={"file": (file.filename, contents, file.content_type)},
        )
    response.raise_for_status()
    uploaded = response.json()
    return {"public_url": uploaded["url"], "file_id": uploaded["file_id"]}

Temporary source URL example

Do not copy an untrusted URL directly into a server-side request without controls. Allow only expected hosts, reject private and loopback addresses, cap redirects and response size, and validate the content type before forwarding the bytes.

source = await client.get(approved_url, follow_redirects=False)
source.raise_for_status()

uploaded = await client.post(
    "https://upload.filepost.dev/v1/upload",
    headers={"X-API-Key": os.environ["FILEPOST_API_KEY"]},
    files={"file": ("attachment.pdf", source.content, "application/pdf")},
)
uploaded.raise_for_status()
public_url = uploaded.json()["url"]

Base64 JSON example

If the webhook already carries base64 data, keep the handoff as JSON:

curl -X POST https://upload.filepost.dev/v1/upload/base64 \
  -H "X-API-Key: $FILEPOST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "report.csv",
    "content_type": "text/csv",
    "data_base64": "bmFtZSx0b3RhbApGaWxlUG9zdCw0Mg=="
  }'

Production checks

Build the storage step once

Start with the live upload above, then copy the matching recipe into your webhook handler.

Get Your Free API Key

Related workflow guides