New: Nano Banana 2.1Try the model
API Stock

API Stock vs Eachlabs

Eachlabs alternative

Compare Eachlabs and API Stock for API-driven image generation. See shared model prices and how an Eachlabs prediction becomes a task with polling or webhook delivery.

How API Stock compares with Eachlabs

When to choose API Stock

Choose API Stock when your application already orchestrates its own workflow and needs a generation API for each step, rather than a visual workflow platform.

When to keep Eachlabs

Keep Eachlabs for workflows or platform tools your application needs beyond a single generation. Multi-step flows must be rebuilt and each required model checked against our catalog.

Eachlabs API documentation

Scroll horizontally to read all table columns.

API changes: Eachlabs to API Stock
Integration detailEachlabsAPI Stock
RequestPOST /v1/prediction/POST /api/v1/generation/create
AuthenticationAuthorization: BearerAuthorization: Bearer
Model identifierbytedance-seedream-v4-5-text-to-image / version: 0.0.1seedream-4-5

This compares the example model below, not every endpoint the provider offers. Shared model names do not guarantee identical parameters, moderation or output.

Price comparison: Eachlabs and API Stock

Selected shared models with matching billing units. Our prices come from the current catalog; competitor prices are dated observations linked to their sources.

Price comparison: Eachlabs and API Stock
Seedream 4.52K · per image · text to imageAPI Stock$0.036Eachlabs$0.0410% lower
Nano Bananaper image · text to imageAPI Stock$0.015Eachlabs$0.0462.5% lower

One image from a text prompt, without reference images. These are public base rates; plans, volume discounts, other resolutions and editing can change the final price.

What a workload costs

Seedream 4.5 · 2K

1,000 images, the configuration above

API Stock
$36
Eachlabs
$40

Nano Banana

1,000 images, the configuration above

API Stock
$15
Eachlabs
$40

Illustrative totals from the rows above, without volume discounts, subscriptions or additional paid options. These examples do not predict latency or identical outputs.

Pricing

Migrating from Eachlabs

Replace /v1/prediction with /api/v1/generation/create. Map the versioned model identifier and nested input to a public model id and documented parameters. Replace webhook_url with webhook and adapt prediction result parsing.

  1. 1

    Create an account, top up your prepaid balance and issue an API key.

  2. 2

    POST to /api/v1/generation/create with the public model id and its documented parameters. Each task generates one output.

  3. 3

    Read taskId from the response. Poll GET /api/v1/task/status/TASK_ID, or set webhook in the creation request.

Eachlabs

bash
curl --fail-with-body 'https://api.eachlabs.ai/v1/prediction/' \
-H "Authorization: Bearer $EACHLABS_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "bytedance-seedream-v4-5-text-to-image",
"version": "0.0.1",
"input": {
"prompt": "A ceramic mug on a wooden table, soft morning light",
"image_size": "landscape_16_9",
"num_images": 1,
"max_images": 1
}
}'

API Stock

bash
curl --fail-with-body 'https://api.api-stock.com/api/v1/generation/create' \
-H "Authorization: Bearer $API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "seedream-4-5",
"prompt": "A ceramic mug on a wooden table, soft morning light",
"resolution": "2K",
"size": "16:9"
}'
Complete example: create a task and download its result

Run on your server with Node 22+ or Bun and API_KEY set. This example creates one paid task, then polls without creating it again. Finished URLs are temporary: save the file to your own storage.

javascript
import { writeFile } from "node:fs/promises";
const baseURL = "https://api.api-stock.com/api/v1";
const apiKey = process.env.API_KEY;
if (!apiKey) throw new Error("Set API_KEY on the server");
async function request(path, options = {}) {
const response = await fetch(baseURL + path, {
...options,
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) throw new Error(await response.text());
return response.json();
}
const { taskId } = await request("/generation/create", {
method: "POST",
body: JSON.stringify({
"model": "seedream-4-5",
"prompt": "A ceramic mug on a wooden table, soft morning light",
"resolution": "2K",
"size": "16:9"
}),
});
if (!taskId) throw new Error("Missing taskId");
const deadline = Date.now() + 10 * 60_000;
let fileUrl;
while (Date.now() < deadline) {
const { data } = await request(`/task/status/${encodeURIComponent(taskId)}`);
if (data.status === "finished") {
fileUrl = data.files?.[0]?.fileUrl;
if (!fileUrl) throw new Error("Task finished without a file");
break;
}
if (data.status === "failed" || data.status === "expired") {
throw new Error(data.errorMessage || data.status);
}
await new Promise((resolve) => setTimeout(resolve, 2000));
}
if (!fileUrl) throw new Error(`Still processing: save taskId ${taskId} and resume polling`);
const file = await fetch(fileUrl, { signal: AbortSignal.timeout(60_000) });
if (!file.ok) throw new Error(`Download failed: ${file.status}`);
const mime = file.headers.get("content-type")?.split(";")[0];
const extension = { "image/png": "png", "image/jpeg": "jpg", "image/webp": "webp" }[mime] || "bin";
await writeFile(`generated-image.${extension}`, new Uint8Array(await file.arrayBuffer()));

Keep API keys on your server. When migrating, test one request and compare its parameters, status handling and output before moving production traffic.

Frequently asked questions

How do I migrate from Eachlabs?

Replace /v1/prediction with /api/v1/generation/create. Map the versioned model identifier and nested input to a public model id and documented parameters. Replace webhook_url with webhook and adapt prediction result parsing.

Is API Stock always cheaper than Eachlabs?

No. Compare the exact model, configuration and billing unit in the table. Prices can move in either direction; check both catalogs before sending production traffic.

Can I move every Eachlabs workflow?

Keep Eachlabs for workflows or platform tools your application needs beyond a single generation. Multi-step flows must be rebuilt and each required model checked against our catalog.

What happens to failed or unfinished requests?

Media tasks retry according to the configured routes; a reserve is used when one is available. A terminal generation failure is refunded. Keep polling a processing task instead of creating a duplicate. An expired file URL is not a failed generation.

How do I top up the balance?

Available payment methods, currencies and minimum top-up amounts are shown in your account before payment. There is no subscription: model usage is charged to your prepaid balance.

Try your first request on API Stock

Choose a model, check its parameters and price, then create an API key in your account. Start with one request before moving your traffic.