API Reference · v1

Developer Documentation

Integrate ImagineLab's generation APIs — image, video, voice, music, writing, and infographic — into your own applications, pipelines, and workflows.

Base URL: https://api.imaginelab.art/api/v1Auth: Bearer tokenFormat: JSONProtocol: HTTPS only

API Access — by request only

Programmatic API access is available on the Ultimate Visionary Studio and Titan Studio plans. Each approved integration receives a scoped, revocable API key. Contact our team to request access before building.

Introduction

What this API is, what it is not, and how versioning works.

The ImagineLab API is a REST interface over HTTPS. All endpoints live under https://api.imaginelab.art/api/v1, accept and return JSON, and authenticate with a per-integration bearer token. There is no SDK or GraphQL layer — standard HTTP clients work.

Generation is always asynchronous: every creation call returns immediately with a job ID, and the actual compute happens in the background. You poll the status endpoint until the job reaches completed or failed.

Versioning

The API version is part of the URL (/v1/). Breaking changes — field removals, renamed endpoints, changed authentication — will be released under a new version prefix, and the previous version will remain available for a deprecation window that we communicate by email to all active API integrators. Non-breaking additions (new fields, new generation types) can appear in the current version without notice.

Supported generation types

type valueLabOutput
imageImage Lab / Image StudioImage file (JPEG/PNG/WebP)
videoVideo LabVideo file (MP4)
voiceVoice LabAudio file (MP3/WAV)
musicMusic LabAudio file (MP3)
textWriting LabPlain text or Markdown
infographicInfographic LabImage file (PNG/SVG)
chatImagine ChatText (streamed or complete)

Quick Start

Generate your first image in under two minutes.

  1. Upgrade to a plan that includes API access (Ultimate Visionary Studio or Titan Studio).
  2. Submit an API access request — our team issues a scoped key within one business day.
  3. Store the key in an environment variable (IMAGINELAB_API_KEY). Never hard-code it.
  4. Call POST /generations to create a job.
  5. Poll GET /generations/{id}/status at a reasonable interval (2–5 s) until completed.
  6. Retrieve the output URLs from GET /generations/{id}.

End-to-end example

Python · image generation
import os, time, requests

BASE = "https://api.imaginelab.art/api/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['IMAGINELAB_API_KEY']}",
    "Content-Type": "application/json",
}

# 1. Create a generation job
res = requests.post(f"{BASE}/generations", headers=HEADERS, json={
    "generation_type": "image",
    "model_name": "seedream-5-lite",
    "prompt": "A neon city skyline at dusk, ultra-detailed, cinematic lighting",
    "settings": {"aspect_ratio": "16:9"},
})
res.raise_for_status()
job = res.json()
job_id = job["id"]
print(f"Job created: {job_id}  (status: {job['status']})")

# 2. Poll until complete
MAX_POLLS = 60          # 60 × 3 s = 3-minute timeout
for attempt in range(MAX_POLLS):
    time.sleep(3)
    status_res = requests.get(f"{BASE}/generations/{job_id}/status", headers=HEADERS)
    status_res.raise_for_status()
    status = status_res.json()
    print(f"  [{attempt+1}/{MAX_POLLS}] status={status['status']}  progress={status.get('progress', 0)}%")
    if status["status"] == "completed":
        break
    if status["status"] == "failed":
        raise RuntimeError(f"Generation failed: {status.get('error_message', 'unknown')}")
else:
    raise TimeoutError("Generation did not complete within the polling window.")

# 3. Fetch result
result = requests.get(f"{BASE}/generations/{job_id}", headers=HEADERS).json()
for output in result["outputs"]:
    print("Output URL:", output["url"])
Node.js · TypeScript
import axios from 'axios';

const BASE = 'https://api.imaginelab.art/api/v1';
const headers = {
  Authorization: `Bearer ${process.env.IMAGINELAB_API_KEY}`,
  'Content-Type': 'application/json',
};

