Skip to content
On this page

Quickstart

Upload an image, create a video generation, and retrieve the result.

Generate videos and manage image, video, and audio assets.

SettingValue
Base URLhttps://api.sand.ai
AuthenticationBearer API key

Authentication

Create a key on the API Keys page and include it in the request header:

http
Authorization: Bearer YOUR_API_KEY

Each API key belongs to an organization. Generations, assets, and usage are managed at the organization level. Keep keys on your server; do not expose them in browsers or mobile apps.

Before running the examples, set your API key:

bash
export SAND_API_KEY='YOUR_API_KEY'

Quickstart

This example uses magi-2-preview-latest. Upload a starting image, create a generation, and retrieve the result.

1. Upload an image

Replace ./start-frame.png with a local image path.

bash
curl https://api.sand.ai/v1/assets \
  -H "Authorization: Bearer $SAND_API_KEY" \
  -F "file=@./start-frame.png"

The response contains an asset ID:

json
{ "id": 123456789 }

2. Create a generation

Set image.assetId to the returned asset ID, as a string.

bash
curl https://api.sand.ai/v2/generations \
  -H "Authorization: Bearer $SAND_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "model": "magi-2-preview-latest",
    "parts": [
      {"type": "prompt", "text": "A person turns and smiles as the camera slowly pulls back."},
      {"type": "start_frame", "image": {"assetId": "123456789"}}
    ],
    "duration": 10,
    "aspectRatio": "16:9",
    "resolution": "1080p"
  }'

A successful request returns HTTP 202 Accepted and a generation ID:

json
{ "id": "987654321" }

Save the generation ID. The request has been accepted, and the video will be generated asynchronously. See Create a Generation for the full request format.

3. Retrieve the result

Set the generation ID and check its status:

bash
export SAND_GENERATION_ID='987654321'
curl "https://api.sand.ai/v2/generations/$SAND_GENERATION_ID" \
  -H "Authorization: Bearer $SAND_API_KEY"
  • queued or processing: continue polling, typically every 5 seconds. Keep the total polling rate across all generations within your organization's limit.
  • succeeded: check that output.videoUrl is not null, then download the video.
  • failed: stop polling and read error.
  • canceled: stop polling.

See Retrieve a Generation for the response fields and download URL expiration.

Resume polling

If the connection drops or polling stops, repeat step 3 with the saved generation ID. You can also use details.generation_id when it is included in a failed creation response.

Do not create another generation to resume polling: doing so may incur duplicate charges. See Retries.