New model MiMo-V2.6 Flash is launching 
Inferway
登录注册
跳转至正文
Interactions API

通过 Interactions API 接入视频模型

视频示例

本示例为所选模型 inferway/minimax-h3-768p 的 Interactions API 流程:后台创建、轮询、下载。

前置条件:bash、curl、jq;Python 示例仅需标准库;TypeScript 示例需要带 fetch 的 Node。设置 INFERWAY_API_KEY 环境变量;可选地用 INFERWAY_IDEMPOTENCY_KEY 恢复之前的创建。

  1. 创建:向 /interactions 发送顶层 JSON 体(op=create,mode=background,duration_seconds 与 prompt),并带上持久的 Idempotency-Key。
  2. 轮询:用 op=get 与返回的 interaction_id 有界地轮询;failed/cancelled/expired/recovery_required 是终止错误。
  3. 下载:成功且 result.download_url 非空后,用一次不带 API 头部的独立 HTTPS 请求下载,不跟随重定向。

轮询达到上限时任务可能仍在运行:保留 interaction ID 与 Idempotency-Key 稍后恢复;下载 URL 过期后再次调用 get 获取新的 URL。

隐私层级:retained_7d。视频产物按所选模型的策略保存,并非聊天那样的零保留。

#!/usr/bin/env bash
# Inferway video generation via the Interactions API.
# Prerequisites: bash, curl, jq.
# Required env: INFERWAY_API_KEY.
# Optional env: INFERWAY_IDEMPOTENCY_KEY — resume a previous create with this
# key; otherwise a fresh key is generated.
# On success the video is saved to ./inferway-video.mp4.
set -u

API_BASE="https://api.inferway.ai/v1"
MODEL="inferway/minimax-h3-768p"
PROMPT="A drone shot along a coastline at dawn."
DURATION_SECONDS=5
SAVE_PATH=inferway-video.mp4

workdir=$(mktemp -d) || exit 1
cleanup() { rm -rf "$workdir"; }
trap cleanup EXIT HUP INT TERM

if [ -z "${INFERWAY_API_KEY:-}" ]; then
  echo "error: INFERWAY_API_KEY is required" >&2
  exit 1
fi

idempotency_key="${INFERWAY_IDEMPOTENCY_KEY:-}"
if [ -z "$idempotency_key" ]; then
  if command -v uuidgen >/dev/null 2>&1; then
    idempotency_key=$(uuidgen | tr 'A-Z' 'a-z') || exit 1
  elif command -v uuid >/dev/null 2>&1; then
    idempotency_key=$(uuid | tr -d '-') || exit 1
  else
    idempotency_key="iv-$(date +%s%N)-$$"
  fi
fi
echo "Idempotency-Key: $idempotency_key"

interactions_url="$API_BASE/interactions"
response_headers=$workdir/headers
response_body=$workdir/body
create_body_file=$workdir/create-body.json

jq -cn \
  --arg model "$MODEL" \
  --argjson durationSeconds "$DURATION_SECONDS" \
  --arg prompt "$PROMPT" \
  '{op: "create", model: $model, mode: "background", duration_seconds: $durationSeconds, prompt: $prompt}' \
  > "$create_body_file" || exit 1

