Overview
The Ordinal API supports two ways to upload media:- URL upload — submit a publicly accessible URL and Ordinal downloads the file for you.
- Local file upload — request signed credentials, then upload the file directly to the returned
uploadUrl.
ready, then use the returned assetId when creating posts.
Choosing a flow
| Use case | Endpoint |
|---|---|
| The file is already hosted at a public URL | POST /uploads |
| The file lives on your machine, server, or in private storage | POST /uploads/prepare |
Supported file types
| Type | Formats |
|---|---|
| Images | JPEG, PNG, GIF, WebP |
| Videos | MP4, QuickTime (MOV) |
File size limits
| Type | Max size |
|---|---|
| Images | 10 MB |
| GIFs | 15 MB |
| Videos | 350 MB |
Images cannot exceed 36 megapixels total resolution.
Upload statuses
| Status | Description |
|---|---|
awaiting_upload | Credentials issued for a local file. Ordinal is waiting for the file to be POSTed. |
pending | Upload is queued and waiting to be processed |
processing | File is being downloaded and processed |
ready | Upload is complete. Use the assetId to attach to posts |
failed | Upload failed. Check the error field for details |
expired | Upload expired before being used in a post |
URL upload
Use this flow when the file is already hosted somewhere Ordinal can reach over the public internet.Submit the file URL
POST to
/uploads with the publicly accessible URL of the file.Poll for status
Poll
GET /uploads/{id} until the status changes to ready.Create a URL upload
Response
Local file upload
Use this flow when the file is on disk, in private storage, or otherwise not reachable from the public internet. Ordinal returns signed credentials that let your client upload the bytes directly to the returneduploadUrl.
Prepare the upload
POST to
/uploads/prepare with the file’s filename, mimetype, and size in bytes.Upload the file
POST the file to the returned
uploadUrl as multipart/form-data with three form fields: params (the JSON string from the prepare response), signature (the signature from the prepare response), and file (the local file bytes). Copy params and signature verbatim — do not modify them. Ordinal is notified automatically when processing finishes.Poll for status
Poll
GET /uploads/{id} until the status changes to ready.Prepare the upload
Response
params value is a signed JSON string. It includes auth (with key and expires), template_id, and fields (uploadJobId, workspaceId, storagePath). The credentials are short‑lived — upload the file before expiresAt.
Upload the file
POST the file touploadUrl as multipart/form-data with three form fields. Use the params and signature values from the prepare response exactly as returned — do not parse, reformat, or regenerate them.
| Form field | Value |
|---|---|
params | The params string from the prepare response |
signature | The signature string from the prepare response |
file | The local file bytes |
uploadUrl, params, and signature with the values returned by /uploads/prepare.
Here’s the same step in Node.js:
processing and then ready.
Checking upload status
Poll the upload endpoint to check when processing is complete:Ready response
When the upload is ready, the response includes theassetId and file metadata:
Failed response
If the upload fails, the response includes an error message:Using assets in posts
Include theassetId in the assetIds array when creating a post:
Platform attachment limits
| Platform | Max attachments |
|---|---|
| X (Twitter) | 4 |
| 20 |
Important notes
Uploads expire within 24 hours if not used in a post. Once an upload expires, create a new upload job.
For videos, the
duration field in the ready response contains the video length in seconds. For images, this field is null.