SEEDANCE25APIINDEPENDENT
FIELD NOTES / INTEGRATION

Seedance 2.5 EvoLink API Guide: Live Integration Checklist

Live API integration pipeline with a contract snapshot, adapter, mock state machine, safety gate, and fallback route

The official Seedance 2.5 API and EvoLink integration are live. You can now define a provider adapter, generate transport types, validate your domain payload, submit asynchronous jobs, test representative failures, and keep a Seedance 2.0 rollback.

Route availability alone does not make a workload production-ready. The correct goal is a live integration with measured quality, queue time, billing, and failure behavior for your own inputs.

Verification snapshot for August 7, 2026: the official developer API and EvoLink route are live. EvoLink exposes three workflow IDs, 4–30 seconds, 480p/720p, and the R2V reference split. Read the current price and account limits in EvoLink before scaled traffic. Seedance25API publishes a site-authored live integration aid and is not affiliated with ByteDance.

What belongs in this guide—and what belongs in the API reference

The API quickstart owns exact fields, endpoint examples, and the current request schema. This guide owns the engineering process around that schema.

QuestionOwning page
Which live pattern can be used today?API quickstart and the current EvoLink documentation
Which request and polling shape can agents load?The integration schema
How do we generate a typed client?This guide
How do we test before scaling traffic?This guide
How do we handle schema changes?This guide
What can fall back to 2.0?This guide and the 2.5 vs 2.0 decision guide
What is the final live price?Pricing page and provider console

Keeping those responsibilities separate prevents a Blog from becoming a stale copy of the documentation.

Seedance 2.5 API readiness workflow from a pinned planning contract through mocks and observability to a circuit breaker and eligible fallback

Define the production-validation boundary first

Write these statements into the project README or architecture decision record:

Before traffic: request validation, type generation, job lifecycle,
error mapping, fallback policy, logging, and callback idempotency.

Measure on the live route: output quality, latency, reference ingestion,
callback delivery, actual cost, failure behavior, and account rate limits.

This boundary changes the acceptance criteria. CI should pass without making a paid call; a small canary then validates live-only behavior before traffic expands.

Step 1: snapshot and version the integration schema

Do not generate client code from a moving remote URL on every production build. Download or vendor a reviewed snapshot, record its hash, and update it intentionally.

curl -fsSL https://seedance25api.io/openapi.json \
  -o contracts/seedance-2.5.openapi.json

shasum -a 256 contracts/seedance-2.5.openapi.json

The integration schema models:

  • live POST /v1/videos/generations task creation;
  • polling through GET /v1/tasks/{task_id};
  • a required workflow-specific model plus prompt;
  • the documented launch fields and reference limits;
  • the current EvoLink task-state vocabulary: pending, processing, completed, and failed;
  • representative errors for local resilience testing.

EvoLink provider documentation remains authoritative. Pinning this independent schema gives the team reviewable contract changes while the live route and task retrieval stay behind a provider adapter.

Step 2: generate types but keep domain types independent

Generate transport types from the snapshot:

npx openapi-typescript@7 contracts/seedance-2.5.openapi.json \
  -o src/generated/seedance-transport.ts

Do not let generated types become the application’s domain model. Generated transport code will change when the contract changes. Product concepts such as a review state, reference role, or accepted output belong in stable application types.

export type VideoRequest = {
  prompt: string;
  durationSeconds: number;
  quality?: string;
  references: Array<{
    type: "image" | "video" | "audio";
    url: string;
    role: string;
  }>;
};

export type VideoJob = {
  id: string;
  state: "queued" | "running" | "generated" | "failed";
  outputUrl?: string;
  errorCode?: string;
};

The adapter maps stable domain types to the current provider transport.

Step 3: keep route capabilities in configuration

Use the three live EvoLink workflow IDs, but keep the selected ID configurable instead of spreading it through UI components, database records, tests, and worker code.

type RouteConfig = {
  baseUrl: string;
  model: string;
  maxDuration?: number;
  qualities?: string[];
  maxImages?: number;
  maxVideos?: number;
  maxAudio?: number;
  enabled: boolean;
};

