doubao-seedance-2-5-260628

最后更新:2026-11-14

POSThttps://www.sagelib.com/videos

doubao-seedance-2-5-260628 模型的视频生成接口,OpenAI兼容,支持文生视频、图生视频等。

接口鉴权方式请参考:API接入与鉴权

请求参数

请求头

参数名称 描述
*Authorization string 鉴权令牌,格式为 Bearer ${AIGATEWAY_TOKEN}
*Content-Type string 可选值:multipart/form-data、application/json
multipart/form-data 或 application/json

Body 参数

参数名称 描述
*model string 可选值:doubao-seedance-2-5-260628
模型 ID,固定值
*prompt string 可选值:Up to 500 Chinese characters / 1000 English words
文本提示词,决定视频内容与风格
size string 默认值:720p
可选值:480p、720p、1080p
输出分辨率
eca_aspect_ratio string 默认值:adaptive
可选值:16:9、4:3、1:1、3:4、9:16、21:9、adaptive
输出宽高比
seconds integer 默认值:5
可选值:4-30, -1 means automatic
生成视频时长(秒)
eca_audio boolean 默认值:true
可选值:true、false
是否生成与视频同步的音频
eca_first_frame string 可选值:Image URL or Base64 (.jpg/.jpeg/.png, up to 10MB)
首帧图片,用于图生视频
eca_last_frame string 可选值:Image URL or Base64 (.jpg/.jpeg/.png, up to 10MB)
尾帧图片,用于视频续接
eca_video_reference array 可选值:Object array; elements contain video / audio fields
参考视频数组,用于视频生视频或视频编辑
eca_video_reference[].video string 可选值:Video URL
参考视频 URL
eca_video_reference[].audio string 可选值:Audio URL
参考视频内音频 URL
eca_audio_reference array 可选值:Object array; elements contain an audio field
独立参考音频数组
*eca_audio_reference[].audio string 可选值:Audio URL or Base64
参考音频内容
eca_tools array 可选值:Object array; elements contain a type field
内容生成工具
eca_tools[].type string 可选值:Tool type
工具类型
input_reference array 可选值:Object array; elements contain an image field
参考图片数组,用于全模态参考生成
*input_reference[].image string 可选值:Image URL or Base64
参考图片内容
frames integer 可选值:Total frames (derived from duration and frame rate)
按总帧数指定视频时长,与 seconds 互斥
output_format string 可选值:mp4
输出格式
omni_reference_task_type string 可选值:reference
全模态参考任务类型
seed integer 默认值:-1
可选值:Integer
随机种子,用于结果复现
watermark boolean 默认值:false
可选值:true、false
是否在视频右下角嵌入 AI 生成水印
return_last_frame boolean 默认值:false
可选值:true、false
是否返回无水印的最后一帧 PNG 图像
execution_expires_after integer 默认值:172800
可选值:3600~259200
任务过期阈值(秒)
callback_url string 可选值:HTTP
任务状态变更通知的 Webhook URL
service_tier string 默认值:default
可选值:default
服务层级

请求示例

curl -v 'https://www.sagelib.com/videos' \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2-5-260628",
    "prompt": "At dusk, an orange tabby slowly rises on a windowsill, gazing at the sunset city skyline; watercolor style, warm tones, the camera slowly zooms in; delicate, soft, atmospheric."
  }'
import json
import requests

# Configure base variables
base_url = "https://www.sagelib.com"  # 把 base_url 换成你的网关地址 https://www.sagelib.com
api_key = "***"  # Replace with your Bearer token

url = f"https://www.sagelib.com/videos"

headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
}

data = {
    "model": "doubao-seedance-2-5-260628",
    "prompt": "At dusk, an orange tabby slowly rises on a windowsill, gazing at the sunset city skyline; watercolor style, warm tones, the camera slowly zooms in; delicate, soft, atmospheric."
}

# Send the POST request
response = requests.post(url, headers=headers, json=data)

