Chameleon

AI Generation APIs

APIs for AI text, image, and video generation

AI Generation APIs

APIs for creating and managing AI-generated content.

Generate AI Content

Create a new AI generation task (image or video).

Endpoint

POST /api/generator/generate

Authentication

Required: User must be logged in

Request

POST /api/generator/generate
Content-Type: application/json

{
  "ai_type": "video",
  "provider": "seedance",
  "model": "doubao-seedance-1-0-pro-250528",
  "prompt": "A dancing robot in futuristic city",
  "options": {}
}

Parameters:

FieldTypeRequiredDescription
ai_typestringYesimage or video
providerstringYesAI provider name
modelstringYesModel identifier
promptstringYesGeneration prompt
optionsobjectNoProvider-specific options

Supported Providers:

Image Generation:

  • openai - Models: dall-e-3, dall-e-2
  • replicate - Models: black-forest-labs/flux-schnell
  • kling - Models: kling-v1

Video Generation:

  • seedance - Models: doubao-seedance-1-0-pro-250528
  • kling - Models: kling-v1, kling-v1-6

Response

{
  "code": 0,
  "data": {
    "gen_id": "gen_1234567890",
    "status": "pending",
    "message": "Generation task created successfully"
  }
}

Fields:

  • gen_id: Unique generation ID (use to query status)
  • status: Always pending initially
  • message: Success message

Error Responses

// Insufficient credits
{
  "code": 1,
  "message": "insufficient credits: need 10, have 5"
}

// Invalid parameters
{
  "code": 1,
  "message": "invalid params: ai_type, provider, model, prompt required"
}

// Unsupported provider
{
  "code": 1,
  "message": "Unsupported video provider: invalid"
}

Credit Costs

AI TypeProviderModelCost
ImageOpenAIDALL-E 35 credits
ImageReplicateFlux Schnell3 credits
ImageKlingkling-v14 credits
VideoSeedancedoubao-seedance10 credits
VideoKlingkling-v110 credits

Example

const generateVideo = async () => {
  const response = await fetch("/api/generator/generate", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      ai_type: "video",
      provider: "seedance",
      model: "doubao-seedance-1-0-pro-250528",
      prompt: "A cat playing piano",
      options: {},
    }),
  });
  
  const data = await response.json();
  
  if (data.code === 0) {
    const genId = data.data.gen_id;
    // Poll for results
    pollGenerationStatus(genId);
  }
};

Query Generation Status

Check the status and results of a generation task.

Endpoint

POST /api/generator/query

Authentication

Required: User must be logged in

Request

POST /api/generator/query
Content-Type: application/json

{
  "gen_id": "gen_1234567890"
}

Response

Processing:

{
  "code": 0,
  "data": {
    "gen_id": "gen_1234567890",
    "status": "processing",
    "created_at": "2024-10-14T10:00:00.000Z"
  }
}

Completed:

{
  "code": 0,
  "data": {
    "gen_id": "gen_1234567890",
    "status": "completed",
    "result_urls": [
      "https://cdn.example.com/video/abc123.mp4"
    ],
    "created_at": "2024-10-14T10:00:00.000Z",
    "completed_at": "2024-10-14T10:02:30.000Z"
  }
}

Failed:

{
  "code": 0,
  "data": {
    "gen_id": "gen_1234567890",
    "status": "failed",
    "error_message": "API rate limit exceeded",
    "created_at": "2024-10-14T10:00:00.000Z",
    "completed_at": "2024-10-14T10:00:15.000Z"
  }
}

Statuses:

  • pending: Task created, waiting to start
  • processing: AI is generating content
  • completed: Success, results available in result_urls
  • failed: Generation failed, see error_message

Polling Example

const pollGenerationStatus = async (genId: string) => {
  const maxAttempts = 60; // 3 minutes max (60 × 3s)
  let attempts = 0;
  
  const poll = async () => {
    const response = await fetch("/api/generator/query", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ gen_id: genId }),
    });
    
    const data = await response.json();
    
    if (data.code === 0 && data.data) {
      const { status, result_urls, error_message } = data.data;
      
      if (status === "completed") {
        console.log("Video ready:", result_urls[0]);
        return;
      }
      
      if (status === "failed") {
        console.error("Generation failed:", error_message);
        return;
      }
      
      // Still processing, poll again
      attempts++;
      if (attempts < maxAttempts) {
        setTimeout(poll, 3000); // Poll every 3 seconds
      }
    }
  };
  
  poll();
};