export const seedance25: RouteConfig = {
  baseUrl: process.env.EVOLINK_BASE_URL ?? "https://api.evolink.ai/v1",
  model: process.env.SEEDANCE_25_MODEL ?? "seedance-2.5-text-to-video",
  maxDuration: Number(process.env.SEEDANCE_25_MAX_DURATION ?? 30),
  qualities: (process.env.SEEDANCE_25_QUALITIES ?? "480p,720p").split(","),
  maxImages: 30,
  maxVideos: 10,
  maxAudio: 10,
  enabled: Boolean(process.env.EVOLINK_API_KEY),
};

The route becomes executable only when the human supplies EVOLINK_API_KEY. Add a startup assertion if code can submit without credentials, validate workflow-specific fields, and rerun smoke tests before expanding traffic.

Step 4: validate before the provider sees the request

Client-side controls improve usability, but server-side validation protects cost and reliability.

export function validateRequest(input: VideoRequest, route: RouteConfig) {
  const errors: string[] = [];

  if (!input.prompt.trim()) errors.push("prompt is required");
  if (route.maxDuration && input.durationSeconds > route.maxDuration) {
    errors.push(`duration must be at most ${route.maxDuration}`);
  }
  if (input.quality && route.qualities && !route.qualities.includes(input.quality)) {
    errors.push(`quality ${input.quality} is not enabled for this route`);
  }

  const count = (type: VideoRequest["references"][number]["type"]) =>
    input.references.filter((r) => r.type === type).length;

  if (route.maxImages && count("image") > route.maxImages) errors.push("too many image references");
  if (route.maxVideos && count("video") > route.maxVideos) errors.push("too many video references");
  if (route.maxAudio && count("audio") > route.maxAudio) errors.push("too many audio references");

  return errors;
}

URL reachability, media metadata, authorization, and signed-URL lifetime need their own checks. A valid URL string can still expire before the provider retrieves it.

Step 5: mock the full asynchronous lifecycle

A useful mock is stateful. It should return a job ID and advance through states rather than returning a completed video immediately.

{
  "create": { "id": "mock-job-001", "status": "pending" },
  "poll_sequence": [
    { "id": "mock-job-001", "status": "pending", "progress": 0 },
    { "id": "mock-job-001", "status": "processing", "progress": 40 },
    {
      "id": "mock-job-001",
      "status": "completed",
      "progress": 100,
      "results": ["https://example.invalid/mock-output.mp4"]
    }
  ]
}

The URL uses the reserved .invalid domain so no test can accidentally download an unrelated file.

Build fixtures for every meaningful outcome:

FixtureExpected application behavior
200 createPersist provider job ID before polling
400 invalid requestShow field-level correction; never retry unchanged
401 invalid keyStop and ask the human to repair key configuration
429 rate limitedApply bounded backoff with jitter
simulated 503 unavailableOpen route circuit and evaluate fallback eligibility
completedSave output, usage, and raw response; enter human review
failedSave reason; do not mark as transport success
duplicate callbackReturn success without applying the state transition twice

Also simulate a job that stays processing beyond the application deadline. The provider job may continue, but the user-facing operation needs a clear timeout state and a way to resume checking.

Step 6: schema-test the adapter, then contract-test the live route

The first schema test should prove that the application request is accepted by the pinned integration schema. The second should prove that every task state maps correctly. The third should fail when the schema changes unexpectedly. EvoLink provider documentation remains authoritative for contract differences.

import assert from "node:assert/strict";

const mapped = mapProviderJob({
  id: "mock-job-001",
  status: "processing",
  progress: 40,
});

assert.deepEqual(mapped, {
  id: "mock-job-001",
  state: "running",
  outputUrl: undefined,
  errorCode: undefined,
});

Add a CI step that compares the reviewed contract snapshot with a newly fetched copy, but do not overwrite automatically:

curl -fsSL https://seedance25api.io/openapi.json \
  -o /tmp/seedance-2.5.latest.json

diff -u contracts/seedance-2.5.openapi.json \
  /tmp/seedance-2.5.latest.json

A diff is a review trigger, not proof of a breaking change. Description updates may be harmless; a required field, enum, state, or response change may require code and fixture updates.

Step 7: design retries by failure class

“Retry three times” is not a policy. Each failure class needs a different response.

FailureRetry?Policy
Network timeout before responseMaybeRetry with idempotency protection or reconcile before resubmitting
400NoCorrect the request
401NoRepair secret or permission
429YesHonor provider guidance; exponential backoff plus jitter
simulated 503LimitedOpen circuit; retry later or use an eligible fallback
Job failedConditionalRetry only if reason is understood and policy allows
Poll timeoutYesResume polling the same job; do not create a duplicate