# Print the status code and the returned JSON data
print(f"Status Code: {response.status_code}")
try:
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except Exception:
    print(response.text)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class LlmStreamClient {
    public static void main(String[] args) {
        String baseUrl = "https://www.sagelib.com";
        String apiKey = "***";
        String url = "https://www.sagelib.com/videos";

        String jsonRequestBody = """
            {
                "model": "doubao-seedance-2-5-260628",
                "prompt": "At dusk, an orange tabby slowly rises on a windowsill, gazing at the sunset city skyline; watercolor style, warm tones, the camera slowly zooms in; delicate, soft, atmospheric."
            }
            """;

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + apiKey)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(jsonRequestBody))
                .build();

        try {
            // Use ofInputStream to handle the streaming response
            HttpResponse<java.io.InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    if (line.startsWith("data:")) {
                        String data = line.substring(5).trim();
                        if ("[DONE]".equals(data)) {
                            break;
                        }
                        // Tip: you can bring in Gson or Jackson here to parse the JSON in data and extract delta.content
                        System.out.println("Received stream chunk: " + data);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    baseUrl := "https://www.sagelib.com"
    apiKey := "***"
    url := "https://www.sagelib.com/videos"

    jsonRequestBody := `
            {
                "model": "doubao-seedance-2-5-260628",
                "prompt": "At dusk, an orange tabby slowly rises on a windowsill, gazing at the sunset city skyline; watercolor style, warm tones, the camera slowly zooms in; delicate, soft, atmospheric."
            }
`

    req, err := http.NewRequest("POST", url, bytes.NewBufferString(jsonRequestBody))
    if err != nil {
        fmt.Println("Failed to create request:", err)
        return
    }
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    // Pretty-print the returned JSON data
    var prettyBody map[string]interface{}
    if err := json.Unmarshal(body, &prettyBody); err == nil {
        pretty, _ := json.MarshalIndent(prettyBody, "", "  ")
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(pretty))
    } else {
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(body))
    }
}
curl -v 'https://www.sagelib.com/videos' \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2-5-260628",
    "prompt": "Fruit biscuit ad: four flavors — strawberry, apple, grape, orange — with their fruits arranged in a strong-order geometric array; a biscuit snaps, the filling bursts, crumbs fly, highlighting product variety and deliciousness; bright and premium.",
    "input_reference": [
      {
        "image": "${image_url}"
      },
      {
        "image": "${image_url}"
      }
    ],
    "eca_audio_reference": [
      {
        "audio": "${audio_url}"
      }
    ]
  }'
import json
import requests

# Configure base variables
base_url = "https://www.sagelib.com"  # 把 base_url 换成你的网关地址 https://www.sagelib.com
api_key = "***"  # Replace with your Bearer token

url = f"https://www.sagelib.com/videos"

headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
}

data = {
    "model": "doubao-seedance-2-5-260628",
    "prompt": "Fruit biscuit ad: four flavors — strawberry, apple, grape, orange — with their fruits arranged in a strong-order geometric array; a biscuit snaps, the filling bursts, crumbs fly, highlighting product variety and deliciousness; bright and premium.",
    "input_reference": [
        {
            "image": "${image_url}"
        },
        {
            "image": "${image_url}"
        }
    ],
    "eca_audio_reference": [
        {
            "audio": "${audio_url}"
        }
    ]
}

# Send the POST request
response = requests.post(url, headers=headers, json=data)

# Print the status code and the returned JSON data
print(f"Status Code: {response.status_code}")
try:
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except Exception:
    print(response.text)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class LlmStreamClient {
    public static void main(String[] args) {
        String baseUrl = "https://www.sagelib.com";
        String apiKey = "***";
        String url = "https://www.sagelib.com/videos";

        String jsonRequestBody = """
            {
                "model": "doubao-seedance-2-5-260628",
                "prompt": "Fruit biscuit ad: four flavors — strawberry, apple, grape, orange — with their fruits arranged in a strong-order geometric array; a biscuit snaps, the filling bursts, crumbs fly, highlighting product variety and deliciousness; bright and premium.",
                "input_reference": [
                    {
                        "image": "${image_url}"
                    },
                    {
                        "image": "${image_url}"
                    }
                ],
                "eca_audio_reference": [
                    {
                        "audio": "${audio_url}"
                    }
                ]
            }
            """;

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + apiKey)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(jsonRequestBody))
                .build();

        try {
            // Use ofInputStream to handle the streaming response
            HttpResponse<java.io.InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    if (line.startsWith("data:")) {
                        String data = line.substring(5).trim();
                        if ("[DONE]".equals(data)) {
                            break;
                        }
                        // Tip: you can bring in Gson or Jackson here to parse the JSON in data and extract delta.content
                        System.out.println("Received stream chunk: " + data);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    baseUrl := "https://www.sagelib.com"
    apiKey := "***"
    url := "https://www.sagelib.com/videos"

    jsonRequestBody := `
            {
                "model": "doubao-seedance-2-5-260628",
                "prompt": "Fruit biscuit ad: four flavors — strawberry, apple, grape, orange — with their fruits arranged in a strong-order geometric array; a biscuit snaps, the filling bursts, crumbs fly, highlighting product variety and deliciousness; bright and premium.",
                "input_reference": [
                    {
                        "image": "${image_url}"
                    },
                    {
                        "image": "${image_url}"
                    }
                ],
                "eca_audio_reference": [
                    {
                        "audio": "${audio_url}"
                    }
                ]
            }
`

    req, err := http.NewRequest("POST", url, bytes.NewBufferString(jsonRequestBody))
    if err != nil {
        fmt.Println("Failed to create request:", err)
        return
    }
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    // Pretty-print the returned JSON data
    var prettyBody map[string]interface{}
    if err := json.Unmarshal(body, &prettyBody); err == nil {
        pretty, _ := json.MarshalIndent(prettyBody, "", "  ")
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(pretty))
    } else {
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(body))
    }
}
curl -v 'https://www.sagelib.com/videos' \
  -H "Authorization: Bearer ***" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2-5-260628",
    "prompt": "Fruit biscuit ad: biscuits in four flavors with their fruits neatly arranged; the camera slowly pushes in to a close-up; a biscuit snaps, the fruity filling bursts, crumbs fly; bright, clean, premium, rhythmic.",
    "eca_video_reference": [
      {
        "video": "${video_url}"
      }
    ],
    "eca_audio_reference": [
      {
        "audio": "${audio_url}"
      }
    ]
  }'