Get Generation History

Retrieve user's AI generation history.

Endpoint

POST /api/generator/history

Authentication

Required: User must be logged in

Request

POST /api/generator/history
Content-Type: application/json

{
  "page": 1,
  "page_size": 20
}

Parameters:

  • page (optional): Page number, default 1
  • page_size (optional): Items per page, default 20, max 100

Response

{
  "code": 0,
  "data": {
    "generations": [
      {
        "gen_id": "gen_1234567890",
        "ai_type": "video",
        "provider": "seedance",
        "model": "doubao-seedance-1-0-pro-250528",
        "prompt": "A dancing robot",
        "result_urls": "[\"https://cdn.../video.mp4\"]",
        "status": "completed",
        "credits_cost": 10,
        "created_at": "2024-10-14T10:00:00.000Z",
        "completed_at": "2024-10-14T10:02:30.000Z"
      }
    ],
    "total": 45,
    "page": 1,
    "page_size": 20
  }
}

Example

const getHistory = async (page = 1) => {
  const response = await fetch("/api/generator/history", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ page, page_size: 20 }),
  });
  
  const data = await response.json();
  
  if (data.code === 0) {
    const { generations, total } = data.data;
    console.log(`Showing ${generations.length} of ${total} generations`);
    
    generations.forEach(gen => {
      console.log(`${gen.ai_type} - ${gen.status} - ${gen.credits_cost} credits`);
    });
  }
};

Demo Endpoints

Demo endpoints for testing AI features (no auth required in development).

Generate Text (Demo)

POST /api/demo/gen-text
Content-Type: application/json

{
  "provider": "openai",
  "model": "gpt-4",
  "prompt": "Write a haiku about coding"
}

Generate Image (Demo)

POST /api/demo/gen-image
Content-Type: application/json

{
  "provider": "openai",
  "model": "dall-e-3",
  "prompt": "A futuristic city at sunset"
}

Stream Text (Demo)

POST /api/demo/gen-stream-text
Content-Type: application/json

{
  "provider": "openai",
  "model": "gpt-4",
  "prompt": "Explain quantum computing"
}

Returns a streaming response.

Demo endpoints are for testing only. They may be rate-limited or disabled in production.

Generation Lifecycle

Create Task → Pending → Processing → Completed/Failed
                                    ↓
                              Deduct Credits (only on success)

Step-by-Step

  1. Create: Call /api/generator/generate

    • Validate parameters
    • Check credit balance
    • Create database record (status: pending)
    • Start background task
    • Return gen_id immediately
  2. Process: Background worker

    • Update status to "processing"
    • Call AI provider API
    • Poll for results (for async providers)
    • Extract result URLs
  3. Complete: On success

    • Update status to "completed"
    • Store result URLs
    • Deduct credits
  4. Fail: On error

    • Update status to "failed"
    • Store error message
    • NO credits deducted

Best Practices

1. Always Check Credits First

// Check before generating
const credits = await fetch("/api/get-user-credits", { method: "POST" });
const data = await credits.json();

if (data.data.left_credits < 10) {
  alert("Insufficient credits!");
  return;
}

// Proceed with generation

2. Poll Efficiently

// Don't poll too frequently
const POLL_INTERVAL = 3000; // 3 seconds

// Set a timeout
const MAX_WAIT = 5 * 60 * 1000; // 5 minutes

3. Handle Errors Gracefully

if (data.data.status === "failed") {
  const errorMsg = data.data.error_message;
  
  if (errorMsg.includes("rate limit")) {
    // Show user-friendly message
    alert("AI service is busy. Please try again in a moment.");
  } else {
    alert(`Generation failed: ${errorMsg}`);
  }
}

4. Cache Results

// Store completed results locally
localStorage.setItem(`gen_${genId}`, JSON.stringify(result_urls));

// Avoid re-querying for completed generations

Webhooks (Future)

Currently not implemented, but you could add webhooks to notify when generation completes:

// Potential future feature
POST /api/generator/generate
{
  "ai_type": "video",
  "prompt": "...",
  "webhook_url": "https://your-app.com/webhook"
}

// When complete, POST to webhook_url

Next Steps