attempt=0
while :; do
  attempt=$((attempt + 1))
  rc=0
  curl -sS --connect-timeout 30 --max-time 30 \
    -D "$response_headers" \
    --data-binary @"$create_body_file" \
    -H "Authorization: Bearer $INFERWAY_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $idempotency_key" \
    "$interactions_url" > "$response_body" 2> "$workdir/curl-err" || rc=$?
  if [ "$rc" -ne 0 ]; then
    if [ "$attempt" -ge 5 ]; then
      echo "error: create request failed on the 5th attempt: $(cat "$workdir/curl-err")" >&2
      exit 1
    fi
    sleep $((1 << (attempt - 1)))
    continue
  fi
  status=$(head -n 1 "$response_headers" | tr -d '\r' | awk '{print $2}')
  case "$status" in
    200|202)
      id=$(jq -er '.id | select(type == "string" and length > 0)' "$response_body" 2>/dev/null) || {
        echo "error: accepted response has no usable id" >&2
        exit 1
      }
      echo "task id: $id"
      break
      ;;
    429|5[0-9][0-9])
      if jq -e '((.error? // {}) | (type == "object") and .retryable == false) or (.retryable? == false)' "$response_body" >/dev/null 2>&1; then
        echo "error: server reported a non-retryable failure (status $status)" >&2
        jq -c . "$response_body" >&2 || true
        exit 1
      fi
      if [ "$attempt" -ge 5 ]; then
        echo "error: create request failed with status $status on the 5th attempt" >&2
        exit 1
      fi
      retry_after=$(sed -n '1,/^$/s/^Retry-After:[[:space:]]*//Ip' "$response_headers" | head -n 1 | tr -d '\r' | tr -d '[:space:]')
      if printf '%s' "${retry_after:-}" | grep -Eq '^[0-9]+$'; then
        if [ "$retry_after" -gt 30 ]; then
          echo "error: server asked to wait $retry_after s (ceiling 30 s); resume later with:" >&2
          echo "  INFERWAY_IDEMPOTENCY_KEY=$idempotency_key" >&2
          exit 1
        else
          sleep "$retry_after"
        fi
      else
        sleep $((1 << (attempt - 1)))
      fi
      continue
      ;;
    *)
      if jq -e '((.error? // {}) | (type == "object") and .retryable == false) or (.retryable? == false)' "$response_body" >/dev/null 2>&1; then
        echo "error: server reported a non-retryable failure (status $status)" >&2
      else
        echo "error: create request failed with status $status" >&2
      fi
      jq -c . "$response_body" >&2 || true
      exit 1
      ;;
  esac
done

# --- Poll at most 30 times, 5 s apart, 30 s per request ---------------------
download_url=""
poll=0
while [ "$poll" -lt 30 ]; do
  poll=$((poll + 1))
  : > "$response_headers"
  rc=0
  curl -sS --connect-timeout 30 --max-time 30 \
    -D "$response_headers" \
    --data-binary "$(jq -cn --arg id "$id" '{op: "get", interaction_id: $id}')" \
    -H "Authorization: Bearer $INFERWAY_API_KEY" \
    -H "Content-Type: application/json" \
    "$interactions_url" > "$response_body" 2> "$workdir/curl-err" || rc=$?
  status=$(head -n 1 "$response_headers" | tr -d '\r' | awk '{print $2}')
  if [ "$rc" -ne 0 ] || [[ ! "$status" =~ ^2[0-9][0-9]$ ]] || ! jq -e . "$response_body" >/dev/null 2>&1; then
    echo "polling stopped (status=${status:-n/a}); the job may still be running." >&2
    echo "resume later with:" >&2
    echo "  task id: $id" >&2
    echo "  INFERWAY_IDEMPOTENCY_KEY=$idempotency_key" >&2
    exit 1
  fi
  state=$(jq -r '.state // empty' "$response_body")
  case "$state" in
    failed|cancelled|expired|recovery_required)
      echo "error: task $id ended in state '$state'" >&2
      exit 1
      ;;
    succeeded)
      candidate=$(jq -er '.result? | select(type == "object") | .download_url? | select(type == "string" and length > 0)' "$response_body" 2>/dev/null) || candidate=""
      if [ -n "$candidate" ]; then
        download_url="$candidate"
        break
      fi
      ;;
  esac
  if [ "$poll" -lt 30 ]; then
    sleep 5
  fi
done

if [ -z "$download_url" ]; then
  echo "wait limit reached (30 polls); the job may still be running." >&2
  echo "resume later with:" >&2
  echo "  task id: $id" >&2
  echo "  INFERWAY_IDEMPOTENCY_KEY=$idempotency_key" >&2
  exit 1
fi

case "$download_url" in
  https://*) ;;
  *)
    echo "error: refusing to download a non-HTTPS URL" >&2
    exit 1
    ;;
esac

# --- Download: separate request, no API headers, no redirects ---------------
rc=0
curl -sS --connect-timeout 30 --max-time 30 \
  -D "$response_headers" -o "$workdir/video" \
  "$download_url" || rc=$?
if [ "$rc" -ne 0 ]; then
  echo "error: download failed (network/timeout)" >&2
  exit 1
fi
status=$(head -n 1 "$response_headers" | tr -d '\r' | awk '{print $2}')
case "$status" in
  2??) ;;
  3??)
    echo "error: download redirected (status $status); refusing to follow redirects" >&2
    exit 1
    ;;
  *)
    echo "error: download failed with status $status" >&2
    exit 1
    ;;
esac

mv "$workdir/video" "$SAVE_PATH" || exit 1
echo "SAVED $SAVE_PATH"