For Airtable users

Your Airtable attachment URLs break every 2 hours. Fix them once.

Airtable signed URLs expire. FilePost gives you a permanent public CDN URL for every attachment, so your dashboards, emails, and client portals stop breaking. One API call. Works with Make, Zapier, n8n, or 10 lines of Python.

Free plan: 300 uploads/mo · 50MB files · No credit card · Ship in under 5 minutes
Works with your stack

The problem you keep running into

You store an Airtable attachment URL in your app. A dashboard image. A PDF link in an email. A file reference in a webhook payload. Everything works, until a few hours later, when every URL starts returning 403 Forbidden.

Airtable attachment URLs look like this:

https://v5.airtableusercontent.com/v3/u/33/33/1706234567/tokenABC/photo.jpg

That token expires in ~2 hours. Airtable's official guidance is to fetch a fresh URL from the API every time you need a file, which is impossible if you've already sent the URL in an email, rendered it on a static site, or passed it to a third-party service.

FilePost solves this at the source: you download the attachment once, upload it to FilePost, and use the permanent CDN URL everywhere. Your dashboards, emails, PDFs, client portals, and public pages stay working.

Fix it in 3 steps

No S3 bucket, no IAM, no CDN config. Just a POST request.

Step 1

Grab your API key

Sign up with email or Google. You get a working key instantly. Free plan covers 300 uploads per month.

Step 2

Pipe the Airtable URL to FilePost

Download the signed Airtable URL, POST the file to filepost.dev/v1/upload. Takes <1 second per file.

Step 3

Store the permanent URL

Write the FilePost CDN URL back to a text field on the Airtable record. Use that URL everywhere instead.

Copy-paste examples

Pick your stack. Every snippet is complete and runs as-is once you fill in your keys.

# pip install pyairtable requests import requests from pyairtable import Api AIRTABLE_TOKEN = "pat_..." BASE_ID = "appXXXXXXXXXXXXXX" TABLE = "Photos" ATTACH_FIELD = "Image" PERMANENT_FIELD = "Permanent URL" FILEPOST_KEY = "your_filepost_api_key" table = Api(AIRTABLE_TOKEN).table(BASE_ID, TABLE) for rec in table.all(): atts = rec["fields"].get(ATTACH_FIELD, []) if not atts or rec["fields"].get(PERMANENT_FIELD): continue a = atts[0] file_bytes = requests.get(a["url"]).content r = requests.post( "https://filepost.dev/v1/upload", headers={"X-API-Key": FILEPOST_KEY}, files={"file": (a["filename"], file_bytes)}, ) permanent = r.json()["url"] table.update(rec["id"], {PERMANENT_FIELD: permanent}) print(f"{a['filename']} -> {permanent}")
# Make scenario (3 modules): # 1) Airtable "Watch Records" -> new record in your table # 2) HTTP "Get a file" -> URL: {{1.Attachment[].url}} # 3) HTTP "Make a request" # URL: https://filepost.dev/v1/upload # Method: POST # Headers: # X-API-Key: your_filepost_api_key # Body type: multipart/form-data # Fields: # file = {{2.Data}} (File) # # 4) Airtable "Update a Record" # Permanent URL = {{3.data.url}}
# n8n workflow (4 nodes): # 1) Airtable Trigger (new record) # 2) HTTP Request, GET the Airtable signed URL # Response format: File # 3) FilePost node (community) OR HTTP Request: # URL: https://filepost.dev/v1/upload # Auth: header "X-API-Key" = your key # Body: multipart, "file" = data binary # 4) Airtable, Update, "Permanent URL" = {{$json.url}}
# Zapier Zap (3 steps): # 1) Airtable "New Record" trigger # 2) Zapier "Webhooks by Zapier" (POST) # URL: https://filepost.dev/v1/upload # Payload type: form # Header: X-API-Key = your key # File field: point to the Airtable attachment URL # 3) Airtable "Update Record" # Permanent URL = {{2.url}}
# 1. Download the Airtable attachment while its signed URL is valid curl -o photo.jpg "https://v5.airtableusercontent.com/v3/u/33/33/.../photo.jpg" # 2. Upload to FilePost -> permanent CDN URL curl -X POST https://filepost.dev/v1/upload \ -H "X-API-Key: your_filepost_api_key" \ -F "file=@photo.jpg" # Response: # {"url": "https://cdn.filepost.dev/abc123/photo.jpg", "file_id": "abc123", ...}

Want the full batch script for existing records? See the walkthrough in Fix Airtable Expiring Attachment URLs.

Why not just refetch from Airtable every time?

You can, but it creates real problems for anything that isn't a live API call.

Scenario Refetch every time Permanent FilePost URL
Image on a public marketing page Breaks between renders Always works
Attachment in an email Dead before recipient opens it Always works
File in a PDF export Broken once PDF is generated Always works
Image cached by browsers / CDNs Cache populated with dead link Safely cacheable forever
Webhook payload processed async URL expires before your worker runs Always works
Shared with external partner / client Requires API access or proxy Just send the link

Frequently asked questions

Why do Airtable attachment URLs expire?

Airtable switched to signed URLs with a temporary authentication token in early 2024. The token is valid for about two hours, after which the URL returns an authorization error. It is a security measure, but it breaks any workflow that treats Airtable attachment URLs as permanent links. Think cached URLs, embedded images, shared files, asynchronous webhook payloads.

How do I get a permanent URL for an Airtable attachment?

Download the Airtable attachment while its signed URL is still valid, re-upload it to FilePost, and store the FilePost CDN URL in a separate field on your Airtable record. The FilePost URL never expires. You can do this once for existing records using a Python script, or automate it with Make, Zapier, or n8n so every new attachment is processed automatically.

Does this also work for Monday, ClickUp, and Notion?

Yes. The same pattern works for any tool whose file URLs expire or require auth tokens. Monday.com, ClickUp, and Notion attachments are all accessible via their APIs and can be re-uploaded to FilePost to get permanent public CDN URLs.

How long are FilePost URLs valid?

Forever. There is no expiration. Files are stored on Backblaze B2 and delivered via Cloudflare's CDN. URLs keep working until you explicitly delete the file via the API or dashboard.

What does it cost?

The free plan includes 300 uploads per month, 50 MB max file size, and 2 GB of storage, enough to cover most small Airtable bases. Starter is $9/month for 5,000 uploads and 200 MB files. Pro is $29/month for 25,000 uploads and 500 MB files. No credit card required to start.

Can I automate this so every new Airtable record gets a permanent URL?

Yes. In Make, Zapier, or n8n, trigger on new Airtable records, add an HTTP step that downloads the attachment, then a FilePost upload step that returns the permanent URL, and finally an Airtable update step that writes the FilePost URL to a separate text field. Full flow runs in under ten seconds per attachment.

Is my data secure?

Uploads use HTTPS end-to-end. Files are stored on Backblaze B2 (SOC 2 Type II) and delivered via Cloudflare's CDN with DDoS protection. Files are public-by-URL (like unguessable CDN links), which matches how Airtable attachment URLs work. If you need private/signed URLs, that's on the roadmap. email us.

Stop losing Airtable files

Free plan gives you 300 uploads/month. No credit card. API key in 5 seconds.

Get free API key →