File Upload API: Complete Developer Guide (2026)
Every serious application eventually needs to accept files: user avatars, PDF invoices, video assets, CSV imports, document scans, audio recordings. Building that infrastructure from scratch means configuring object storage, wiring a CDN, signing URLs, handling retries, scaling for spikes, and monitoring it all. A file upload API does that work for you. Your app POSTs a file, the API returns a URL, the URL serves the file back to users.
This guide covers what a file upload API actually does, the REST shape of a typical upload request, working code in four languages, the tradeoffs between services, and how to choose the one that fits your stack. If you are evaluating tools, skip to the comparison table and the how-to-choose section.
What Is a File Upload API?
A file upload API is an HTTP endpoint that accepts a file in the request body and returns a URL (or identifier) for the stored file. Under the hood, the service handles:
- Object storage. Files land in a backing store like S3, GCS, or Backblaze B2.
- CDN delivery. Files are served through a geographically distributed CDN so downloads are fast anywhere.
- Metadata. Size, MIME type, original filename, and a stable ID are recorded.
- Access control. Public URLs, signed URLs, or time-limited links depending on the service.
- Retries and resumability. Large files may use chunked or resumable uploads transparently.
From your app's perspective, the entire mechanism collapses into one call: POST a file, get a URL.
How a REST File Upload API Works
The standard shape of an upload request, regardless of service, is a multipart/form-data POST:
POST /v1/upload HTTP/1.1
Host: api.example.com
X-API-Key: your_api_key
Content-Type: multipart/form-data; boundary=----FormBoundary
------FormBoundary
Content-Disposition: form-data; name="file"; filename="document.pdf"
Content-Type: application/pdf
[binary file bytes]
------FormBoundary--
Most HTTP clients construct this for you: you pass a filename and the library does the boundary and encoding work. The response is typically JSON:
{
"url": "https://cdn.example.com/uploads/a1b2c3.pdf",
"file_id": "a1b2c3",
"size": 245810,
"content_type": "application/pdf"
}
The url field is the public (or signed) delivery URL. The file_id is what you store in your database so you can manage the file later.
Authentication
Most file upload APIs use one of three auth models:
- API key in a header (simplest, most common). Example:
X-API-Key: fh_.... Easy to rotate, easy to scope. - Bearer token (OAuth-style). Example:
Authorization: Bearer <token>. Common when uploads are tied to a user identity. - Signed policy (pre-signed URL). The server signs an upload URL, the client uploads directly. Common with S3-style uploads for very large files.
For most product use cases, an API key in a header is the right default.
Code Examples
These examples use a FilePost endpoint for concreteness. Replace the URL and header with your chosen service's endpoint; the shape is the same.
cURL
curl -X POST https://filepost.dev/v1/upload \
-H "X-API-Key: your_api_key" \
-F "file=@document.pdf"
Python (requests)
import requests
with open("document.pdf", "rb") as f:
resp = requests.post(
"https://filepost.dev/v1/upload",
headers={"X-API-Key": "your_api_key"},
files={"file": f},
)
data = resp.json()
print(data["url"])
Node.js (fetch)
import fs from "node:fs";
const form = new FormData();
form.append(
"file",
new Blob([fs.readFileSync("document.pdf")]),
"document.pdf"
);
const res = await fetch("https://filepost.dev/v1/upload", {
method: "POST",
headers: { "X-API-Key": process.env.FILEPOST_KEY },
body: form,
});
const { url } = await res.json();
console.log(url);
Go (net/http)
package main
import (
"bytes"
"io"
"mime/multipart"
"net/http"
"os"
)
func upload(path, apiKey string) (*http.Response, error) {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
f, err := os.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
part, _ := writer.CreateFormFile("file", "document.pdf")
io.Copy(part, f)
writer.Close()
req, _ := http.NewRequest("POST", "https://filepost.dev/v1/upload", body)
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("X-API-Key", apiKey)
return http.DefaultClient.Do(req)
}
Common Features Across File Upload APIs
Features that matter when you are evaluating services:
- Permanent URLs vs ephemeral links. Do returned URLs stay live indefinitely, or do they expire?
- File management. Can you list, inspect, or delete files through the API, or only on upload?
- Max file size. Both the per-request limit and any total-storage limit on your plan.
- Rate limiting. Upload requests per second, per minute, per hour. Important for batch ingest.
- CDN coverage. Where the delivery edge lives and whether it is included in the price.
- Transformations. On-the-fly image resizing, video transcoding, format conversion.
- Access control. Public URLs, signed URLs, or private files requiring auth to read.
- SDKs vs plain REST. Some services require an SDK (ties you to a language or framework); others are pure HTTP.
- Intake / anonymous uploads. Can you generate a shareable URL that third parties can upload to without an API key?
Comparison of Popular File Upload APIs
| Feature | FilePost | Cloudinary | Uploadcare | UploadThing | Filestack | file.io |
|---|---|---|---|---|---|---|
| Plain REST API | Yes | Yes | Yes | No (SDK) | Yes | Yes |
| Works with any language | Yes | Yes | Yes | TS only | Yes | Yes |
| Permanent URLs | Yes | Yes | Yes | Yes | Yes | No (auto-delete) |
| Image transformations | No | Yes | Yes | No | Yes | No |
| Intake links | Yes | No | No | No | No | No |
| Free tier | 300 up/mo | Limited | Limited | Varies | Trial | Yes |
| Starting paid price | 9 USD/mo | 89 USD/mo | 35 USD/mo | 10 USD/mo | 59 USD/mo | Varies |
| Pricing model | Flat | Credits | Credits | Per-GB | Credits | Tiered |
How to Choose a File Upload API
Use this decision tree:
- You just need upload plus CDN URL, at a flat price, in any language: FilePost.
- You need image or video transformations as a core feature: Cloudinary.
- You want a pre-built upload widget for the browser: Uploadcare.
- Your entire stack is Next.js: UploadThing. See the UploadThing alternatives comparison if you have any non-JS backend.
- You have enterprise requirements (virus scanning, content moderation, workflows): Filestack or its alternatives.
- You just need a one-time share link: file.io. See the file.io API guide.
File Upload API Design Considerations
If you are building (rather than buying) a file upload API, a few patterns to copy from the mature ones:
- Return JSON with a stable file_id. The URL can change (CDN migration, domain changes); the ID is your join key.
- Support both multipart and chunked uploads. Multipart is fine up to ~50 MB. Above that, chunked or resumable uploads handle flaky networks.
- Validate content-type server-side. Do not trust the client's declared MIME type.
- Enforce per-plan limits at upload time. Rejecting early is cheaper than accepting then cleaning up.
- Rate-limit by API key and IP. Protect against bot abuse without hurting legitimate per-user bursts.
- Make the delete API idempotent. DELETE /files/{id} should succeed whether the file exists or not.
Common Pitfalls When Building on a File Upload API
- Storing the upload URL in the database instead of the file_id. If the URL format changes, you are stuck migrating.
- Assuming URLs stay live forever. Some services expire links. Always check the service's retention policy before putting URLs in email or permanent records.
- Not handling 413 Payload Too Large. If your users can upload photos, one of them will upload a 45 MP RAW. Validate size client-side where possible and show a friendly error.
- Forgetting the Content-Type on the multipart request. Some HTTP clients do not set it automatically when you construct the body by hand.
- Logging the API key. Scrub API keys from logs and error reports.
- Treating upload latency like a synchronous operation in UX. A 20 MB upload on a flaky 4G connection can take 30 seconds. Always show progress.
Try FilePost as Your File Upload API
If you want the simplest possible REST file upload API with flat pricing, permanent URLs, and no SDK lock-in, FilePost is designed exactly for that use case. The whole API is one endpoint, works with any language that can make an HTTP request, and the free tier is generous enough to ship a real product on.
Try FilePost Free
300 uploads per month, 50MB max file size, full REST API access. No credit card required.
Get Your Free API KeySummary
A file upload API is a thin abstraction over object storage, CDN, and metadata that turns "handle file uploads in my app" into a single HTTP call. The right service depends on whether you need transformations, permanence, a specific framework integration, or a flat price. For most developers shipping a product, the "simple REST, any language, permanent URLs, flat pricing" profile is the right starting point, and that is what FilePost is built for.