async function generateImage(prompt: string): Promise<string[]> {
  // 1. Create
  const { data: job } = await axios.post(`${BASE}/generations`, {
    generation_type: 'image',
    model_name: 'seedream-5-lite',
    prompt,
    settings: { aspect_ratio: '1:1' },
  }, { headers });

  // 2. Poll with exponential back-off
  const startedAt = Date.now();
  const TIMEOUT_MS = 3 * 60 * 1000;   // 3 minutes
  let delay = 2000;

  while (Date.now() - startedAt < TIMEOUT_MS) {
    await new Promise(r => setTimeout(r, delay));
    delay = Math.min(delay * 1.5, 8000); // cap at 8 s

    const { data: s } = await axios.get(`${BASE}/generations/${job.id}/status`, { headers });
    if (s.status === 'completed') break;
    if (s.status === 'failed') throw new Error(`Generation failed: ${s.error_message}`);
  }

  // 3. Result
  const { data: result } = await axios.get(`${BASE}/generations/${job.id}`, { headers });
  return result.outputs.map((o: { url: string }) => o.url);
}

generateImage('A serene forest at golden hour').then(console.log);

Authentication

Every request must carry a valid bearer token. Keys are per-integration and revocable.

Pass your API key in the Authorization header on every request:

Authorization: Bearer YOUR_API_KEY

Key properties

  • Keys are scoped — each key is tied to one integration and one account. A key cannot access another account's generations or credits.
  • Keys are revocable at any time by your account owner or by our team. Revocation takes effect immediately.
  • Keys do not expire automatically, but they are deactivated if the associated plan lapses.
  • A single account may hold multiple keys (one per integration). Request additional keys via support.

Never expose your key client-side

API keys must live on your server only. Do not embed them in browser JavaScript, mobile app binaries, public repositories, or CI/CD logs. If a key is leaked, contact support@imaginelab.art immediately so we can revoke and reissue it. Leaked keys can be used to drain your EDT balance.

Testing without a key

The /v1/ping endpoint returns the API version and timestamp without authentication. Use it to verify network connectivity and TLS configuration before your key is issued.

Rate Limits

Limits protect system stability for all users. Exceed them and you receive 429.

