When you compose a video edit, you normally provide URLs to your source footage and Shotstack downloads them as part of rendering. That works well, but pulling files from arbitrary URLs every time comes with some downsides — latency, bandwidth costs, and no easy way to standardize footage coming from different devices or sources.
The Ingest API solves this by letting you upload or fetch source files (video, image, audio and fonts) once, store them with Shotstack, and reuse them across edits — with optional transformations along the way.
Fetch a file from a URL
If your footage is already hosted somewhere, send Shotstack the URL and it will fetch it asynchronously:
curl -X POST https://api.shotstack.io/ingest/stage/sources \
-H 'Content-Type: application/json' \
-H 'x-api-key: YOUR_API_KEY' \
-d '{ "url": "https://example.com/video.mp4" }'
You'll get back a source id in the response:
{
"data": {
"type": "source",
"id": "zzytey4v-32km-kq1z-aftr-3kcuqi0brad2"
}
}
Use that id to check the file's status or reference it later.
Upload a file directly
If the file isn't hosted anywhere yet, you can upload it straight from your application in two steps: request a signed upload URL, then PUT your file to it. No storage or hosting setup required on your end.
Step 1 — Request a signed URL
curl -X POST https://api.shotstack.io/ingest/stage/upload \
-H 'Accept: application/json' \
-H 'x-api-key: YOUR_API_KEY'
The response includes a signed URL at data.attributes.url, valid for a limited time:
{
"data": {
"type": "upload",
"id": "zzyafe82-4tvb-ku1r-87ty-0io5sv0mtrdl",
"attributes": {
"id": "zzyafe82-4tvb-ku1r-87ty-0io5sv0mtrdl",
"url": "https://shotstack-ingest-api-v1-sources.s3.ap-southeast-2.amazonaws.com/.../source?AWSAccessKeyId=...&Expires=...&Signature=...",
"expires": "2023-01-02T02:47:37.260Z"
}
}
}
Step 2 — PUT your file to the signed URL
Upload the file directly to the signed URL using an HTTP PUT request:
curl -X PUT -T video.mp4 "SIGNED_URL"
Note: The upload runs in the foreground and shouldn't be interrupted until it completes. If it's interrupted, just re-run the command — the signed URL stays valid until it expires.
Once uploaded, poll the source's status (below) to confirm it's ready to use.
Setting the Content-Type header
For common media files (video, image, audio) the type is auto-detected, so a Content-Type header is optional. For text-based files like .srt, .vtt, .csv or .txt, auto-detection doesn't work — set the type explicitly one of two ways:
curl -X PUT -H 'Content-Type: application/x-subrip' -T subtitles.srt "SIGNED_URL"
…or provide a filename with the correct extension when requesting the signed URL instead:
curl -X POST https://api.shotstack.io/ingest/stage/upload \
-H 'Content-Type: application/json' \
-H 'x-api-key: YOUR_API_KEY' \
-d '{ "filename": "subtitles.srt" }'
Checking when a file is ready
Ingesting and processing can take a few seconds to a few minutes. You have two options:
Poll the source's status by
iduntil it showsready(alsoqueued,importing, orfailedif something goes wrong).Add a
callbackURL to your ingest request and receive a webhook to your own server when it's done — no polling needed.
"callback": "https://my-server.com/webhook.php"
Webhooks are more efficient than polling if you're ingesting at any real volume. See the Understanding Webhooks article for how the payload is structured.
Creating renditions
You can also ask Shotstack to transform a source file as part of ingestion — resizing, changing aspect ratio, cropping, or adjusting framerate and quality. This is useful for standardizing footage from different devices or matching your edit's output resolution. Add an outputs.renditions array to your ingest request:
curl -X POST https://api.shotstack.io/ingest/stage/sources \
-H 'Content-Type: application/json' \
-H 'x-api-key: YOUR_API_KEY' \
-d '{
"url": "https://example.com/video.mp4",
"outputs": {
"renditions": [ { "resolution": "hd" } ]
}
}'
Renditions also work with direct uploads — just include the same outputs.renditions array in your signed URL request instead. Check rendition status the same way as source files, under data.attributes.outputs.renditions in the response.
Note: Files ingested via the Ingest API are stored in S3 in the AWS Sydney region, primarily for use in your edits. We don't recommend serving these files directly to your end users — use a CDN or your own storage/hosting for that.