import json
import requests

# Configure base variables
base_url = "https://www.sagelib.com"  # 把 base_url 换成你的网关地址 https://www.sagelib.com
api_key = "***"  # Replace with your Bearer token

url = f"https://www.sagelib.com/videos"

headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json",
}

data = {
    "model": "doubao-seedance-2-5-260628",
    "prompt": "Fruit biscuit ad: biscuits in four flavors with their fruits neatly arranged; the camera slowly pushes in to a close-up; a biscuit snaps, the fruity filling bursts, crumbs fly; bright, clean, premium, rhythmic.",
    "eca_video_reference": [
        {
            "video": "${video_url}"
        }
    ],
    "eca_audio_reference": [
        {
            "audio": "${audio_url}"
        }
    ]
}

# Send the POST request
response = requests.post(url, headers=headers, json=data)

# Print the status code and the returned JSON data
print(f"Status Code: {response.status_code}")
try:
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except Exception:
    print(response.text)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class LlmStreamClient {
    public static void main(String[] args) {
        String baseUrl = "https://www.sagelib.com";
        String apiKey = "***";
        String url = "https://www.sagelib.com/videos";

        String jsonRequestBody = """
            {
                "model": "doubao-seedance-2-5-260628",
                "prompt": "Fruit biscuit ad: biscuits in four flavors with their fruits neatly arranged; the camera slowly pushes in to a close-up; a biscuit snaps, the fruity filling bursts, crumbs fly; bright, clean, premium, rhythmic.",
                "eca_video_reference": [
                    {
                        "video": "${video_url}"
                    }
                ],
                "eca_audio_reference": [
                    {
                        "audio": "${audio_url}"
                    }
                ]
            }
            """;

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + apiKey)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(jsonRequestBody))
                .build();

        try {
            // Use ofInputStream to handle the streaming response
            HttpResponse<java.io.InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());

            try (BufferedReader reader = new BufferedReader(new InputStreamReader(response.body()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    line = line.trim();
                    if (line.startsWith("data:")) {
                        String data = line.substring(5).trim();
                        if ("[DONE]".equals(data)) {
                            break;
                        }
                        // Tip: you can bring in Gson or Jackson here to parse the JSON in data and extract delta.content
                        System.out.println("Received stream chunk: " + data);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    baseUrl := "https://www.sagelib.com"
    apiKey := "***"
    url := "https://www.sagelib.com/videos"

    jsonRequestBody := `
            {
                "model": "doubao-seedance-2-5-260628",
                "prompt": "Fruit biscuit ad: biscuits in four flavors with their fruits neatly arranged; the camera slowly pushes in to a close-up; a biscuit snaps, the fruity filling bursts, crumbs fly; bright, clean, premium, rhythmic.",
                "eca_video_reference": [
                    {
                        "video": "${video_url}"
                    }
                ],
                "eca_audio_reference": [
                    {
                        "audio": "${audio_url}"
                    }
                ]
            }
`

    req, err := http.NewRequest("POST", url, bytes.NewBufferString(jsonRequestBody))
    if err != nil {
        fmt.Println("Failed to create request:", err)
        return
    }
    req.Header.Set("Authorization", "Bearer "+apiKey)
    req.Header.Set("Content-Type", "application/json")

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    // Pretty-print the returned JSON data
    var prettyBody map[string]interface{}
    if err := json.Unmarshal(body, &prettyBody); err == nil {
        pretty, _ := json.MarshalIndent(prettyBody, "", "  ")
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(pretty))
    } else {
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(body))
    }
}
curl -v 'https://www.sagelib.com/videos/${video_id}' \
  -H "Authorization: Bearer ***"
import json
import requests

# Configure base variables
base_url = "https://www.sagelib.com"  # 把 base_url 换成你的网关地址 https://www.sagelib.com
api_key = "***"  # Replace with your Bearer token
video_id = "${video_id}"  # The video task ID returned when creating the task

url = f"https://www.sagelib.com/videos/{video_id}"

headers = {
    "Authorization": f"Bearer {api_key}",
}

# Send the GET request to query the task status
response = requests.get(url, headers=headers)

# Print the status code and the returned JSON data
print(f"Status Code: {response.status_code}")
try:
    print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except Exception:
    print(response.text)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class LlmVideoQuery {
    public static void main(String[] args) {
        String baseUrl = "https://www.sagelib.com";
        String apiKey = "***";
        String videoId = "${video_id}";  // The video task ID returned when creating the task
        String url = "https://www.sagelib.com/videos/" + videoId;

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + apiKey)
                .GET()
                .build();

        try {
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            System.out.println("Status Code: " + response.statusCode());
            System.out.println(response.body());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    baseUrl := "https://www.sagelib.com"
    apiKey := "***"
    videoId := "${video_id}" // The video task ID returned when creating the task
    url := "https://www.sagelib.com/videos/" + videoId

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Println("Failed to create request:", err)
        return
    }
    req.Header.Set("Authorization", "Bearer "+apiKey)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    // Pretty-print the returned JSON data
    var prettyBody map[string]interface{}
    if err := json.Unmarshal(body, &prettyBody); err == nil {
        pretty, _ := json.MarshalIndent(prettyBody, "", "  ")
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(pretty))
    } else {
        fmt.Println("Status Code:", resp.StatusCode)
        fmt.Println(string(body))
    }
}
curl -v 'https://www.sagelib.com/videos/${video_id}/content' \
  -H "Authorization: Bearer ***" \
  -o output.mp4