If the provider does not expose an idempotency key, the application needs its own submission record. A network timeout after the provider accepted a request is dangerous: blind resubmission may create two billable jobs.

Step 8: make fallback eligibility explicit

Seedance 2.0 can exercise the surrounding application today, but fallback is not a string replacement. A 2.5-planned request may exceed 2.0 duration or reference constraints.

function canFallbackToSeedance20(input: VideoRequest) {
  return (
    input.durationSeconds <= 15 &&
    input.references.filter((r) => r.type === "image").length <= 9 &&
    input.references.filter((r) => r.type === "video").length <= 3 &&
    input.references.filter((r) => r.type === "audio").length <= 3
  );
}

The limits above reflect the cited public EvoLink 2.0 guide and must still be checked against the active route. If the request is not eligible, give the user a choice: shorten, remove references, retry the 2.5 route later, or choose another verified route. Silent truncation is not a safe fallback.

Step 9: log the evidence needed before scaling traffic

Prepare structured fields now:

internal_request_id
provider_route
model_id
contract_version
provider_job_id
submit_attempt
http_status
provider_state
duration_requested
reference_counts
created_at / completed_at
usage_or_cost
output_url_expiry
review_outcome
fallback_route

Never log the bearer token or sensitive signed URLs without redaction. Logs should answer whether an error came from validation, authentication, capacity, generation, output retrieval, or human rejection.

Pre-production-traffic verification checklist

Contract-tested software still needs live evidence. Run these checks in order:

  1. Confirm the final model ID and account entitlement in provider documentation.
  2. Replace the planning assumptions with the live provider schema and review every difference.
  3. Create a short, low-risk smoke job.
  4. Verify every returned state and output access.
  5. Confirm the billing record for success and investigate failure billing separately.
  6. Test rate-limit and temporary-unavailability handling without creating a retry storm.
  7. Verify callback authentication, duplication, and ordering if callbacks are enabled.
  8. Run the frozen workload evaluation set.
  9. Enable only a small canary of eligible jobs.
  10. Confirm the kill switch returns traffic to a verified route.

The integration is ready for a canary only when the application behavior and provider behavior match. It is ready for broader production only when output acceptance, cost, latency, and error thresholds pass.

Pin the machine-readable integration schema, generate types, and test the asynchronous state machine. Use the live 2.5 example in the API quickstart, the agent guide for safe key handoff, and Seedance 2.0 only where rollback eligibility is explicit.

That work is valuable even if a final Seedance 2.5 field changes. The adapter isolates change; the job, review, logging, and evaluation systems survive it.

Sources

Verification note: checked against EvoLink’s Seedance 2.5, Seedance 2.0, and task-detail documentation on August 7, 2026. The local OpenAPI file is a site-authored integration aid; EvoLink’s own documentation and console remain authoritative for current model IDs, request fields, limits, pricing, and error contracts.

Q&AQUICK ANSWERS
Q.01Can developers use Seedance 2.5 through EvoLink now?
Yes. The official API and EvoLink integration are live. Choose the T2V, I2V, or R2V model ID, create an EvoLink key, and begin with a short test.
Q.02Should the Seedance 2.5 model ID be hard-coded?
Keep it configurable so each request can select the matching workflow and the application can retain Seedance 2.0 as rollback.
Q.03What should a local mock simulate?
At minimum simulate job creation, pending, processing, completed, failed, invalid request, missing key, rate limiting, server unavailability, duplicate polling, and a callback arriving more than once. These are resilience scenarios, not claims about a final Seedance 2.5 error contract.
Q.04Does passing local schema tests mean the integration is production-ready?
No. Local tests prove that the application handles its current planning shape and modeled state transitions. Production readiness additionally requires the official provider schema, live authentication, billing, output retrieval, latency, failure, and quality tests.
Q.05Why use Seedance 2.0 as a fallback?
It gives the team a documented rollback if a 2.5 workload misses its quality, latency, or cost threshold. The fallback must be eligibility-based because not every 2.5 request can be represented safely on 2.0.
Q.06Why mock HTTP 503 for the live Seedance 2.5 route?
A video application should tolerate temporary upstream unavailability regardless of provider, and mocks let you exercise that path cheaply without burning live jobs. Treat the fixture as a resilience test, not as evidence that the Seedance 2.5 create endpoint documents that exact response.