ScopeLimitWindow
Global (per API key)120 requests1 minute
POST /generations30 creates1 minute
GET /generations/*/status300 polls1 minute
Concurrent active jobs10 jobsat any time
Daily generation budgetPlan-dependent24 hours (UTC)

Rate limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are included in every response. After a 429, respect the Retry-After header.

Polling best practice

Poll status at 2–5 second intervals, not faster. Aggressive polling counts against your rate limit and does not speed up generation. For high-volume pipelines, increase the interval progressively (see Best Practices for an exponential back-off example).

Generations

Create, track, and retrieve async generation jobs.

Health check

GET/ping

No auth required. Returns API version and server timestamp.

Response
{ "status": "ok", "version": "v1", "timestamp": "2026-08-23T09:00:00Z" }

List available models

GET/generations/models

Returns all models your key is authorised to use, grouped by generation type.

Response
{
  "models": [
    {
      "name": "seedream-5-lite",
      "generation_type": "image",
      "provider": "ByteDance",
      "available": true
    },
    ...
  ]
}

Create a generation

POST/generations

Request body

FieldTypeDescription
generation_typerequiredstringOne of: image · video · voice · music · text · infographic · chat
model_namerequiredstringExact model name from GET /generations/models
promptrequiredstringThe creative instruction. Max 4,000 characters for most types.
settingsobjectType-specific parameters (aspect_ratio, duration, voice_id, etc.). See Generation Types.
project_idstring|nullOptional project tag. Useful for grouping generations in your dashboard.
webhook_urlstring|nullIf provided, a POST is sent to this URL when the job finishes. Must be HTTPS.
JSON body — image example
{
  "generation_type": "image",
  "model_name": "seedream-5-lite",
  "prompt": "A neon city skyline at dusk, ultra-detailed, cinematic lighting",
  "settings": {
    "aspect_ratio": "16:9",
    "quality": "high"
  }
}
cURL
curl -X POST https://api.imaginelab.art/api/v1/generations \
  -H "Authorization: Bearer $IMAGINELAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "generation_type": "image",
    "model_name": "seedream-5-lite",
    "prompt": "A neon city skyline at dusk",
    "settings": { "aspect_ratio": "16:9" }
  }'
201 Created
{
  "id": "gen_8f3a21c7",
  "generation_type": "image",
  "model_name": "seedream-5-lite",
  "prompt": "A neon city skyline at dusk, ultra-detailed, cinematic lighting",
  "status": "pending",
  "credit_cost": 5,
  "settings": { "aspect_ratio": "16:9", "quality": "high" },
  "created_at": "2026-08-23T09:01:00Z",
  "outputs": []
}

Poll status

GET/generations/{id}/status

Lightweight endpoint. Poll at 2–5 second intervals.

Response — in progress
{
  "id": "gen_8f3a21c7",
  "status": "processing",
  "progress": 62,
  "estimated_remaining_seconds": 14
}
Response — completed
{
  "id": "gen_8f3a21c7",
  "status": "completed",
  "progress": 100,
  "estimated_remaining_seconds": 0
}

Fetch result

GET/generations/{id}

Returns the full generation record including output URLs. Available once status is 'completed'.

Response — image
{
  "id": "gen_8f3a21c7",
  "generation_type": "image",
  "status": "completed",
  "credit_cost": 5,
  "outputs": [
    {
      "url": "https://cdn.imaginelab.art/outputs/gen_8f3a21c7/result.png",
      "mime_type": "image/png",
      "width": 1920,
      "height": 1080,
      "expires_at": "2026-09-22T09:01:00Z"
    }
  ],
  "created_at": "2026-08-23T09:01:00Z",
  "completed_at": "2026-08-23T09:01:24Z"
}

Output URL expiry

Output URLs are signed and expire after 30 days. Download and store the files in your own infrastructure before the URL expires. Expired URLs return 403. We do not re-issue URLs for deleted or expired outputs.

List generations

GET/generations?type={type}&limit={n}&cursor={cursor}

Paginated history. Default limit: 20. Max: 100.

Response
{
  "generations": [ { "id": "gen_8f3a21c7", "status": "completed", ... }, ... ],
  "cursor": "eyJpZCI6MTgzMH0=",
  "has_more": true
}

Generation Types

Type-specific settings passed in the 'settings' object of a create request.

imageImage Generation

FieldTypeDescription
aspect_ratio"1:1" | "16:9" | "4:3" | "3:4" | "9:16"Output aspect ratio. Default: 1:1.
quality"standard" | "high" | "ultra"Rendering quality. Higher = more credits.
stylestringOptional style hint (e.g. "photorealistic", "anime"). Model-dependent.
negative_promptstringElements to avoid. Supported by select models.

videoVideo Generation

FieldTypeDescription
aspect_ratio"16:9" | "9:16" | "1:1" | "4:3"Video frame ratio.
duration"5s" | "10s" | "15s" | "30s"Clip length. Available options vary by model.
resolution"720p" | "1080p" | "4K"Output resolution. Model-dependent.
input_imagestring (URL)Source image for image-to-video workflows.

voiceVoice / TTS

FieldTypeDescription
voice_idstringVoice identifier from GET /voices. Required.
language"en-US" | "en-GB" | …BCP-47 language tag. Default: en-US.
stabilitynumber 0–1Voice consistency (0 = expressive, 1 = stable). Default: 0.75.
speednumber 0.5–2.0Playback speed multiplier. Default: 1.0.

musicMusic Generation

FieldTypeDescription
genrestringMusical genre (e.g. "Electronic Pop", "Orchestral", "Lo-Fi").
moodstringEmotional tone (e.g. "Uplifting", "Melancholic", "Energetic").
duration"15s" | "30s" | "60s" | "120s"Track length. Generation time varies by model.
instrumentalbooleanSet true to suppress vocals. Default: false.
lyricsstringCustom lyrics for lyric-to-song workflows. Mutually exclusive with prompt.

textWriting (text)

FieldTypeDescription
tonestring"Professional" | "Casual" | "Persuasive" | "Academic" | custom.
length"short" | "medium" | "long"Approximate output length.
output_languagestringBCP-47 code. Default: en-US.
writing_taskstringTask hint: "blog-post" | "email" | "product-description" | "paraphrase" | "humanize".

infographicInfographic

FieldTypeDescription
infographic_type"data-overview" | "comparison" | "timeline" | "process-flow" | "mind-map"Visual layout type.
color_schemestringPalette hint (e.g. "corporate-blue", "vibrant"). Optional.
aspect_ratio"1:1" | "4:3" | "16:9" | "A4"Canvas ratio.

Credits & Wallet

Every generation spends EDT from your wallet. Insufficient balance returns 402.

GET/credits/wallet

Returns current balance and plan information.

Response
{
  "balance": 1240,
  "plan": "Ultimate Visionary Studio",
  "plan_edt_reset_at": "2026-09-01T00:00:00Z",
  "topup_balance": 500,
  "currency": "EDT"
}
GET/credits/packages

Lists available top-up packages for the authenticated account.

GET/credits/history?limit=20&cursor=

Paginated ledger of credit events (generation spends, top-ups, refunds).

Credit cost reference

Generation typeBase cost (EDT)Variable factors
text2–4Model, output length, writing task
voice3–8Character count, model, language
image5–20Model, quality, resolution
music8–18Duration, model, lyrics complexity
infographic10–25Model, data complexity, type
video15–60Duration, resolution, model, input type

The exact cost for each job is confirmed in the create response (credit_cost) and reserved immediately. If the job fails, credits are refunded automatically.

Error Reference

The API uses standard HTTP status codes. Every error body contains a machine-readable 'code' and a human-readable 'detail'.

Error response shape
{
  "code": "INSUFFICIENT_CREDITS",
  "detail": "Your wallet balance (3 EDT) is below the required cost (5 EDT).",
  "request_id": "req_f7c3a9b1"
}
HTTPcodeMeaning & action
200 / 201SUCCESSRequest succeeded. For creates, the job is queued.
400VALIDATION_ERRORMissing or invalid field. Fix the request body before retrying.
401UNAUTHORIZEDToken is missing, malformed, or revoked. Check the Authorization header.
402INSUFFICIENT_CREDITSBalance too low. Top up your wallet or wait for the plan reset.
403FORBIDDENAction not permitted for your key scope or plan tier.
404NOT_FOUNDGeneration ID does not exist or belongs to a different account.
409CONFLICTDuplicate request detected. Check if the job already exists.
422UNPROCESSABLEBody is valid JSON but semantically incorrect (e.g. unsupported model for type).
429RATE_LIMITEDToo many requests. Respect the Retry-After header before retrying.
500SERVER_ERRORInternal error. Retry with back-off. If persistent, contact support with request_id.
502 / 503UPSTREAM_ERRORUpstream AI provider unavailable. Retry with back-off.

Failed generation

If a job reaches status: "failed", the full record includes an error_message field explaining the failure. Credits reserved for a failed job are automatically refunded to your wallet — no manual action required.

Failed job
{
  "id": "gen_9b2c11f4",
  "status": "failed",
  "error_message": "The upstream model returned an empty result. The prompt may contain content that cannot be processed.",
  "credit_cost": 0,
  "outputs": []
}

Best Practices

Follow these to build a reliable, secure, and cost-efficient integration.

Security

  • Server-side only. Your API key must never reach the browser. Proxy all ImagineLab calls through your own backend.
  • Rotate keys periodically. Even if not compromised, rotate every 90 days as part of standard hygiene.
  • Scope your keys. Use one key per integration (one for dev, one for staging, one for prod). Revoke individually if one is compromised.
  • Validate webhook signatures. If you use webhook_url, verify the X-ImagineLab-Signature header before processing the payload.
  • Do not log prompts. User-submitted prompts may contain personal data. Follow your own data-protection obligations before persisting them.

Polling & retry

Use exponential back-off when polling and when handling transient errors (429, 502, 503). A fixed 2-second interval at scale will hit rate limits.

Python — exponential back-off poller
import time, math, requests

def poll_until_done(base_url, job_id, headers, timeout=300):
    """Poll status with exponential back-off. Raises on timeout or failure."""
    deadline = time.monotonic() + timeout
    delay = 2.0
    attempt = 0
    while time.monotonic() < deadline:
        r = requests.get(f"{base_url}/generations/{job_id}/status", headers=headers)
        if r.status_code == 429:
            wait = int(r.headers.get("Retry-After", delay))
            time.sleep(wait)
            continue
        r.raise_for_status()
        data = r.json()
        if data["status"] == "completed":
            return data
        if data["status"] == "failed":
            raise RuntimeError(data.get("error_message", "Generation failed"))
        delay = min(delay * 1.5, 10.0)  # cap at 10 s
        attempt += 1
        time.sleep(delay)
    raise TimeoutError(f"Job {job_id} did not complete within {timeout}s")

Credit management

  • Call GET /credits/wallet at app startup and cache the balance. Refresh it after every generation.
  • Gate generation calls client-side if the remaining balance is too low to avoid a round trip that results in a 402.
  • Trust the credit_cost in the create response as the definitive cost for that job — not the table in this documentation, which is approximate.

Output handling

  • Download outputs within 30 days. Signed CDN URLs expire. Store the files in your own storage as soon as possible.
  • Always check the mime_type field before rendering — some model/setting combinations produce different file formats.
  • For video outputs, serve from your own CDN rather than hot-linking the ImagineLab CDN URL. Hot-linking at scale may be rate-limited.

Usage Policy

Your API integration is subject to the same Terms of Service as the web platform — plus the constraints below.

Prohibited use — these will result in immediate key revocation

  • Generating or storing non-consensual intimate imagery (NCII) or content that sexually exploits minors (CSAM).
  • Generating deepfakes of identifiable private individuals without clear, documented consent.
  • Using the API to train, fine-tune, or distill any AI model without a written enterprise license.
  • Reselling raw API access to third parties (white-label integrations require a separate enterprise agreement).
  • Automated abuse of the generation pipeline — bots, credential stuffing, or any attempt to circumvent credit accounting.
  • Generating content that promotes violence, terrorism, or incites hatred against protected groups.
  • Scraping, reverse-engineering, or probing internal API behavior beyond what is documented here.

Content rights via the API

Outputs generated through the API carry the same rights as those generated through the web platform — governed by your current plan's Terms of Service. Commercial-use rights apply where your plan includes them. The API does not grant additional rights beyond what your subscription covers.

Data handling

Prompts, settings, and generation metadata are stored on ImagineLab infrastructure and governed by the Privacy Policy. If your users' data flows through your integration, you are responsible for ensuring they have consented under your own privacy framework. Do not transmit personally identifiable information (PII) inside prompt text unless your users have explicitly consented.

Reporting abuse

If you discover that your API key has been misused — whether by your team or a third party — revoke access immediately by contacting support@imaginelab.art. Include your account email and any relevant request IDs. We will investigate and can restore service once the issue is contained.

Ready to integrate?

API access is available on Ultimate Visionary Studio and Titan Studio plans. Contact our team to request a key and get started.

For urgent issues, email support@imaginelab.art with subject line API: for priority routing.