import requests

# Configure base variables
base_url = "https://www.sagelib.com"  # 把 base_url 换成你的网关地址 https://www.sagelib.com
api_key = "***"  # Replace with your Bearer token
video_id = "${video_id}"  # The video task ID returned when creating the task

url = f"https://www.sagelib.com/videos/{video_id}/content"

headers = {
    "Authorization": f"Bearer {api_key}",
}

# Send the GET request and stream the video content to a local file
response = requests.get(url, headers=headers, stream=True)
response.raise_for_status()

with open("output.mp4", "wb") as f:
    for chunk in response.iter_content(chunk_size=8192):
        f.write(chunk)

print(f"Status Code: {response.status_code}")
print("Video saved to output.mp4")
import java.io.InputStream;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class LlmVideoDownload {
    public static void main(String[] args) {
        String baseUrl = "https://www.sagelib.com";
        String apiKey = "***";
        String videoId = "${video_id}";  // The video task ID returned when creating the task
        String url = "https://www.sagelib.com/videos/" + videoId + "/content";

        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + apiKey)
                .GET()
                .build();

        try {
            HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
            System.out.println("Status Code: " + response.statusCode());
            try (InputStream in = response.body()) {
                Files.copy(in, Path.of("output.mp4"), StandardCopyOption.REPLACE_EXISTING);
                System.out.println("Video saved to output.mp4");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    baseUrl := "https://www.sagelib.com"
    apiKey := "***"
    videoId := "${video_id}" // The video task ID returned when creating the task
    url := "https://www.sagelib.com/videos/" + videoId + "/content"

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        fmt.Println("Failed to create request:", err)
        return
    }
    req.Header.Set("Authorization", "Bearer "+apiKey)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()

    fmt.Println("Status Code:", resp.StatusCode)

    out, err := os.Create("output.mp4")
    if err != nil {
        fmt.Println("Failed to create output file:", err)
        return
    }
    defer out.Close()

    _, err = io.Copy(out, resp.Body)
    if err != nil {
        fmt.Println("Failed to save video:", err)
        return
    }
    fmt.Println("Video saved to output.mp4")
}

响应参数

Body 参数

参数名称 描述
id string 视频任务 ID
object string 可选值:video
固定为 video
model string 模型 ID
created_at integer 创建时间戳(Unix 秒)
expires_at integer 过期时间戳(Unix 秒)
status string 可选值:created、in_progress、completed、failed、expired
初始为 created,轮询后为 in_progress

响应示例

{
  "id": "${video_id}",
  "object": "video",
  "model": "doubao-seedance-2-5-260628",
  "status": "created"
}
{
  "id": "${video_id}",
  "object": "video",
  "model": "doubao-seedance-2-5-260628",
  "created_at": 1789541351,
  "expires_at": 1789714151,
  "status": "in_progress"
}