GuidesSeedance 2.5 API Tutorial: Generate Your First AI Video in 4 Calls
MakerNice Team · ·
To generate a video with the Seedance 2.5 API on MakerNice, you make four REST calls with one API key: request a quote, create the generation, poll its status, then download the file. This tutorial uses Seedance 2.5, ByteDance's video model, in text-to-video mode, and the same flow works for every video model on the platform. The API is plain REST, not OpenAI-compatible, and there is no official SDK, so every example uses curl.
What do you need before calling the Seedance 2.5 API?
You need a MakerNice account with prepaid balance and an API key. Create the key in the console under Developers, API Keys, and give it a spend limit and an expiry date if it will live in a script. Send the key as a Bearer token on every request; only GET /v1/models and GET /v1/pricing work without one.
Step 1: How do you get a price quote?
Call POST /v1/generations/quote with exactly the input you plan to generate. A quote tells you the cost before anything is held from your wallet. The fields model, mode and prompt are required; duration and resolution are optional and fall back to the model defaults (for Seedance 2.5: 5 seconds and 720p); aspect_ratio is optional too and is simply not sent when you leave it out.
curl https://api.makernice.com/v1/generations/quote \
-H "Authorization: Bearer $MAKERNICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedance-2.5",
"mode": "t2v",
"prompt": "A paper boat drifts down a rain-soaked street at dusk, slow dolly-in, warm shop lights reflecting on the water",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9"
}'The response contains an id starting with qt_, the amount as a string of micro-USD (1,000,000 micro-USD equal 1 US dollar), the price_version, an expires_at timestamp and a facts object that echoes what was priced. The price stays locked for 12 minutes.
Step 2: How do you create the generation without being charged twice?
Post the quote id together with the same input to POST /v1/generations, and add an Idempotency-Key header of 1 to 200 printable ASCII characters without spaces, such as a UUID or your own order id. The API answers 202 with an id starting with gen_, status queued and billing held. If the network drops and you retry with the same key, you get the original generation back with 200 instead of a second charge.
curl https://api.makernice.com/v1/generations \
-H "Authorization: Bearer $MAKERNICE_API_KEY" \
-H "Idempotency-Key: demo-order-1842-attempt-1" \
-H "Content-Type: application/json" \
-d '{
"quote_id": "qt_...",
"input": {
"model": "seedance-2.5",
"mode": "t2v",
"prompt": "A paper boat drifts down a rain-soaked street at dusk, slow dolly-in, warm shop lights reflecting on the water",
"duration": 5,
"resolution": "720p",
"aspect_ratio": "16:9"
}
}'
Step 3: How do you check the status and download the video?
Poll GET /v1/generations/{id} every few seconds. The status moves from queued to generating and ends as succeeded, failed or canceled; while we confirm a result you may briefly see checking. When it succeeds, outputs[0].url points at the file. Request it with your key and you receive a 302 redirect, so let curl follow it with -L.
# Check the status until it is succeeded, failed or canceled
curl https://api.makernice.com/v1/generations/gen_... \
-H "Authorization: Bearer $MAKERNICE_API_KEY"
# Download the file once succeeded
curl -L -o video.mp4 https://api.makernice.com/v1/generations/gen_.../outputs/0 \
-H "Authorization: Bearer $MAKERNICE_API_KEY"Which errors will you see on your first calls?
| Status | Error code | What it means | What to do |
|---|---|---|---|
| 400 | invalid_request | A field the mode does not use, or an unknown field, was sent | Remove the field; check GET /v1/models for the mode |
| 422 | price_unavailable | This model, mode and resolution has no price | Pick a listed resolution |
| 422 | quote_mismatch | Model, mode, resolution or duration changed after quoting | Quote again with the final input |
| 410 | quote_expired | The 12 minute quote window passed | Request a fresh quote |
| 409 | quote_already_used | The quote was already used for a generation | Request a fresh quote |
| 402 | insufficient_balance | The wallet cannot cover the hold | Top up in the console |
Once this flow works, read the API integration best practices post for the idempotency, polling and rate-limit habits worth building in from day one.
