Kunya API

Build powerful AI-powered applications with the Kunya API. Access advanced writing generation, image creation, audio synthesis, video generation, game development tools, and chat capabilities with a single, unified API.

๐Ÿ’ฌ

Chat

Multi-model chat completions API

โœ๏ธ

Writing

Generate content with custom voice profiles

๐ŸŽจ

Images

Create stunning images with AI models

๐ŸŽฌ

Video Gen

Generate AI videos with Kling, Sora, Veo, Seedance 2.0

โœ‚๏ธ

Video Edit

Edit, trim, transitions, color grade, AI edits

๐ŸŽ™๏ธ

Audio

TTS, transcription, music & podcasts

๐Ÿ—ฃ๏ธ

Voice Cloning

Clone voices for personalized TTS

๐Ÿค–

AI Agents

Create and manage autonomous agents

๐Ÿ“š

Content

Save, summarize & organize content

๐Ÿ”

Search

Web search via Brave & DuckDuckGo

๐Ÿ“

Files

Process and convert file formats

๐Ÿ‘ฅ

Team

Team management and collaboration

Getting Started

Quickstart by Use Case

Kunya is one API for frontier chat, multimodal video, generative media, headless CMS, voice agents, workspace backends, and autonomous agents โ€” switch models per request without switching providers. Pick a playbook below.

Claude Code & dev tools on every model

Point Claude Code, Cursor, or the Anthropic SDK at Kunya โ€” use Claude, GPT-5.5, Gemini 3.5 Flash, or DeepSeek with one key.

/v1/messages/v1/models
1

Configure the gateway

export ANTHROPIC_BASE_URL=https://kunya.ai/api
export ANTHROPIC_API_KEY=kunya_YOUR_API_KEY
export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1
claude update && claude
2

Or call Messages API directly with any model

Try gpt-5.5, gemini-3.5-flash, or claude-sonnet-4.6.

curl -X POST https://kunya.ai/api/v1/messages \
  -H "x-api-key: kunya_YOUR_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"model": "gemini-3.5-flash", "max_tokens": 2048, "messages": [{"role": "user", "content": "Refactor this API handler"}]}'

Video intelligence pipeline

Turn product demos, ads, or YouTube URLs into structured briefs, chapters, and QA reports โ€” no frame extraction setup.

/v1/videos/analyze/v1/chat/completions
1

Analyze a hosted or YouTube video

curl -X POST https://kunya.ai/api/v1/videos/analyze \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://www.youtube.com/watch?v=VIDEO_ID",
    "prompt": "List scenes, on-screen text, and a 3-bullet creative brief.",
    "model": "gemini-3.5-flash",
    "response_format": "markdown"
  }'
2

Chain into chat for follow-up edits

curl -X POST https://kunya.ai/api/v1/chat/completions \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4.6",
    "messages": [{"role": "user", "content": "Turn this analysis into 5 ad hook scripts: ..."}]
  }'

Creative studio in one API

Generate, edit, batch, score video, and soundtrack assets โ€” GPT Image 2, Nano Banana Pro/2, Seedance, Suno.

/v1/images/generations/v1/videos/generations/v1/audio/music
1

Generate hero image

curl -X POST https://kunya.ai/api/v1/images/generations \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Product hero, soft studio light", "model": "gpt-image-2", "size": "1024x1024"}'
2

Edit with reference (Nano Banana Pro)

curl -X POST https://kunya.ai/api/v1/images/generations \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Remove background, add gradient", "model": "gemini-3-pro-image", "reference_image": "https://cdn.example.com/hero.jpg"}'
3

Animate + soundtrack

# Video
curl -X POST https://kunya.ai/api/v1/videos/generations \
  -d '{"prompt": "Slow orbit around product", "model": "seedance-2.0-t2v", "duration": 5}'

# Music
curl -X POST https://kunya.ai/api/v1/audio/music \
  -d '{"prompt": "Cinematic pulse, 45s", "model": "suno-v5", "duration": 45}'

Live research chat (built-in tools)

Ship a research copilot that browses the web and generates images when needed โ€” no tool wiring on your side.

/v1/chat/completions
1

One call with kunya_tools enabled

Uses gemini-3.5-flash by default; set kunya_tools: false to disable.

curl -X POST https://kunya.ai/api/v1/chat/completions \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-3.5-flash",
    "kunya_tools": true,
    "messages": [{"role": "user", "content": "What launched in AI this week? Cite sources."}],
    "stream": true
  }'

Knowledge-base chatbot for your product

Embed a widget or server-side bot that answers from your docs, URLs, and Notion โ€” not generic LLM guesses.

/v1/chatbot-widgets/v1/knowledge-bases/chatbot/{id}
1

Create a widget tied to a knowledge base

curl -X POST https://kunya.ai/api/v1/chatbot-widgets \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Docs Assistant",
    "knowledge_base_id": "KB_ID",
    "greeting": "Ask anything about our API โ€” I use your indexed docs."
  }'
2

Chat from your app (embed token or public widget route)

Visitors chat via your hosted widget; server apps use the widget message endpoint with session id.

curl -X POST https://kunya.ai/api/chatbot/WIDGET_ID \
  -H "Content-Type: application/json" \
  -d '{"message": "How do I authenticate?", "session_id": "user-123"}'

Headless content & SEO engine

Programmatic blog: brand voice, long-form generation, bulk campaigns, publish โ€” for agencies and product-led SEO.

/v1/blog/ai/generate-article/v1/blog/ai/bulk-generate/v1/blog/posts
1

Set brand context once

curl -X PUT https://kunya.ai/api/v1/blog/brand-context \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"brand_context": "# Acme\nTone: direct, technical. Audience: developers."}'
2

Stream a full SEO article

curl -X POST https://kunya.ai/api/v1/blog/ai/generate-article \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "API design patterns for AI apps", "model": "claude-sonnet-4.6", "target_length": "long", "include_faq": true}'
3

Bulk-generate a content calendar (async)

curl -X POST https://kunya.ai/api/v1/blog/ai/bulk-generate \
  -d '{"objective": "8 posts on AI infrastructure", "model": "claude-sonnet-4.6", "auto_publish": false}'

Voice agent that can take actions

Phone or web voice agents with tool calling โ€” book meetings, look up CRM data, or hand off to support.

/v1/voice/agents/v1/voice/calls
1

Create a voice agent with instructions + model

curl -X POST https://kunya.ai/api/v1/voice/agents \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Receptionist",
    "type": "support",
    "system_prompt": "Schedule demos and answer pricing FAQs.",
    "model": "gemini-2.5-flash",
    "voice": { "provider": "elevenlabs", "voice_id": "21m00Tcm4TlvDq8ikWAM" }
  }'
2

Start an outbound or inbound call

Connect Twilio/LiveKit numbers in the dashboard; API triggers the call session.

curl -X POST https://kunya.ai/api/v1/voice/calls \
  -d '{"agent_id": "AGENT_ID", "to": "+15551234567"}'

Workspace backend for your SaaS

Give customers docs, databases, whiteboards, and spreadsheets via API โ€” plus AI edit on page content.

/v1/workspaces/pages/v1/workspaces/databases/v1/workspaces/spreadsheets
1

Spin up a customer database + rows

const dbPage = await fetch('https://kunya.ai/api/v1/workspaces/pages', {
  method: 'POST',
  headers: { Authorization: 'Bearer kunya_xxx', 'Content-Type': 'application/json' },
  body: JSON.stringify({ title: 'Customer CRM', type: 'database' }),
}).then((r) => r.json());

await fetch(`https://kunya.ai/api/v1/workspaces/databases/${dbPage.data.database_id}/rows/bulk`, {
  method: 'POST',
  body: JSON.stringify({ rows: [{ cells: { /* column_id */: 'Acme Corp' } }] }),
});
2

AI-update a document page

curl -X POST https://kunya.ai/api/v1/workspaces/pages/PAGE_ID/ai \
  -d '{"operation": "ai_rewrite", "instruction": "Make this executive-ready", "model": "claude-sonnet-4.6"}'

Autonomous agent with scheduled tasks

Deploy agents that run pipelines, use tools, and report back โ€” content ops, monitoring, or game-studio automation.

/v1/agents/v1/agents/{id}/tasks/v1/agents/{id}/chat
1

Create an agent with tools enabled

curl -X POST https://kunya.ai/api/v1/agents \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Content Ops", "instructions": "Draft and queue social posts from our RSS.", "config": {"model": "claude-sonnet-4.6", "temperature": 0.4}}'
2

Kick off a task run

curl -X POST https://kunya.ai/api/v1/agents/AGENT_ID/tasks \
  -d '{"prompt": "Summarize today tech headlines and draft 3 LinkedIn posts."}'

Authentication

All API requests require authentication using an API key. Include your key in theAuthorization header:

Authentication Header
Authorization: Bearer kunya_YOUR_API_KEY

Alternatively, use the X-API-Key header:

X-API-Key: kunya_YOUR_API_KEY

Security: Keep your API key secure and never expose it in client-side code. Use environment variables in production.

Rate Limits

Rate limits vary by plan. When limits are exceeded, the API returns a 429 status code.

PlanRequests/minRequests/hourRequests/day
Free10100500
Starter601,00010,000
Professional2005,00050,000
Enterprise1,000+50,000+500,000+
Rate Limit Response Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1704067200000
Retry-After: 35

Error Reference

All errors follow a consistent envelope format. Use the machine-readable catalog at GET /api/v1/errors to build error-handling logic programmatically.

Error Response Format
{
  "error": {
    "message": "Insufficient credits. Please add more credits or enable overage billing.",
    "type": "billing_error",
    "code": "insufficient_credits"
  }
}
HTTP StatusError TypeRetryableDescription
400invalid_request_errorNoMalformed request, missing fields, or invalid values
401authentication_errorNoMissing, invalid, or revoked API key
402billing_errorNoInsufficient credits or spend limit exceeded
404not_found_errorNoResource does not exist or belongs to another workspace
429rate_limit_errorYesRate limit exceeded โ€” respect Retry-After header
500server_errorYesInternal error โ€” exponential backoff, max 3 retries

Common Error Codes

CodeStatusMeaning
invalid_api_key401API key missing, malformed, or revoked
insufficient_credits402Credit balance zero, overage disabled
account_spend_limit_exceeded402Account-level spend cap reached
workspace_spend_limit_exceeded402Workspace-level spend cap reached
rate_limit_exceeded429Too many requests for your plan tier
missing_field400Required field missing from request body
invalid_model400Model ID not found or not available on your plan
content_too_long400Input exceeds model context window
generation_failed500AI provider failed after retries
provider_error502Upstream AI provider error โ€” safe to retry

For the full error catalog with all codes and retry guidance, fetch GET /api/v1/errors โ€” it returns a machine-readable JSON document designed for programmatic consumption.

AI Operations

Chat Completions

POST/api/v1/chat/completions

Generate conversational responses using 140+ AI models from OpenAI, Anthropic, Google, DeepSeek, xAI, MiniMax, Meta, Mistral, Qwen, and more.

Request Body

{
  "messages": [
    {"role": "system", "content": "You are a helpful assistant."},
    {"role": "user", "content": "What is machine learning?"}
  ],
  "model": "claude-sonnet-4.6",
  "stream": false,
  "max_tokens": 1000,
  "temperature": 0.7
}

Response

{
  "id": "chat_abc123",
  "object": "chat.completion",
  "model": "claude-sonnet-4.6",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Machine learning is a subset of AI..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 45,
    "completion_tokens": 150,
    "total_tokens": 195
  },
  "cost": 0.002925
}

cURL Example

curl -X POST https://kunya.ai/api/v1/chat/completions \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messages": [{"role": "user", "content": "Hello!"}],
    "model": "claude-sonnet-4.6",
    "stream": false
  }'
GET/api/v1/models

List all available AI models with pricing information.

Response

{
  "models": [
    {
      "id": "gpt-5.5",
      "name": "GPT-5.5",
      "provider": "openai",
      "type": "chat",
      "pricing": {
        "input": 0.005,
        "output": 0.015
      },
      "supports_streaming": true,
      "supports_vision": true
    }
  ]
}

Anthropic Messages API

Anthropic-compatible endpoint for Claude Code, the Anthropic SDK, and any tool that expects the Messages API format. All 140+ Kunya models work through this endpoint โ€” not just Claude. Use the same kunya_ API keys.

Claude Code setup: Set ANTHROPIC_BASE_URL=https://kunya.ai/api and ANTHROPIC_API_KEY=kunya_YOUR_API_KEY

POST/api/v1/messages

Create a message. Accepts any Kunya model ID (claude-sonnet-4.6, gemini-2.5-flash, gpt-5.5, gemini-3.5-flash, deepseek-chat, claude-sonnet-4.6, etc.). Returns Anthropic-format responses with streaming support.

Request Body

{
  "model": "claude-sonnet-4.6",
  "max_tokens": 1024,
  "messages": [
    {"role": "user", "content": "What is machine learning?"}
  ],
  "stream": false
}

Response

{
  "id": "msg_abc123",
  "type": "message",
  "role": "assistant",
  "content": [{"type": "text", "text": "Machine learning is..."}],
  "model": "claude-sonnet-4.6",
  "stop_reason": "end_turn",
  "usage": {"input_tokens": 12, "output_tokens": 150}
}

Python (Anthropic SDK)

import anthropic

client = anthropic.Anthropic(
    api_key="kunya_YOUR_API_KEY",
    base_url="https://kunya.ai/api"
)

message = client.messages.create(
    model="gemini-2.5-flash",  # Any Kunya model
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}]
)
print(message.content[0].text)

cURL Example

curl -X POST https://kunya.ai/api/v1/messages \
  -H "x-api-key: kunya_YOUR_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "claude-sonnet-4.6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'
POST/api/v1/messages/count_tokens

Estimate input token count for a request. Used by Claude Code for context window management.

cURL Example

curl -X POST https://kunya.ai/api/v1/messages/count_tokens \
  -H "x-api-key: kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "claude-sonnet-4.6", "messages": [{"role": "user", "content": "Hello"}]}'

Conversations

Manage persistent conversations with message history.

GET/api/v1/conversations

List all conversations for the authenticated user.

Query Parameters

GET /api/v1/conversations?limit=50&offset=0

Response

{
  "data": [
    {
      "id": "conv_abc123",
      "title": "Machine Learning Discussion",
      "model": "claude-sonnet-4.6",
      "created_at": "2025-01-15T10:30:00Z",
      "updated_at": "2025-01-15T11:45:00Z"
    }
  ]
}
POST/api/v1/conversations

Create a new conversation.

// Request
{
  "title": "My New Conversation",
  "model": "claude-sonnet-4.6"
}

// Response (201)
{
  "id": "conv_xyz789",
  "title": "My New Conversation",
  "model": "claude-sonnet-4.6",
  "created_at": "2025-01-15T12:00:00Z"
}
GET/api/v1/conversations/{id}/messages

Retrieve all messages in a conversation.

{
  "data": [
    {
      "id": "msg_001",
      "role": "user",
      "content": "What is machine learning?",
      "model": null,
      "tokens": 6,
      "created_at": "2025-01-15T10:30:00Z"
    },
    {
      "id": "msg_002",
      "role": "assistant",
      "content": "Machine learning is a subset of AI...",
      "model": "claude-sonnet-4.6",
      "tokens": 150,
      "created_at": "2025-01-15T10:30:05Z"
    }
  ],
  "conversation_id": "conv_abc123"
}

AI Memories

Store and retrieve persistent AI memories for context-aware conversations.

GET/api/v1/ai/memories

List all stored AI memories.

{
  "data": [
    {
      "id": "mem_abc123",
      "content": "User prefers concise responses",
      "category": "preferences",
      "source": "conversation",
      "created_at": "2025-01-15T10:00:00Z"
    }
  ]
}
POST/api/v1/ai/memories

Create a new AI memory.

// Request
{
  "content": "User works in fintech and prefers Python",
  "category": "context"
}

// Response (201)
{
  "id": "mem_xyz789",
  "content": "User works in fintech and prefers Python",
  "category": "context",
  "created_at": "2025-01-15T12:00:00Z"
}

Agents

AI Agents

Create and manage autonomous AI agents for specialized tasks.

GET/api/v1/agents

List all agents in your workspace.

{
  "data": [
    {
      "id": "agent_abc123",
      "name": "Research Assistant",
      "description": "Autonomous research agent",
      "type": "custom",
      "status": "active",
      "is_active": true,
      "config": { ... },
      "stats": { ... },
      "created_at": "2025-01-10T09:00:00Z"
    }
  ]
}
POST/api/v1/agents

Create a new AI agent.

// Request
{
  "name": "Customer Support Bot",
  "description": "Handles tier-1 customer inquiries",
  "type": "support",
  "config": {
    "model": "claude-sonnet-4.6",
    "systemPrompt": "You are a helpful customer support agent...",
    "temperature": 0.5,
    "maxTokens": 2048,
    "memoryEnabled": true
  }
}

// Response (201)
{
  "data": {
    "id": "agent_xyz789",
    "name": "Customer Support Bot",
    "description": "Handles tier-1 customer inquiries",
    "type": "support",
    "status": "active",
    "created_at": "2025-01-15T12:00:00Z"
  },
  "message": "Agent created"
}
PATCH/api/v1/agents/{id}

Update an agent's configuration.

// Request
{
  "name": "Updated Agent Name",
  "config": {
    "temperature": 0.3,
    "enabledTools": ["web_search", "calculator"]
  }
}

// Response
{
  "data": {
    "id": "agent_xyz789",
    "name": "Updated Agent Name",
    "status": "active",
    "updated_at": "2025-01-15T14:00:00Z"
  },
  "message": "Agent updated"
}

Agent Tasks

Create autonomous tasks for agents. Tasks run in the background and can execute multi-step workflows using the agent's full tool set.

POST/api/v1/agents/{id}/tasks

Create and run a task for an agent. The agent will execute autonomously using its configured tools.

Request Body

{
  "objective": "Write an SEO blog post about sustainable fashion trends",
  "instructions": "Use voice profile 'Brand Voice', target keyword 'sustainable fashion 2026', save to blog drafts",
  "type": "autonomous"
}

Response (201)

{
  "data": {
    "id": "task_abc123",
    "agent_id": "agent_xyz789",
    "status": "running",
    "objective": "Write an SEO blog post about sustainable fashion trends",
    "created_at": "2026-02-20T12:00:00Z"
  }
}
GET/api/v1/agents/{id}/tasks/{taskId}

Get task status, progress, steps executed, and results.

{
  "data": {
    "id": "task_abc123",
    "status": "completed",
    "objective": "Write an SEO blog post about sustainable fashion trends",
    "progress_percentage": 100,
    "deliverable": {
      "type": "blog_post",
      "content": "# Sustainable Fashion Trends in 2026\n\nThe fashion industry...",
      "wordCount": 2100,
      "format": "markdown"
    },
    "steps": [
      { "type": "tool_call", "toolName": "writer_load_voice_profile", "status": "completed" },
      { "type": "tool_call", "toolName": "web_search", "status": "completed" },
      { "type": "tool_call", "toolName": "writer_generate_article", "status": "completed" },
      { "type": "tool_call", "toolName": "writer_save_to_blog_drafts", "status": "completed" }
    ],
    "tokens": { "input": 8500, "output": 4200, "total": 12700 },
    "cost": 0.038,
    "timing": {
      "started_at": "2026-02-20T12:00:01Z",
      "completed_at": "2026-02-20T12:01:45Z",
      "duration_seconds": 104
    }
  }
}
POST/api/v1/agents/{id}/chat

Interactive chat with an agent. The agent has access to all its tools and can execute multi-step workflows conversationally.

Request Body

{
  "message": "Write a LinkedIn post about our new Portuguese VoIP numbers",
  "conversation_id": "conv_abc123"
}

Returns a streaming response. The agent may make tool calls (web search, content generation, etc.) during the conversation.

POST/api/v1/agents/{id}/tasks/{taskId}/approve

Approve a task step that requires approval (e.g., publishing a blog post).

// Request
{
  "approved": true,
  "feedback": "Looks great, publish it"
}

// Response
{
  "data": { "status": "running", "message": "Task resumed" }
}
POST/api/v1/agents/{id}/tasks/{taskId}/cancel

Cancel a running task.

// Response
{
  "data": { "status": "cancelled", "message": "Task cancelled" }
}

Content Writer Agent

The Content Writer is a specialized agent that writes in your voice across every medium โ€” from tweets to long-form SEO articles. It learns your style from voice profiles, browses your content library for consistency, writes natively in any language, and publishes to your blog or exports for any platform.

Quick Start: Create a Content Writer

curl -X POST https://kunya.ai/api/v1/agents \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Brand Content Writer",
    "template_id": "template-writing",
    "type": "writing",
    "config": {
      "model": "claude-sonnet-4.6",
      "temperature": 0.7,
      "tone": "professional"
    }
  }'

Content Writer Tools

These are NOT REST endpoints.

The tools below are used internally by the agent during task execution and chat. You do not call them directly. Instead, create a task via POST /api/v1/agents/{id}/tasks or chat via POST /api/v1/agents/{id}/chat and the agent will invoke these tools autonomously based on your instructions.

ToolPurpose
writer_list_voice_profilesDiscover available voice profiles
writer_load_voice_profileLoad full voice DNA for style matching
writer_browse_content_librarySearch blog posts + documents for reference
writer_generate_paragraphsQuick 1-3 paragraphs for any medium (tweet, email, ad, blog, etc.)
writer_generate_articleFull long-form article with voice matching, research, SEO
writer_edit_content12 edit types: refine, rewrite, expand, condense, tone shift, SEO optimize, etc.
writer_translate_contentNative-quality translation preserving voice and cultural context
writer_save_to_librarySave to content library (writing documents)
writer_save_to_blog_draftsPush directly to blog CMS as a draft
writer_delete_contentDelete from library or blog
writer_export_contentExport for WordPress, Ghost, Markdown frontmatter, HTML, or universal CMS JSON
POST/api/v1/agents/{id}/tasks

Generate quick paragraphs โ€” tweets, LinkedIn posts, email snippets, blog intros, ad copy.

Example: Social Media Copy

{
  "objective": "Write 2 LinkedIn posts about remote work productivity",
  "instructions": "Use my default voice profile. Hook-driven format, include CTA. Professional but conversational tone."
}
POST/api/v1/agents/{id}/tasks

Generate a full article with research, voice matching, SEO optimization, and publishing.

Example: Full Blog Post Pipeline

{
  "objective": "Research the top 10 VoIP providers for Portuguese numbers and write an SEO-optimized blog post",
  "instructions": "Include our service (Kunya) as one of the providers. Target keyword: 'portugal voip number'. Use voice profile 'Brand Voice'. Save to blog drafts. Target 2000+ words. Generate a featured image."
}

The agent will autonomously: load your voice profile, web search for competitors, browse your content library for existing coverage, generate the article, create a featured image, and save it as a blog draft.

POST/api/v1/agents/{id}/tasks

Translate or localize content while preserving voice and cultural context.

Example: Multi-Language Content

{
  "objective": "Translate our latest blog post about VoIP providers into Portuguese and Spanish",
  "instructions": "Adapt cultural references for each market. Preserve SEO structure. Save translations to content library."
}

Export Formats

When using the Content Writer via tasks, you can request content export in formats compatible with popular platforms:

universal_cms

Normalized JSON schema for any CMS

wordpress

WordPress import with Yoast SEO meta

ghost

Ghost JSON import with mobiledoc

markdown_frontmatter

Hugo, Jekyll, Astro compatible

html_standalone

Self-contained HTML document

json_structured

Raw JSON with content + metadata

Using via Chat (Conversational Editing)

Use the agent chat endpoint for iterative, conversational content creation. The agent stays in editing mode after producing content.

Conversational flow example
# 1. Start a conversation
POST /api/v1/agents/{id}/chat
{ "message": "Write a blog intro about sustainable AI practices" }
# โ†’ Agent generates intro using voice profile

# 2. Iterate
POST /api/v1/agents/{id}/chat
{ "message": "Make it more casual and add a surprising statistic", "conversation_id": "conv_..." }
# โ†’ Agent rewrites with edits

# 3. Publish
POST /api/v1/agents/{id}/chat
{ "message": "Save this to blog drafts with SEO metadata", "conversation_id": "conv_..." }
# โ†’ Agent saves to blog CMS

Using with Other Agents

The Content Writer is designed to be called by other agents (Marketing Maestro, Social Media Manager, Supervisor) via the delegation system. When giving a task to a supervisor or marketing agent, include content writing subtasks and they'll be automatically routed to available Content Writer agents.

Writing Generation

Generate content that matches your unique writing style using trained voice profiles.

POST/api/v1/writing/generate

Generate content using a voice profile for consistent brand voice.

Request Body

{
  "prompt": "Write a blog intro about sustainable fashion",
  "profile_id": "profile_xyz789",
  "context": "blog",
  "length": "medium",
  "model": "claude-sonnet-4.6"
}

Response

{
  "content": "In a world where fast fashion dominates...",
  "profile_used": "profile_xyz789",
  "profile_name": "Brand Voice",
  "context": "blog",
  "model": "claude-sonnet-4.6",
  "tokens": 450,
  "cost": 0.00675
}
POST/api/v1/writing/rewrite

Rewrite text with optional tone and style adjustments.

// Request
{
  "text": "Our product is really good and you should buy it",
  "tone": "professional",
  "style": "persuasive",
  "instructions": "Make it more compelling for enterprise buyers"
}

// Response
{
  "original": "Our product is really good and you should buy it",
  "rewritten": "Our enterprise solution delivers measurable ROI...",
  "tone": "professional",
  "style": "persuasive",
  "cost": "0.00045"
}
GET/api/v1/writing/profiles

List all your voice profiles.

{
  "profiles": [
    {
      "id": "profile_xyz789",
      "name": "Brand Voice",
      "description": "Professional yet friendly tone",
      "profile_type": "author",
      "sample_count": 15,
      "word_count": 25000,
      "is_ready": true
    }
  ]
}
POST/api/v1/writing/profiles

Create a new voice profile.

{
  "name": "Technical Writer",
  "description": "Clear, precise technical documentation",
  "profile_type": "brand",
  "settings": {
    "formality": 0.8,
    "verbosity": 0.6,
    "technicality": 0.9,
    "warmth": 0.3,
    "confidence": 0.8
  }
}

Writing Documents

Create and manage writing documents organized in folders.

GET/api/v1/writing/documents

List writing documents with optional folder filtering.

// GET /api/v1/writing/documents?limit=50&offset=0&folder_id=folder_abc

{
  "data": [
    {
      "id": "doc_abc123",
      "title": "Q1 Marketing Plan",
      "content": "# Marketing Strategy...",
      "folder_id": "folder_abc",
      "word_count": 2500,
      "created_at": "2025-01-10T09:00:00Z",
      "updated_at": "2025-01-15T14:30:00Z"
    }
  ]
}
POST/api/v1/writing/documents

Create a new writing document.

// Request
{
  "title": "Product Launch Brief",
  "content": "## Overview
Our new product...",
  "folder_id": "folder_abc"
}

// Response (201)
{
  "id": "doc_xyz789",
  "title": "Product Launch Brief",
  "created_at": "2025-01-15T12:00:00Z"
}
PUT/api/v1/writing/documents/{id}

Update a document's content or metadata.

// Request
{
  "title": "Updated Title",
  "content": "## Updated Content...",
  "folder_id": "folder_new"
}

// Response
{ "success": true }

Writing Sessions

AI-powered writing sessions with voice profiles, outlines, auto-complete, and step-by-step generation.

POST/api/v1/writing/sessions

Create a new AI writing session.

// Request
{
  "title": "Blog Post: AI in Healthcare",
  "description": "Long-form article about AI applications in healthcare",
  "profile_id": "profile_xyz789",
  "settings": {
    "model": "claude-sonnet-4.6",
    "target_word_count": 3000,
    "content_type": "blog_post",
    "temperature": 0.7
  }
}

// Response (201)
{
  "id": "session_abc123",
  "title": "Blog Post: AI in Healthcare",
  "status": "active",
  "word_count": 0,
  "created_at": "2025-01-15T12:00:00Z"
}
GET/api/v1/writing/sessions/{id}

Get full session details including content, outline, and generation history.

{
  "id": "session_abc123",
  "title": "Blog Post: AI in Healthcare",
  "content": "## Introduction
AI is transforming healthcare...",
  "outline": [...],
  "settings": { "model": "claude-sonnet-4.6", "target_word_count": 3000 },
  "generation_history": [...],
  "voice_profile_id": "profile_xyz789",
  "word_count": 1250,
  "paragraph_count": 8,
  "total_tokens_used": 5400,
  "total_cost": "0.081",
  "status": "active",
  "created_at": "2025-01-15T12:00:00Z"
}
GET/api/v1/writing/sessions

List writing sessions with optional status filtering.

GET /api/v1/writing/sessions?status=active&limit=20&offset=0

Image Generation

POST/api/v1/images/generations

Generate images using AI models including GPT Image 2, DALL-E 3, Midjourney V7, and more.

Request Body

{
  "prompt": "A serene mountain landscape at sunset, digital art style",
  "model": "gpt-image-2",
  "size": "1024x1024",
  "quality": "hd",
  "style": "vivid"
}

Midjourney V7 Request

{
  "prompt": "A serene mountain landscape at sunset --ar 16:9 --style raw",
  "model": "midjourney-v7",
  "midjourney_speed": "fast"
}

Supported Models

Model IDNameProviderNotes
gpt-image-2GPT Image 2OpenAILatest, fastest GPT image model with flexible sizes
gpt-image-1.5GPT Image 1.5OpenAIImage generation with native editing
gpt-image-1GPT Image 1OpenAISupports reference image editing
dall-e-3DALLยทE 3OpenAIStandard image generation
gemini-3-pro-imageNano Banana ProGoogleGemini-powered generation
midjourney-v7Midjourney V7MidjourneyAsync, returns up to 4 images, V7 native prompt params

Request Parameters

ParameterTypeRequiredDescription
promptstringYesText description of the image to generate
modelstringYesModel ID from the supported models table
sizestringNoImage dimensions (e.g. 1024x1024). Not applicable to Midjourney
qualitystringNostandard or hd (model-dependent)
stylestringNovivid or natural (DALL-E 3 only)
midjourney_speedstringNoMidjourney only. draft, fast, or turbo. Default: fast
reference_imagesarrayNoReference images for editing (GPT Image models)

Response

{
  "id": "img_abc123",
  "url": "data:image/png;base64,...",
  "model": "gpt-image-2",
  "size": "1024x1024",
  "quality": "hd",
  "revised_prompt": "A serene mountain landscape...",
  "cost": 0.080
}

Midjourney V7 Response (multiple images)

{
  "id": "img_mj_456",
  "data": [
    { "url": "https://cdn.midjourney.com/...", "index": 0 },
    { "url": "https://cdn.midjourney.com/...", "index": 1 },
    { "url": "https://cdn.midjourney.com/...", "index": 2 },
    { "url": "https://cdn.midjourney.com/...", "index": 3 }
  ],
  "model": "midjourney-v7",
  "prompt": "A serene mountain landscape at sunset --ar 16:9 --style raw",
  "cost": 0.100
}

Midjourney Note: Midjourney V7 is async and can take up to 20 minutes to complete. The response returns up to 4 images in the data[] array. Midjourney V7 supports native prompt parameters (--ar, --style, --chaos, --weird, etc.) directly in the prompt string.

With Reference Images (Image Editing)

{
  "prompt": "Make the sky more dramatic with storm clouds",
  "model": "gpt-image-2",
  "reference_images": [
    {
      "url": "data:image/png;base64,...",
      "purpose": "edit"
    }
  ]
}
POST/api/v1/images/batch

Generate multiple images in a single batch request (max 10 prompts).

// Request
{
  "prompts": [
    "A futuristic cityscape at dawn",
    "A cozy cabin in the woods",
    "An underwater coral reef"
  ],
  "model": "gpt-image-2",
  "size": "1024x1024",
  "quality": "standard"
}

// Response
{
  "data": [
    { "prompt": "A futuristic cityscape...", "url": "data:image/png;base64,...", "cost": 0.04 },
    { "prompt": "A cozy cabin...", "url": "data:image/png;base64,...", "cost": 0.04 },
    { "prompt": "An underwater coral reef", "url": "data:image/png;base64,...", "cost": 0.04 }
  ],
  "total": 3,
  "successful": 3,
  "total_cost": 0.12
}
POST/api/v1/images/agent-generate

Batch image generation with an AI agent. Parse complex tasks into prompt+model pairs, then generate all images with SSE progress streaming. Up to 100 images per batch. Optional reference_images (max 8) guide parsing and every generation.

Parse Task

// Request
{
  "action": "parse",
  "task": "Generate with Nano Banana Pro:\n- A sunset over a mountain lake\n\nGenerate with DALLยทE 3:\n- A vintage travel poster for Japan",
  "parser_model": "gemini-3.5-flash",
  "reference_images": [
    { "base64": "data:image/png;base64,...", "filename": "style-ref.png" }
  ]
}

// Response
{
  "data": {
    "items": [
      { "id": "item_1", "model": "gemini-3-pro-image", "model_name": "Nano Banana Pro", "prompt": "A sunset over a mountain lake", "estimated_cost": 0.02 },
      { "id": "item_2", "model": "gpt-image-2", "model_name": "DALLยทE 3", "prompt": "A vintage travel poster for Japan", "estimated_cost": 0.04 }
    ],
    "total_estimated_cost": 0.06
  }
}

Reference Images (optional)

Up to 8 images. Send the same reference_images array on parse and execute. Each item uses these references when calling /api/v1/images/generate (identity-preserving edit on supported models).

Execute (SSE Stream)

// Request
{
  "action": "execute",
  "items": [{ "id": "item_1", "model": "gemini-3-pro-image", "prompt": "...", "size": "1024x1024", "quality": "auto", "estimated_cost": 0.02 }],
  "reference_images": [{ "base64": "data:image/png;base64,...", "filename": "style-ref.png" }]
}

// SSE Events
event: job_created โ†’ { "job_id": "uuid", "total_items": 2 }
event: item_started โ†’ { "item_id": "item_1" }
event: item_completed โ†’ { "item_id": "item_1", "image_url": "https://...", "cost": 0.02 }
event: item_failed โ†’ { "item_id": "item_2", "error": "Provider timeout" }
event: done โ†’ { "total": 2, "succeeded": 1, "failed": 1, "total_cost": 0.02 }

Cancel

{ "action": "cancel", "job_id": "uuid" }
POST/api/v1/images/enhance-prompt

Enhance a simple prompt into a detailed, optimized image generation prompt.

// Request
{
  "prompt": "a cat on a roof",
  "style": "photorealistic"
}

// Response
{
  "original_prompt": "a cat on a roof",
  "enhanced_prompt": "A sleek orange tabby cat perched on terracotta roof tiles at golden hour, soft bokeh background of a Mediterranean village, warm sunlight casting long shadows, photorealistic, 8K detail",
  "cost": "0.00015"
}
GET/api/v1/images/projects

List image projects/folders.

{
  "data": [
    {
      "id": "proj_abc",
      "name": "Marketing Assets",
      "description": "Social media and ad images",
      "image_count": 45,
      "created_at": "2025-01-10T09:00:00Z"
    }
  ]
}

Video Generation

Generate AI-powered videos using state-of-the-art models including Kling, Sora 2, Google Veo, Luma, Seedance 2.0, Wan 2.7 (Kunya), and more.

POST/api/v1/videos/generations

Generate videos from text prompts or images.

Text-to-Video Request

{
  "prompt": "A majestic eagle soaring through misty mountains at sunrise, cinematic",
  "model": "kling-2.5-pro",
  "duration": 5,
  "aspect_ratio": "16:9",
  "resolution": "1080p"
}

Image-to-Video Request

{
  "prompt": "Gentle wind blowing through hair, subtle movement",
  "model": "kling-2.5-pro-i2v",
  "image_url": "data:image/png;base64,...",
  "duration": 5,
  "aspect_ratio": "16:9",
  "resolution": "720p"
}

The resolution parameter controls output quality. Use GET /api/v1/videos/generations to see each model's supported_resolutions. Higher resolutions incur a cost multiplier (1.5x for 1080p, 3x for 4K). Defaults to 720p.

Response

{
  "created": 1704067200,
  "data": [
    {
      "url": "https://fal.media/files/video_abc123.mp4",
      "duration": 5,
      "aspect_ratio": "16:9",
      "resolution": "1080p",
      "model": "kling-2.5-pro"
    }
  ],
  "usage": {
    "duration_seconds": 5,
    "cost": 0.375
  }
}
GET/api/v1/videos/status

Check the status of a video generation by ID.

// GET /api/v1/videos/status?id=gen_abc123

{
  "id": "gen_abc123",
  "status": "completed",
  "video_url": "https://fal.media/files/video_abc123.mp4",
  "thumbnail_url": "https://...",
  "prompt": "A majestic eagle soaring...",
  "model": "kling-2.5-pro",
  "created_at": "2025-01-15T12:00:00Z"
}
POST/api/v1/videos/ads

Generate an AI-enhanced video ad script.

// Request
{
  "script": "Introducing our revolutionary new fitness app...",
  "product_name": "FitPro AI",
  "target_audience": "Health-conscious millennials",
  "style": "energetic",
  "duration": 30
}

// Response
{
  "id": "ad_abc123",
  "script": "Enhanced script with scene directions...",
  "style": "energetic",
  "duration": 30,
  "cost": "0.025",
  "created_at": "2025-01-15T12:00:00Z"
}
GET/api/v1/videos/generations

List available video models with capabilities and pricing.

{
  "object": "list",
  "data": [
    {
      "id": "kling-2.5-pro",
      "name": "Kling 2.5 Pro",
      "description": "High-quality video with excellent character consistency",
      "provider": "FAL AI (Kling)",
      "capabilities": {
        "text_to_video": true,
        "image_to_video": false,
        "video_to_video": false
      },
      "supported_resolutions": ["720p", "1080p", "4k"],
      "max_duration": 10,
      "pricing": { "per_second": 0.05 }
    },
    {
      "id": "seedance-2.0-t2v",
      "name": "Seedance 2.0 Text-to-Video",
      "description": "ByteDance Seedance 2.0 โ€” multimodal video with synced audio, lip-sync, up to 15s",
      "provider": "Kunya (Seedance)",
      "capabilities": {
        "text_to_video": true,
        "image_to_video": false,
        "video_to_video": false
      },
      "supported_resolutions": ["480p", "720p"],
      "max_duration": 15,
      "pricing": { "per_second": 0.147 }
    },
    {
      "id": "seedance-1.5-pro",
      "name": "Seedance 1.5 Pro",
      "description": "ByteDance Seedance 1.5 โ€” synchronized audio+video with lip-sync and foley",
      "provider": "Kunya (Seedance)",
      "capabilities": {
        "text_to_video": true,
        "image_to_video": true,
        "video_to_video": false
      },
      "supported_resolutions": ["480p", "720p", "1080p"],
      "max_duration": 12,
      "pricing": { "per_second": 0.08 }
    },
    {
      "id": "evolink-wan2.7-t2v",
      "name": "Wan 2.7 Text-to-Video",
      "description": "Alibaba Wan 2.7 via Kunya โ€” multi-shot narrative, auto BGM/SFX or driving-audio lip-sync, 2-15s",
      "provider": "Kunya (Wan)",
      "capabilities": {
        "text_to_video": true,
        "image_to_video": false,
        "video_to_video": false
      },
      "supported_resolutions": ["720p", "1080p"],
      "min_duration": 2,
      "max_duration": 15,
      "pricing": { "per_second": 0.086 }
    }
  ]
}

Wan 2.7 Text-to-Video

{
  "prompt": "A small kitten running under the moonlight",
  "model": "evolink-wan2.7-t2v",
  "duration": 5,
  "aspect_ratio": "16:9",
  "resolution": "720p",
  "audio_urls": ["https://example.com/recital.mp3"],
  "negative_prompt": "blurry, low quality",
  "seed": 42,
  "model_params": { "prompt_extend": false }
}

Wan 2.7 supports audio_urls (one driving audio URL for lip-sync), negative_prompt, seed, and model_params.prompt_extend (default false). Without audio_urls, the model auto-generates background music and sound effects. Duration: 2โ€“15 seconds.

Note: Video generation typically takes 1-5 minutes depending on duration and model. Use the status endpoint to poll for completion. Seedance 2.0 supports generate_audio (default true) and model_params.web_search (default false) parameters. Wan 2.7 (Kunya) supports audio_urls, negative_prompt, seed, and model_params.prompt_extend.

Video Analysis

Multimodal video understanding powered by Gemini. Send a hosted video URL or YouTube link and get back structured analysis โ€” pacing, hooks, on-screen text, narration tone, B-roll cadence, or any custom dimensions you ask for. Far cheaper than per-frame screenshot analysis when temporal context matters.

POST/api/v1/videos/analyze

Analyze a hosted video or YouTube URL with Gemini. Returns markdown or a JSON object you control via prompt.

Request Body

{
  "video_url": "https://www.youtube.com/watch?v=Wlf1T5nrO50",
  "prompt": "Describe the hook in the first 5 seconds, the narration tone, and the pacing (cuts per 30s).",
  "response_format": "json",
  "json_schema_hint": "{ hookStyle, narrationTone, cutsPer30s, overallSentiment }",
  "model": "gemini-3.5-flash",
  "duration_seconds_hint": 480
}

Parameters

  • video_url (string, required) โ€” Hosted video URL (mp4/webm/mov) or a YouTube watch/share/shorts URL. YouTube links are passed to Gemini as fileData parts โ€” no download needed on your side.
  • prompt (string, required) โ€” What you want extracted. Be specific about the dimensions you care about.
  • response_format (string, optional) โ€” "markdown" (default) or "json". JSON mode adds responseMimeType: application/json so the response is a single parseable object.
  • json_schema_hint (string, optional) โ€” Shape hint appended to the prompt when response_format = "json".
  • model (string, optional) โ€” One of gemini-2.0-flash, gemini-2.5-flash, gemini-2.5-flash-lite, gemini-2.5-pro, gemini-3-flash-preview, gemini-3.5-flash (default), gemini-3.1-pro-preview, gemini-3.1-flash-lite.
  • duration_seconds_hint (number, optional) โ€” Used for token estimation if Gemini's usage metadata is missing.

Response (response_format = โ€œjsonโ€)

{
  "analysis": {
    "hookStyle": "Direct contrarian claim with on-screen counter-thesis",
    "narrationTone": "Casual, fast, mild sarcasm",
    "cutsPer30s": 14,
    "overallSentiment": "skeptical-positive"
  },
  "format": "json",
  "model": "gemini-3.5-flash",
  "videoUrl": "https://www.youtube.com/watch?v=Wlf1T5nrO50",
  "isYouTube": true,
  "tokens": { "input": 4123, "output": 312 }
}

curl

curl -X POST https://api.kunya.ai/api/v1/videos/analyze \
  -H "Authorization: Bearer kunya_..." \
  -H "Content-Type: application/json" \
  -d '{
    "video_url": "https://www.youtube.com/watch?v=Wlf1T5nrO50",
    "prompt": "What is this video about? List the 3 main claims.",
    "response_format": "json",
    "json_schema_hint": "{ summary, claims: string[] }"
  }'

Pricing & limits: Billed at the underlying Gemini modelโ€™s per-token rate plus the standard markup. Gemini meters video at ~263 tokens/second, so a 60-second clip is roughly 16k input tokens. Hosted videos under ~18MB are sent inline; larger files are uploaded to the Gemini Files API automatically. YouTube URLs work directly โ€” public videos only. Returns 400 with code video_not_supported if the requested model is not in the allowed list.

Video Editing

Professional video editing API with timeline-based EDL, 40+ transitions, effects, color grading, audio mixing, text overlays, and AI-powered natural language editing.

Projects

POST/api/v1/videos/edit/projects

Create a new video editing project with sources, tracks, and output settings.

Request Body

{
  "name": "My Video Project",
  "sources": [
    { "id": "src_1", "type": "video", "url": "https://...", "name": "Intro.mp4", "duration": 15.5 },
    { "id": "src_2", "type": "audio", "url": "https://...", "name": "BGMusic.mp3", "duration": 120 },
    { "id": "src_3", "type": "image", "url": "https://...", "name": "Logo.png" }
  ],
  "tracks": [
    {
      "id": "track_v1", "type": "video", "volume": 1,
      "clips": [
        {
          "id": "clip_1", "sourceId": "src_1",
          "startTime": 0, "duration": 10,
          "sourceIn": 0, "sourceOut": 10,
          "effects": [
            { "type": "color_grade", "params": { "brightness": 0.05, "contrast": 1.2, "saturation": 0.9 } }
          ],
          "transition": null
        }
      ]
    },
    {
      "id": "track_a1", "type": "audio", "volume": 0.5,
      "clips": [
        { "id": "clip_a1", "sourceId": "src_2", "startTime": 0, "duration": 10, "sourceIn": 0, "sourceOut": 10 }
      ]
    }
  ],
  "outputSettings": { "format": "mp4", "resolution": "1080p", "fps": 30, "codec": "h264" }
}

Response

{
  "success": true,
  "project": {
    "id": "proj_abc123",
    "name": "My Video Project",
    "status": "draft",
    "created_at": "2025-01-15T12:00:00Z"
  }
}
GET/api/v1/videos/edit/projects

List all video editing projects in the workspace.

{
  "success": true,
  "projects": [
    { "id": "proj_abc123", "name": "My Video Project", "status": "draft", "created_at": "..." },
    { "id": "proj_def456", "name": "Product Demo", "status": "completed", "outputUrl": "https://..." }
  ]
}

Rendering

POST/api/v1/videos/edit/render

Submit a render job to process the EDL into a final video file.

Request Body

{
  "projectId": "proj_abc123",
  "type": "render",
  "outputSettings": { "format": "mp4", "resolution": "1080p", "fps": 30, "codec": "h264" }
}

Response

{
  "success": true,
  "jobId": "job_xyz789",
  "status": "queued"
}
GET/api/v1/videos/edit/status

Poll render job status and progress. Query: ?jobId=job_xyz789

In Progress

{
  "success": true,
  "job": { "id": "job_xyz789", "status": "processing", "progress": 65, "outputUrl": null }
}

Completed

{
  "success": true,
  "job": { "id": "job_xyz789", "status": "completed", "progress": 100, "outputUrl": "https://r2.example.com/output.mp4" }
}

AI Edit (Natural Language)

POST/api/v1/videos/edit/ai

Edit a video using natural language instructions. The AI translates your instruction into precise timeline modifications. Supports any model available in the Kunya API.

Request Body

{
  "message": "Add dissolve transitions between all clips, apply cinematic color grading, and add a title at the start",
  "model": "claude-sonnet-4.6",
  "sources": [
    { "id": "src_1", "type": "video", "url": "https://...", "name": "Footage.mp4", "duration": 30 }
  ],
  "tracks": [
    { "id": "track_v", "type": "video", "clips": [
      { "id": "clip_1", "sourceId": "src_1", "startTime": 0, "duration": 15, "sourceIn": 0, "sourceOut": 15 },
      { "id": "clip_2", "sourceId": "src_1", "startTime": 15, "duration": 15, "sourceIn": 15, "sourceOut": 30 }
    ]}
  ]
}

Response

{
  "success": true,
  "message": "Added dissolve transitions (0.5s), applied cinematic color grade, and added 'My Title' text at 0-3s.",
  "tracks": [
    { "id": "track_v", "type": "video", "clips": [
      { "id": "clip_1", "sourceId": "src_1", "startTime": 0, "duration": 15, "sourceIn": 0, "sourceOut": 15,
        "effects": [{ "type": "color_grade", "params": { "brightness": 0.05, "contrast": 1.3, "saturation": 0.85, "temperature": 0.1 } }]
      },
      { "id": "clip_2", "sourceId": "src_1", "startTime": 15, "duration": 15, "sourceIn": 15, "sourceOut": 30,
        "transition": { "type": "dissolve", "duration": 0.5 },
        "effects": [{ "type": "color_grade", "params": { "brightness": 0.05, "contrast": 1.3, "saturation": 0.85, "temperature": 0.1 } }]
      }
    ]},
    { "id": "track_t", "type": "text", "clips": [
      { "id": "clip_t1", "sourceId": "", "startTime": 0, "duration": 3, "sourceIn": 0, "sourceOut": 3, "text": "My Title", "style": { "fontSize": 72, "fontColor": "white", "fontWeight": "bold" } }
    ]}
  ]
}

Effects Reference

EffectTypeKey ParamsDescription
Speedspeedfactor: 0.25-4.0Constant speed change
Speed Rampspeed_ramppoints: JSON arrayVariable speed over time
Fade Infade_induration: secondsVideo fade from black
Fade Outfade_outduration: secondsVideo fade to black
Blurblur / gaussian_blurintensity: 1-20Gaussian blur
Cropcropx, y, width, heightCrop region
Volumevolumelevel: 0-3Audio volume adjustment
Noise Reductionnoise_reductionstrength: 5-25Reduce background noise
Color Gradecolor_gradebrightness, contrast, saturation, temperatureFull color correction
Curvescurvespreset: vintage, lighter, etc.Color curves preset
LUTluturl: .cube file URLCustom LUT file
Sharpensharpenintensity: 0-5Sharpen video
Vignettevignetteintensity: 0-1Add vignette effect
LetterboxletterboxaspectRatio: "2.35:1"Add letterbox bars
Chroma Keychroma_keycolor, similarityGreen screen removal

Example: Clip with Multiple Effects

{
  "id": "clip_1",
  "sourceId": "src_1",
  "startTime": 0,
  "duration": 10,
  "sourceIn": 0,
  "sourceOut": 10,
  "effects": [
    { "type": "color_grade", "params": { "brightness": 0.05, "contrast": 1.2, "saturation": 0.9, "temperature": 0.15 } },
    { "type": "vignette", "params": { "intensity": 0.3 } },
    { "type": "letterbox", "params": { "aspectRatio": "2.35:1" } },
    { "type": "fade_in", "params": { "duration": 1 } }
  ]
}

Transitions Reference

Transitions are applied between adjacent clips. Set the transition field on the second clip (the clip being transitioned TO).

{
  "id": "clip_2",
  "sourceId": "src_1",
  "startTime": 10,
  "duration": 8,
  "sourceIn": 10,
  "sourceOut": 18,
  "transition": { "type": "dissolve", "duration": 0.5 }
}

All Available Transitions (40+)

dissolvefadefadeblackfadewhitefadegrayswipe_leftwipe_rightwipe_upwipe_downslide_leftslide_rightslide_upslide_downsmoothleftsmoothrightsmoothupsmoothdownzoom_inzoom_outspinblur_transitionpixelizeradial_wipeclock_wipesqueeze_hsqueeze_vcover_leftcover_rightcover_upcover_downreveal_leftreveal_rightreveal_upreveal_downdiagonal_tldiagonal_trdiagonal_bldiagonal_briris_openiris_closehorzopenhorzclosevertopenvertclosecirclecroprectcropdistance

Text Overlays

Text clips support rich styling with fonts, colors, backgrounds, shadows, and animations.

{
  "id": "clip_t1", "sourceId": "", "startTime": 0, "duration": 3,
  "sourceIn": 0, "sourceOut": 3,
  "text": "My Title",
  "style": {
    "fontFamily": "Arial", "fontSize": 72, "fontColor": "#ffffff",
    "fontWeight": "bold", "textAlign": "center",
    "backgroundColor": "#000000", "backgroundOpacity": 0.5,
    "borderColor": "black", "borderWidth": 2,
    "shadowColor": "#000000", "shadowX": 2, "shadowY": 2,
    "animation": { "type": "fade_in", "duration": 0.5 }
  }
}

Text animations: none, fade_in, fade_out, slide_in_left, slide_in_right, slide_in_up, slide_in_down, scale_in, scale_out, typewriter, bounce, blur_in

Audio Mixing

Multiple audio tracks with independent volume and mute controls. Clips support per-clip volume effects and audio fades.

{
  "id": "track_a1", "type": "audio", "volume": 0.8, "muted": false,
  "clips": [
    {
      "id": "clip_bgm", "sourceId": "src_music", "startTime": 0, "duration": 60,
      "sourceIn": 0, "sourceOut": 60,
      "effects": [
        { "type": "audio_fade_in", "params": { "duration": 2 } },
        { "type": "audio_fade_out", "params": { "duration": 3 } }
      ]
    },
    {
      "id": "clip_sfx", "sourceId": "src_ding", "startTime": 15, "duration": 2,
      "sourceIn": 0, "sourceOut": 2,
      "effects": [{ "type": "volume", "params": { "level": 1.5 } }]
    }
  ]
}

Note: Video editing render jobs are processed by a dedicated FFmpeg worker. Render times vary with complexity but typically complete in 30s-5min. Use the status endpoint to poll progress.

Audio (TTS & Transcription)

POST/api/v1/audio/speech

Convert text to natural-sounding speech using ElevenLabs or Google TTS.

Request Body

{
  "text": "Hello, welcome to our platform!",
  "provider": "elevenlabs",
  "voice_id": "21m00Tcm4TlvDq8ikWAM",
  "settings": {
    "stability": 0.5,
    "similarity_boost": 0.75
  }
}

Response

{
  "id": "audio_abc123",
  "audio_url": "data:audio/mpeg;base64,...",
  "provider": "elevenlabs",
  "voice_id": "21m00Tcm4TlvDq8ikWAM",
  "voice_name": "Rachel",
  "duration": 3,
  "cost": 0.0012
}
POST/api/v1/audio/transcriptions

Transcribe audio files to text using OpenAI Whisper.

Request (multipart/form-data)

curl -X POST https://kunya.ai/api/v1/audio/transcriptions \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -F "[email protected]" \
  -F "language=en" \
  -F "response_format=json"

Response

{
  "transcription": {
    "text": "Hello, this is a test recording..."
  },
  "model": "whisper-1",
  "language": "en",
  "duration_seconds": 45,
  "cost": 0.0045
}
POST/api/v1/audio/meeting-notes

Transcribe audio and generate structured meeting notes with action items.

Request (multipart/form-data)

curl -X POST https://kunya.ai/api/v1/audio/meeting-notes \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -F "[email protected]"

Response

{
  "transcription": "Full transcript of the meeting...",
  "duration": 1800,
  "notes": {
    "summary": "Team discussed Q1 roadmap priorities...",
    "key_points": ["Agreed on new feature timeline", "Budget approved"],
    "action_items": [
      { "owner": "Alice", "task": "Draft PRD by Friday" },
      { "owner": "Bob", "task": "Set up staging environment" }
    ]
  },
  "cost": "0.235"
}

Music Generation

Generate AI music from text prompts using multiple providers including Suno, MiniMax, CassetteAI, Sonauto, ElevenLabs, and more. Suno models support custom lyrics, vocal gender, and creative controls.

POST/api/v1/audio/music

Generate music from a text prompt. Suno models support custom lyrics, vocal gender, and style controls.

Request Body

{
  "prompt": "A cheerful summer pop song about road trips and freedom",
  "model": "suno-v5",
  "duration": 60,
  "style": "pop, electronic, upbeat"
}

Request Body (Suno custom mode)

{
  "prompt": "[Verse]\nDriving down the highway, windows down\n[Chorus]\nSummer dreams, summer nights",
  "model": "suno-v4.5",
  "title": "Summer Dreams",
  "style": "pop, electronic, upbeat, female vocals",
  "instrumental": false,
  "vocal_gender": "f",
  "negative_tags": "heavy metal, screaming",
  "style_weight": 0.7
}

Available Models

ModelProviderMax DurationVocals
suno-v5Suno480sYes
suno-v4.5Suno480sYes
suno-v4.5plusSuno480sYes
suno-v4.5allSuno480sYes
suno-v4Suno240sYes
elevenlabs-musicElevenLabs600sYes
minimax-musicMiniMax240sYes
minimax-music-v2MiniMax240sYes
cassetteai-musicCassetteAI240sNo
sonauto-v2Sonauto240sYes
beatoven-musicBeatoven150sNo
stable-audioStability47sNo
musicgen-largeMeta30sNo
lyria-realtimeGoogle300sNo

Suno-specific Parameters

ParameterTypeDescription
titlestringSong title (max 80 chars)
vocal_genderstringm or f
negative_tagsstringStyles to avoid (comma-separated)
style_weightnumber0.0โ€“1.0, style adherence
weirdness_constraintnumber0.0โ€“1.0, creativity level
audio_weightnumber0.0โ€“1.0, audio feature weight
instrumentalbooleantrue for no vocals
custom_modebooleanFine control over style/title/lyrics

Response

{
  "id": "music_abc123",
  "model": "suno-v5",
  "audio_url": "https://media.example.com/music_abc123.mp3",
  "duration": 91,
  "cost": "0.10",
  "created_at": "2025-01-15T12:00:00Z"
}
POST/api/v1/audio/agent-generate

Batch music generation with an AI agent. Parse complex tasks into prompt+model+duration tuples, then generate all tracks with SSE progress streaming. Up to 50 tracks per batch.

Parse Task

// Request
{
  "action": "parse",
  "task": "Generate 3 tracks:\n- An upbeat electronic track with synths, 60s (CassetteAI)\n- A cinematic orchestral piece, 90s (Lyria)\n- A pop song about summer with vocals, 60s (Suno V5)",
  "parser_model": "gemini-3.5-flash"
}

// Response
{
  "data": {
    "items": [
      { "id": "item_1", "model": "cassetteai-music", "model_name": "CassetteAI Music", "prompt": "Upbeat electronic track with driving synths", "duration": 60, "estimated_cost": 0.02 },
      { "id": "item_2", "model": "lyria-realtime", "model_name": "Lyria RealTime", "prompt": "Cinematic orchestral piece with strings", "duration": 90, "estimated_cost": 0.036 },
      { "id": "item_3", "model": "suno-v5", "model_name": "Suno V5", "prompt": "Pop song about summer love", "duration": 60, "style": "upbeat", "lyrics": "[Verse]\nSunshine on my face...", "estimated_cost": 0.06 }
    ],
    "total_estimated_cost": 0.116
  }
}

Execute (SSE Stream)

// Request
{
  "action": "execute",
  "items": [{ "id": "item_1", "model": "cassetteai-music", "prompt": "...", "duration": 60, "estimated_cost": 0.02 }]
}

// SSE Events
event: job_created โ†’ { "job_id": "uuid", "total_items": 3 }
event: item_started โ†’ { "item_id": "item_1" }
event: item_completed โ†’ { "item_id": "item_1", "audio_url": "https://...", "cost": 0.02, "duration": 62 }
event: item_failed โ†’ { "item_id": "item_2", "error": "Provider timeout" }
event: done โ†’ { "total": 3, "succeeded": 2, "failed": 1, "total_cost": 0.08 }

Cancel

{ "action": "cancel", "job_id": "uuid" }

Podcast Generation

Generate multi-voice podcast audio from a script with speaker assignments.

POST/api/v1/audio/podcast

Generate podcast audio from a script with multiple speakers.

// Request
{
  "script": [
    { "speaker": "host", "text": "Welcome to the show! Today we're discussing AI." },
    { "speaker": "guest", "text": "Thanks for having me. AI is transforming everything." },
    { "speaker": "host", "text": "Let's dive into the key trends." }
  ],
  "speakers": [
    { "id": "host", "name": "Sarah", "voice_id": "21m00Tcm4TlvDq8ikWAM" },
    { "id": "guest", "name": "Dr. Chen", "voice_id": "EXAVITQu4vr4xnSDxMaL" }
  ]
}

// Response
{
  "id": "podcast_abc123",
  "segments": [
    { "speaker": "host", "audio_url": "data:audio/mpeg;base64,...", "text": "Welcome to the show!..." },
    { "speaker": "guest", "audio_url": "data:audio/mpeg;base64,...", "text": "Thanks for having me..." },
    { "speaker": "host", "audio_url": "data:audio/mpeg;base64,...", "text": "Let's dive into..." }
  ],
  "total_segments": 3,
  "cost": "0.0156",
  "created_at": "2025-01-15T12:00:00Z"
}

Voice Cloning

Clone custom voices for personalized text-to-speech. Upload audio samples to create unique voice profiles.

GET/api/v1/audio/voices

List available voices including default and custom cloned voices.

{
  "object": "list",
  "data": [
    {
      "id": "alloy",
      "name": "Alloy",
      "description": "Neutral and balanced",
      "provider": "openai",
      "category": "default"
    },
    {
      "id": "voice_abc123",
      "name": "My Brand Voice",
      "description": "Custom cloned voice",
      "provider": "elevenlabs",
      "category": "cloned",
      "preview_url": "https://..."
    }
  ]
}
POST/api/v1/audio/voices

Clone a new voice from audio samples (multipart/form-data).

Request (multipart/form-data)

curl -X POST https://kunya.ai/api/v1/audio/voices \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -F "name=My Brand Voice" \
  -F "description=Professional narrator voice" \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "[email protected]"

Response

{
  "id": "voice_abc123xyz",
  "name": "My Brand Voice",
  "description": "Professional narrator voice",
  "provider": "elevenlabs",
  "created": 1704067200
}
Audio Sample Requirements
  • Upload 1-25 audio samples (more = better quality)
  • Clear, single-speaker recordings
  • MP3, WAV, or M4A format
  • Minimum 30 seconds total audio recommended
  • Avoid background noise or music

Voice Agents

Create AI-powered voice agents for phone calls, support, sales, and interviews.

POST/api/v1/voice/agents

Create a new voice agent.

// Request
{
  "name": "Support Agent",
  "description": "Handles customer support calls",
  "type": "support",
  "voice": {
    "provider": "elevenlabs",
    "voice_id": "21m00Tcm4TlvDq8ikWAM"
  },
  "model": "claude-sonnet-4.6",
  "system_prompt": "You are a helpful customer support agent...",
  "greeting": "Hello! How can I help you today?",
  "language": "en",
  "max_call_duration_minutes": 30
}

// Response (201)
{
  "data": {
    "id": "vagent_abc123",
    "name": "Support Agent",
    "type": "support",
    "is_active": true,
    "created_at": "2025-01-15T12:00:00Z"
  },
  "message": "Voice agent created"
}
GET/api/v1/voice/agents

List voice agents with optional type and active status filtering.

// GET /api/v1/voice/agents?type=support&active=true

{
  "data": [
    {
      "id": "vagent_abc123",
      "name": "Support Agent",
      "type": "support",
      "voice": { "provider": "elevenlabs", "voice_id": "..." },
      "model": "claude-sonnet-4.6",
      "phone_number": "+1234567890",
      "is_active": true,
      "stats": {
        "total_calls": 150,
        "avg_call_duration": 180,
        "avg_satisfaction": 4.5
      },
      "created_at": "2025-01-10T09:00:00Z"
    }
  ]
}
GET/api/v1/voice/agents/{id}

Get full voice agent details including recent calls.

{
  "data": {
    "id": "vagent_abc123",
    "name": "Support Agent",
    "type": "support",
    "voice": { "provider": "elevenlabs", "voice_id": "..." },
    "model": "claude-sonnet-4.6",
    "temperature": 0.7,
    "system_prompt": "You are a helpful...",
    "greeting": "Hello! How can I help?",
    "behavior_rules": [...],
    "forbidden_topics": [...],
    "is_active": true,
    "stats": { "total_calls": 150 },
    "recent_calls": [...],
    "created_at": "2025-01-10T09:00:00Z"
  }
}

Content Library

Save, organize, and AI-summarize content from articles, URLs, and text.

GET/api/v1/content

List saved content with filtering and pagination.

// GET /api/v1/content?limit=50&offset=0&content_type=article&search=AI

{
  "data": [
    {
      "id": "cnt_abc123",
      "title": "The Future of AI in Healthcare",
      "description": "A comprehensive overview...",
      "content_type": "article",
      "url": "https://example.com/ai-healthcare",
      "summary": "AI is revolutionizing healthcare...",
      "is_favorite": true,
      "collection_id": "col_xyz",
      "created_at": "2025-01-15T10:00:00Z"
    }
  ],
  "total": 42,
  "limit": 50,
  "offset": 0
}
POST/api/v1/content

Save new content to your library.

// Request
{
  "title": "Great Article on AI",
  "url": "https://example.com/ai-article",
  "content_type": "article",
  "collection_id": "col_xyz"
}

// Response (201)
{
  "id": "cnt_xyz789",
  "title": "Great Article on AI",
  "content_type": "article",
  "created_at": "2025-01-15T12:00:00Z"
}
POST/api/v1/content/summarize

Generate an AI-powered summary of text or URL content.

// Request
{
  "url": "https://example.com/long-article",
  "max_length": 300
}

// Response
{
  "summary": "This article discusses the key trends in AI...",
  "cost": "0.0025"
}
GET/api/v1/content/collections

List content collections.

{
  "data": [
    {
      "id": "col_xyz",
      "name": "AI Research",
      "description": "Curated AI research papers and articles",
      "color": "#3b82f6",
      "icon": "brain",
      "created_at": "2025-01-01T00:00:00Z"
    }
  ]
}
POST/api/v1/content/collections

Create a new content collection.

// Request
{
  "name": "Product Research",
  "description": "Competitor analysis and market research",
  "color": "#10b981",
  "icon": "search"
}

// Response (201)
{
  "id": "col_new123",
  "name": "Product Research",
  "created_at": "2025-01-15T12:00:00Z"
}

Files

Process, extract text from, and convert files between formats.

POST/api/v1/files/process

Process uploaded files (PDF, Excel, Word, images, text) and extract content.

Request (multipart/form-data)

curl -X POST https://kunya.ai/api/v1/files/process \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -F "[email protected]" \
  -F "action=extract_text"

Available Actions

ActionDescription
extract_textExtract raw text from the file
summarizeExtract text and generate AI summary
analyzeExtract text and run AI analysis
extract_dataExtract structured data from the file

Response

{
  "filename": "document.pdf",
  "size": 245000,
  "type": "application/pdf",
  "action": "extract_text",
  "text": "Extracted text content from the PDF...",
  "cost": "0.001"
}
POST/api/v1/files/convert

Convert files between formats (CSV, XLSX, JSON, Markdown, HTML).

curl -X POST https://kunya.ai/api/v1/files/convert \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -F "[email protected]" \
  -F "target_format=xlsx"

Workspaces

Pages

Create, read, update, and manage workspace pages. Pages can be documents (rich text) or databases (structured data).

GET/v1/workspaces/pages

List pages in the workspace with optional filters.

Query Parameters

NameTypeRequiredDescription
space_idstringNoFilter by space
parent_idstringNoFilter by parent page
typestringNoFilter by type: document or database
searchstringNoSearch in title and content
trashedbooleanNoInclude trashed pages
favoritesbooleanNoOnly favorite pages
limitnumberNoMax results (default 50, max 200)
offsetnumberNoPagination offset
curl -X GET "https://api.kunya.app/v1/workspaces/pages?type=document&limit=20" \
  -H "Authorization: Bearer kunya_xxx"
POST/v1/workspaces/pages

Create a new page (document or database).

Request Body

NameTypeRequiredDescription
titlestringNoPage title (default: Untitled)
typestringNodocument, database, or whiteboard (default: document)
space_idstringNoSpace to create in
parent_idstringNoParent page for nesting
contentobjectNoTiptap JSON content for documents
emojistringNoPage emoji icon
template_idstringNoTemplate to apply
curl -X POST "https://api.kunya.app/v1/workspaces/pages" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{"title": "Project Plan", "type": "document", "emoji": "๐Ÿ“‹"}'
GET/v1/workspaces/pages/:id

Get a single page with its content and metadata.

PUT/v1/workspaces/pages/:id

Update page content, title, or metadata. Auto-versions on significant content changes.

Request Body

NameTypeRequiredDescription
titlestringNoUpdated title
contentobjectNoUpdated Tiptap JSON content
emojistringNoUpdated emoji
is_favoritebooleanNoToggle favorite
cover_imagestringNoCover image URL
propertiesobjectNoPage metadata properties
DELETE/v1/workspaces/pages/:id

Soft-delete page to trash. Add ?permanent=true to hard delete.

Databases

Workspace databases are structured data stores with typed columns, multiple views, filters, sorts, grouping, and formulas.

GET/v1/workspaces/databases/:id

Get database configuration including columns, views, and row count.

PUT/v1/workspaces/databases/:id

Update database columns, views, filters, sorts, or grouping.

Request Body

NameTypeRequiredDescription
columnsarrayNoColumn definitions (id, name, type, options)
view_configsarrayNoView configurations
default_view_idstringNoDefault view to show
filter_configsobjectNoDefault filter configuration
sort_configsarrayNoDefault sort rules
group_configobjectNoGrouping configuration

Column Types

text, number, select, multi_select, date, person, files, checkbox, url, email, phone, formula, relation, rollup, created_time, last_edited_time, created_by, last_edited_by, auto_increment, rating, progress, currency

Database Rows

CRUD operations on database rows. Rows store cell values keyed by column ID.

GET/v1/workspaces/databases/:id/rows

List rows with pagination, filtering, and sorting.

Query Parameters

NameTypeRequiredDescription
limitnumberNoMax results (default 50, max 500)
offsetnumberNoPagination offset
sort_bystringNoColumn ID to sort by
sort_dirstringNoasc or desc
searchstringNoSearch text cells
filtersstringNoJSON-encoded filter group
POST/v1/workspaces/databases/:id/rows

Create a new row.

Request Body

NameTypeRequiredDescription
cellsobjectYesCell values keyed by column ID
sort_ordernumberNoPosition in the list
curl -X POST "https://api.kunya.app/v1/workspaces/databases/db_xxx/rows" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{"cells": {"col_title": "New Task", "col_status": "in_progress", "col_priority": 3}}'
GET/v1/workspaces/databases/:id/rows/:rowId

Get a single row.

PUT/v1/workspaces/databases/:id/rows/:rowId

Update row cells (shallow merge with existing).

DELETE/v1/workspaces/databases/:id/rows/:rowId

Delete a row.

Page Actions

Lock, duplicate, move, and export workspace pages. AI-powered content operations.

POST/v1/workspaces/pages/:id/lock

Lock a page to prevent edits. Returns 409 if already locked.

DELETE/v1/workspaces/pages/:id/lock

Unlock a page. Only the user who locked it can unlock (403 otherwise).

POST/v1/workspaces/pages/:id/duplicate

Duplicate a page including children, databases, and rows.

POST/v1/workspaces/pages/:id/move

Move a page to a new parent. Prevents circular references.

Request Body

NameTypeRequiredDescription
parent_idstringNoNew parent page ID (null for root)
space_idstringNoMove to a different space
sort_ordernumberNoPosition among siblings
POST/v1/workspaces/pages/:id/export

Export page content in various formats.

Request Body

NameTypeRequiredDescription
formatstringYesExport format: markdown, html, pdf, docx, csv, json
POST/v1/workspaces/pages/:id/ai

Run AI operations on page content (write, rewrite, summarize, translate, etc.).

Request Body

NameTypeRequiredDescription
operationstringYesAI operation: ai_write, ai_continue, ai_rewrite, ai_summarize, ai_translate, ai_expand, ai_shorten, ai_fix_grammar, ai_change_tone, ai_explain, ai_extract_action_items, ai_generate_outline, ai_improve
contentstringYesPage content to operate on
modelstringNoAI model to use (default: gemini-3.5-flash)
instructionstringNoCustom instruction for write/rewrite operations
tonestringNoTarget tone: professional, casual, friendly, formal, academic
target_languagestringNoTarget language for translation

Comments

Threaded comments on workspace pages. Supports inline block references and resolve/unresolve.

GET/v1/workspaces/pages/:id/comments

List all comments for a page, threaded by parent.

POST/v1/workspaces/pages/:id/comments

Add a comment to a page.

Request Body

NameTypeRequiredDescription
contentstringYesComment text
block_refstringNoReference to a specific block in the page
parent_comment_idstringNoParent comment ID for threading
PUT/v1/workspaces/pages/:id/comments/:commentId

Update a comment (author only).

DELETE/v1/workspaces/pages/:id/comments/:commentId

Delete a comment (author only).

POST/v1/workspaces/pages/:id/comments/:commentId/resolve

Toggle resolve/unresolve a comment thread.

Sharing

Share pages with specific users or create public links with configurable permissions.

GET/v1/workspaces/pages/:id/share

List all shares for a page.

POST/v1/workspaces/pages/:id/share

Create a share (user invite or public link).

Request Body

NameTypeRequiredDescription
permissionstringYesPermission level: view, comment, edit, full_access
user_idstringNoUser ID to share with
emailstringNoEmail to share with
is_public_linkbooleanNoCreate a public share link
DELETE/v1/workspaces/pages/:id/share

Remove a share. Pass share_id in the request body.

Version History

Automatic and manual version snapshots for workspace pages. Restore any previous version.

GET/v1/workspaces/pages/:id/versions

List all versions for a page, newest first.

POST/v1/workspaces/pages/:id/versions

Create a manual version snapshot.

Request Body

NameTypeRequiredDescription
change_descriptionstringNoDescription of the snapshot
POST/v1/workspaces/pages/:id/versions/:versionId/restore

Restore a page to a previous version. Creates a new version entry for the restore.

Database Views

Manage database views: table, board, calendar, gallery, list, timeline, and chart.

GET/v1/workspaces/databases/:id/views

List all views for a database.

POST/v1/workspaces/databases/:id/views

Create a new view.

Request Body

NameTypeRequiredDescription
namestringYesView name
typestringYesView type: table, board, calendar, gallery, list, timeline, chart
filtersobjectNoFilter configuration
sortsarrayNoSort configuration
visible_columnsarrayNoColumn IDs to show
PUT/v1/workspaces/databases/:id/views/:viewId

Update a view (name, filters, sorts, visible columns, etc.).

DELETE/v1/workspaces/databases/:id/views/:viewId

Delete a view.

Database Advanced

Bulk operations, import/export, formula validation, and AI-powered natural language queries.

POST/v1/workspaces/databases/:id/rows/bulk

Bulk insert rows (max 1000 per request).

Request Body

NameTypeRequiredDescription
rowsarrayYesArray of row objects, each with a cells property
DELETE/v1/workspaces/databases/:id/rows/bulk

Bulk delete rows by ID.

Request Body

NameTypeRequiredDescription
row_idsarrayYesArray of row IDs to delete
POST/v1/workspaces/databases/:id/import

Import data from CSV or JSON.

Request Body

NameTypeRequiredDescription
datastringYesRaw CSV or JSON string
formatstringYesData format: csv or json
column_mappingobjectNoMap source column names to database column names
POST/v1/workspaces/databases/:id/export

Export database as CSV or JSON file.

Request Body

NameTypeRequiredDescription
formatstringYesExport format: csv or json
view_idstringNoView ID to filter visible columns
POST/v1/workspaces/databases/:id/formula/validate

Validate a formula expression.

Request Body

NameTypeRequiredDescription
formulastringYesFormula expression to validate
POST/v1/workspaces/databases/:id/query

AI-powered natural language query. Converts text questions into filters and sorts.

Request Body

NameTypeRequiredDescription
querystringYesNatural language question (e.g. "Show all deals over $10k closing this month")
modelstringNoAI model to use (default: gemini-3.5-flash)

Templates

Document and database templates. List public templates or create workspace-specific ones.

GET/v1/workspaces/templates

List templates (public and workspace-specific).

Query Parameters

NameTypeRequiredDescription
typestringNoFilter by type: document or database
categorystringNoFilter by category
searchstringNoSearch by name or description
POST/v1/workspaces/templates

Create a new template.

Request Body

NameTypeRequiredDescription
namestringYesTemplate name
typestringYesTemplate type: document or database
descriptionstringNoTemplate description
emojistringNoEmoji icon
categorystringNoCategory for organization
contentobjectNoTemplate content (TipTap JSON)
database_schemaobjectNoDatabase column schema for database templates
is_publicbooleanNoMake template available to all workspaces
GET/v1/workspaces/templates/:id

Get a single template.

PUT/v1/workspaces/templates/:id

Update a template (workspace-owned only).

DELETE/v1/workspaces/templates/:id

Delete a template (creator only).

Spaces

Organize pages into spaces (folders/teams). Each space can contain multiple pages.

GET/v1/workspaces/spaces

List all spaces in the workspace.

POST/v1/workspaces/spaces

Create a new space.

Request Body

NameTypeRequiredDescription
namestringYesSpace name
iconstringNoIcon identifier
emojistringNoEmoji icon
descriptionstringNoSpace description
GET/v1/workspaces/spaces/:id

Get a space with its pages.

PUT/v1/workspaces/spaces/:id

Update space details.

DELETE/v1/workspaces/spaces/:id

Delete a space.

Trash

Manage trashed pages. Soft-deleted pages can be restored or permanently removed.

GET/v1/workspaces/trash

List all trashed pages.

POST/v1/workspaces/trash/:id/restore

Restore a trashed page.

DELETE/v1/workspaces/trash/empty

Permanently delete all trashed pages.

Whiteboards

Programmatically read and manipulate shapes on whiteboard pages. Create a whiteboard page with POST /v1/workspaces/pages using type: "whiteboard", then use these endpoints to manage shapes.

GET/v1/workspaces/pages/:id/whiteboard

Get all shapes on a whiteboard.

Response

NameTypeRequiredDescription
page_idstringYesThe whiteboard page ID
versionnumberYesDocument version (always 1)
shapesarrayYesArray of shape objects
shape_countnumberYesTotal number of shapes
curl -X GET "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/whiteboard" \
  -H "Authorization: Bearer kunya_xxx"
PUT/v1/workspaces/pages/:id/whiteboard

Replace all shapes on a whiteboard (full overwrite).

Request Body

NameTypeRequiredDescription
shapesarrayYesComplete array of shapes to set on the board
curl -X PUT "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/whiteboard" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{"shapes": [{"type": "rectangle", "x": 100, "y": 100, "width": 200, "height": 150}]}'
POST/v1/workspaces/pages/:id/whiteboard/shapes

Add one or more shapes to the whiteboard.

Request Body

NameTypeRequiredDescription
shapesarrayYesArray of shapes to add (max 500)
shapes[].typestringYesrectangle, ellipse, diamond, line, arrow, pencil, text, sticky, image, frame, or connector
shapes[].xnumberNoX position (default: 0)
shapes[].ynumberNoY position (default: 0)
shapes[].widthnumberNoWidth in pixels
shapes[].heightnumberNoHeight in pixels
shapes[].textstringNoText content (for text, sticky types)
shapes[].titlestringNoFrame title (for frame type)
shapes[].fillstringNoFill color (hex or transparent)
shapes[].strokestringNoStroke color (hex)
shapes[].stroke_widthnumberNoStroke width in pixels
shapes[].start_shape_idstringNoStart shape for connectors
shapes[].end_shape_idstringNoEnd shape for connectors
shapes[].start_anchorstringNoauto, top, right, bottom, or left
shapes[].end_anchorstringNoauto, top, right, bottom, or left
curl -X POST "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/whiteboard/shapes" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{"shapes": [
    {"type": "rectangle", "x": 100, "y": 100, "width": 200, "height": 100, "text": "Step 1", "fill": "#bfdbfe"},
    {"type": "rectangle", "x": 400, "y": 100, "width": 200, "height": 100, "text": "Step 2", "fill": "#bbf7d0"},
    {"type": "connector", "start_shape_id": "SHAPE_1_ID", "end_shape_id": "SHAPE_2_ID"}
  ]}'
PUT/v1/workspaces/pages/:id/whiteboard/shapes/:shapeId

Update an existing shape by ID.

Request Body

NameTypeRequiredDescription
xnumberNoNew X position
ynumberNoNew Y position
widthnumberNoNew width
heightnumberNoNew height
textstringNoUpdated text content
fillstringNoUpdated fill color
strokestringNoUpdated stroke color
lockedbooleanNoLock/unlock the shape
curl -X PUT "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/whiteboard/shapes/SHAPE_ID" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{"text": "Updated label", "fill": "#fecaca"}'
DELETE/v1/workspaces/pages/:id/whiteboard/shapes/:shapeId

Delete a shape by ID. Connected connectors are also removed.

curl -X DELETE "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/whiteboard/shapes/SHAPE_ID" \
  -H "Authorization: Bearer kunya_xxx"

Page Content

Read the body of a document page as structured TipTap JSON, plain text, or converted Markdown. For whiteboards, returns the shapes array. For databases, returns a pointer to the rows API.

TipTap Block Types

Document pages store content as TipTap JSON โ€” an array of typed blocks. Each block has a type and optional attrs and content fields.

Block TypeDescriptionKey Attributes
paragraphPlain text blockโ€”
headingSection headinglevel (1โ€“4)
bulletListUnordered listโ€”
orderedListNumbered listโ€”
taskListChecklist with checkboxesโ€”
blockquoteBlock quotationโ€”
codeBlockSyntax-highlighted codelanguage
horizontalRuleHorizontal dividerโ€”
imageInline imagesrc, alt, title, width, height
fileAttachmentUploaded file (PDF, DOCX, etc.)url, fileName, fileSize, mimeType
tableTable with rows and cellsโ€”
calloutBlockHighlighted notice blocktype (info, warning, error, success)
toggleBlockCollapsible contentsummary, open
tableOfContentsAuto-generated from headingsโ€”
mathBlockLaTeX math equationlatex
bookmarkNamed anchor pointid, label
pageBreakPrint page breakโ€”
inlineDatabaseEmbedded database viewdatabaseId, pageId, title
inlineWhiteboardEmbedded whiteboardpageId, title
inlinePageEmbedded page referencepageId, title, emoji, pageType
syncedBlockReusable content across pagessourceId
// Example: document with a heading, paragraph, and file attachment
{
  "type": "doc",
  "content": [
    { "type": "heading", "attrs": { "level": 1 }, "content": [{ "type": "text", "text": "Project Brief" }] },
    { "type": "paragraph", "content": [{ "type": "text", "text": "See the attached spec document below." }] },
    { "type": "fileAttachment", "attrs": { "url": "https://media.kunya.app/files/workspaces/.../spec.pdf", "fileName": "spec.pdf", "fileSize": 204800, "mimeType": "application/pdf" } },
    { "type": "image", "attrs": { "src": "https://media.kunya.app/images/uploads/.../diagram.png", "width": 600, "height": 400 } }
  ]
}
GET/v1/workspaces/pages/:id/content

Get the content body of a page.

Query Parameters

NameTypeRequiredDescription
formatstringNo"json" (default) or "markdown". Markdown converts TipTap JSON to Markdown text.

Response

NameTypeRequiredDescription
page_idstringYesPage UUID
typestringYesdocument, database, or whiteboard
formatstringYesjson or markdown
contentobject | stringYesTipTap JSON (format=json), Markdown string (format=markdown), or shapes array (whiteboard)
plain_textstringNoPlain text extraction (json format only)
word_countnumberNoWord count
# Get content as JSON
curl "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/content" \
  -H "Authorization: Bearer kunya_xxx"

# Get content as Markdown
curl "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/content?format=markdown" \
  -H "Authorization: Bearer kunya_xxx"

Database Columns

Programmatically add, update, or delete columns on a workspace database. Send a batch of operations in a single request. Column IDs are auto-generated for new columns if not provided.

PATCH/v1/workspaces/databases/:id/columns

Batch add, update, or delete columns.

Request Body

NameTypeRequiredDescription
operationsarrayYesArray of column operations (max 50)
operations[].opstringYes"add", "update", or "delete"
operations[].columnobjectNoColumn definition for "add" ops. Must have name and type.
operations[].column_idstringNoTarget column ID for "update" and "delete" ops
operations[].updatesobjectNoFields to update for "update" ops (name, type, width, options, etc.)
curl -X PATCH "https://api.kunya.app/v1/workspaces/databases/DB_ID/columns" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "operations": [
      { "op": "add", "column": { "name": "Status", "type": "select", "options": [{"label":"To Do"},{"label":"Done"}] } },
      { "op": "add", "column": { "name": "Due Date", "type": "date" } },
      { "op": "update", "column_id": "COL_ID", "updates": { "name": "Renamed Column", "width": 250 } },
      { "op": "delete", "column_id": "OLD_COL_ID" }
    ]
  }'

Space Members

Manage per-space membership. Members can be given viewer, editor, or admin roles within a space.

GET/v1/workspaces/spaces/:id/members

List all members of a space with their user details.

curl "https://api.kunya.app/v1/workspaces/spaces/SPACE_ID/members" \
  -H "Authorization: Bearer kunya_xxx"
POST/v1/workspaces/spaces/:id/members

Add a member to a space or update their role if they already exist.

Request Body

NameTypeRequiredDescription
user_idstringYesUUID of the user to add
rolestringNo"viewer", "editor" (default), or "admin"
curl -X POST "https://api.kunya.app/v1/workspaces/spaces/SPACE_ID/members" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "user_id": "USER_UUID", "role": "editor" }'
DELETE/v1/workspaces/spaces/:id/members

Remove a member from a space by member_id or user_id query param.

curl -X DELETE "https://api.kunya.app/v1/workspaces/spaces/SPACE_ID/members?user_id=USER_UUID" \
  -H "Authorization: Bearer kunya_xxx"

Bulk Pages

Create multiple pages in a single request. Supports _ref / parent_ref keys so pages within the same batch can reference each other as parents โ€” ideal for bootstrapping a project tree.

POST/v1/workspaces/pages/bulk

Create up to 100 pages in one request.

Request Body

NameTypeRequiredDescription
pagesarrayYesArray of page objects (max 100)
pages[]._refstringNoTemporary ref key for cross-referencing within this batch
pages[].parent_refstringNoReference to a _ref from another page in this batch (resolved to parent_id)
pages[].parent_idstringNoUUID of an existing parent page
pages[].space_idstringNoTarget space UUID
pages[].titlestringNoPage title (default: "Untitled")
pages[].typestringNo"document" (default), "database", or "whiteboard"
pages[].contentobjectNoInitial content (TipTap JSON or whiteboard shapes)
curl -X POST "https://api.kunya.app/v1/workspaces/pages/bulk" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "pages": [
      { "_ref": "project", "title": "Q2 Project", "space_id": "SPACE_ID" },
      { "title": "Requirements", "parent_ref": "project" },
      { "title": "Sprint Board", "parent_ref": "project", "type": "database" },
      { "title": "Architecture", "parent_ref": "project", "type": "whiteboard" }
    ]
  }'

Page AI

Run AI operations on page content โ€” generate, rewrite, summarize, translate, and more. Uses your account's AI credits.

POST/v1/workspaces/pages/:id/ai

Execute an AI operation on page content.

Request Body

NameTypeRequiredDescription
operationstringYesOne of: ai_write, ai_continue, ai_rewrite, ai_summarize, ai_translate, ai_expand, ai_shorten, ai_fix_grammar, ai_change_tone, ai_explain, ai_extract_action_items, ai_generate_outline, ai_improve
contentstringNoText to operate on. Falls back to the page's content_text if omitted.
instructionstringNoCustom instruction for ai_write or ai_rewrite
tonestringNoTarget tone for ai_change_tone (e.g., "professional", "casual")
target_languagestringNoLanguage for ai_translate (e.g., "Spanish", "Japanese")
modelstringNoAI model to use (default: gemini-3.5-flash)

Response

NameTypeRequiredDescription
resultstringYesAI-generated content
operationstringYesThe operation that was executed
modelstringYesModel used
# Summarize a page
curl -X POST "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/ai" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "operation": "ai_summarize" }'

# Translate content to Spanish
curl -X POST "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/ai" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "operation": "ai_translate", "target_language": "Spanish" }'

# Generate content from an instruction
curl -X POST "https://api.kunya.app/v1/workspaces/pages/PAGE_ID/ai" \
  -H "Authorization: Bearer kunya_xxx" \
  -H "Content-Type: application/json" \
  -d '{ "operation": "ai_write", "instruction": "Write a project kickoff agenda" }'

Workspace Webhooks

Workspace mutations from the v1 API automatically fire webhook events to your registered endpoints. Subscribe to these events in your webhook configuration.

EventFired When
workspace.page.createdA page is created (single or bulk)
workspace.page.updatedA page's content or metadata is updated
workspace.page.deletedA page is trashed or permanently deleted
workspace.database.row_createdA row is added to a database
workspace.database.row_updatedA database row is modified
workspace.database.row_deletedA database row is deleted
workspace.database.columns_updatedDatabase columns are added, updated, or deleted
workspace.whiteboard.shapes_addedShapes are added to a whiteboard via API

Webhook Payload Format

{
  "id": "evt_abc123",
  "event": "workspace.page.created",
  "timestamp": "2026-03-11T12:00:00.000Z",
  "data": {
    "page_id": "uuid",
    "title": "New Page",
    "type": "document"
  }
}

All webhook payloads include an X-Webhook-Signature header (HMAC-SHA256) for payload verification. Configure your webhook endpoint and subscribed events in the dashboard settings.

Platform

Team Management

Manage your workspace team members, roles, and invitations.

GET/api/v1/team

Get workspace info and team members.

{
  "workspace": {
    "id": "ws_abc123",
    "name": "My Workspace"
  },
  "members": [
    {
      "id": "member_001",
      "user_id": "user_abc",
      "role": "owner",
      "name": "Alice Smith",
      "email": "[email protected]",
      "joined_at": "2025-01-01T00:00:00Z"
    }
  ],
  "total_members": 5
}
POST/api/v1/team/invite

Invite a new member to the team.

// Request
{
  "email": "[email protected]",
  "role": "user"
}

// Response (201)
{
  "id": "member_002",
  "user_id": "user_bob",
  "email": "[email protected]",
  "role": "user",
  "invited_at": "2025-01-15T12:00:00Z"
}
PUT/api/v1/team/members/{id}

Update a team member's role.

// Request
{ "role": "team_admin" }

// Response
{ "success": true }

Web Fetch & Scraping

Cheap, LLM-friendly web reading. Use these instead of a full browser session whenever you just need to read (not interact with) a page. All endpoints are read-only, require the web:read scope, and cost zero credits beyond the infrastructure call.

Provider transparency. /v1/web/fetch-rendered and /v1/web/screenshot use our in-house Playwright sidecar by default. IfFIRECRAWL_API_KEY, BROWSERLESS_API_KEY,SCREENSHOTONE_ACCESS_KEY, or URLBOX_API_KEY are set on the server, they are used as fallbacks. The response always includes a provider or source field so you know which path handled your request.
POST/api/v1/web/fetch

Fetch a URL over plain HTTP and return a Readability extraction โ€” title, description, clean markdown, and a list of links. ~10โ€“50ร— cheaper than opening a browser. Use this first. If the response is tiny because the page is a JS-heavy SPA, fall back to /v1/web/fetch-rendered.

Request Body

NameTypeRequiredDescription
urlstringYesFull HTTP(S) URL to fetch.
max_charsnumberNoMax characters of markdown (500โ€“60000, default 20000).
include_linksbooleanNoInclude extracted list of links (default true).
timeout_msnumberNoRequest timeout in milliseconds (default 15000).

Example

curl -X POST https://kunya.ai/api/v1/web/fetch \
  -H "Authorization: Bearer kunya_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

Response

{
  "url": "https://example.com/",
  "statusCode": 200,
  "title": "Example Domain",
  "description": "",
  "markdown": "# Example Domain\n\nThis domain is for use in illustrative examples...",
  "text": "Example Domain This domain is for use in illustrative examples...",
  "links": [
    { "href": "https://www.iana.org/domains/example", "text": "More information..." }
  ],
  "contentType": "text/html; charset=UTF-8",
  "source": "http",
  "fetchedAt": "2026-04-16T12:34:56.000Z"
}
POST/api/v1/web/fetch-rendered

Fetch a URL with full JavaScript rendering. Uses our in-house Playwright sidecar by default; falls back to Firecrawl or Browserless if configured. Use ONLY when /v1/web/fetch returned too little content because the page is a single-page app. More expensive than /v1/web/fetch.

Request Body

NameTypeRequiredDescription
urlstringYesFull HTTP(S) URL.
wait_msnumberNoMilliseconds to wait after load (0โ€“15000, default 1500).
providerstringNo"auto" (default), "playwright", "firecrawl", or "browserless". Use "auto" unless you need to force one.

Response

Same shape as /v1/web/fetch, except source will be "rendered-playwright", "rendered-firecrawl", or "rendered-browserless".

POST/api/v1/web/screenshot

Capture a PNG screenshot of a public URL. Uses our in-house Playwright sidecar by default; falls back to ScreenshotOne, Urlbox, or Browserless if configured. Playwright and Browserless return inline base64; ScreenshotOne and Urlbox return a signed image_url you can embed directly.

Request Body

NameTypeRequiredDescription
urlstringYesFull HTTP(S) URL to screenshot.
viewportstringNo"desktop" (1440x900, default), "mobile" (390x844), or "fullpage".
wait_msnumberNoMilliseconds to wait after page load.
providerstringNo"auto", "playwright", "screenshotone", "urlbox", or "browserless".

Response (inline base64)

{
  "url": "https://example.com/",
  "provider": "playwright",
  "captured_at": "2026-04-16T12:34:56.000Z",
  "base64": "iVBORw0KGgoAAAANSUhEUgAA...",
  "mime_type": "image/png"
}

Response (signed URL)

{
  "url": "https://example.com/",
  "provider": "screenshotone",
  "captured_at": "2026-04-16T12:34:56.000Z",
  "image_url": "https://api.screenshotone.com/take?access_key=...&url=..."
}
POST/api/v1/web/pdf

Download a PDF and return extracted text plus per-page chunks. Use for research papers, RFPs, whitepapers, contracts, datasheets โ€” anything application/pdf.

Request Body

NameTypeRequiredDescription
urlstringYesFull HTTP(S) URL to the PDF.
max_charsnumberNoMax total characters of extracted text (1000โ€“200000, default 60000).
timeout_msnumberNoRequest timeout in milliseconds (default 30000).

Response

{
  "url": "https://example.com/whitepaper.pdf",
  "numPages": 12,
  "title": "Kunya Platform Whitepaper",
  "text": "Introduction\nKunya is an AI platform...",
  "pages": [
    { "pageNumber": 1, "text": "Introduction..." },
    { "pageNumber": 2, "text": "Architecture..." }
  ],
  "fetchedAt": "2026-04-16T12:34:56.000Z"
}
POST/api/v1/web/sitemap

Fetch and parse /sitemap.xml for a domain. Follows sitemap-index files automatically. Use for route enumeration, SEO audits, or QA coverage planning โ€” much cheaper than crawling.

Request Body

NameTypeRequiredDescription
urlstringYesDomain ("example.com") or full sitemap URL ("https://example.com/sitemap.xml").
max_urlsnumberNoMax URLs to return (10โ€“5000, default 500).
follow_indexbooleanNoFollow sub-sitemaps in a sitemapindex file (default true).

Response

{
  "url": "https://example.com/sitemap.xml",
  "totalUrls": 1248,
  "subSitemaps": ["https://example.com/sitemap-posts.xml", "https://example.com/sitemap-pages.xml"],
  "urls": [
    { "loc": "https://example.com/", "lastmod": "2025-12-01", "priority": 1.0 },
    { "loc": "https://example.com/pricing", "lastmod": "2025-11-22", "priority": 0.8 }
  ],
  "fetchedAt": "2026-04-16T12:34:56.000Z"
}
POST/api/v1/web/robots

Check robots.txt for a URL. Returns whether fetching is allowed for the given user-agent, the matched allow/disallow rule, crawl-delay, and any declared sitemaps. Use BEFORE a heavy fetch to avoid wasted work on disallowed paths.

Request Body

NameTypeRequiredDescription
urlstringYesFull HTTP(S) URL you intend to fetch or visit.
user_agentstringNoUser-agent token to evaluate against (default "*").

Response

{
  "url": "https://www.google.com/search",
  "robotsUrl": "https://www.google.com/robots.txt",
  "allowed": false,
  "matchedRule": { "type": "disallow", "pattern": "/search", "userAgent": "*" },
  "crawlDelay": null,
  "sitemaps": ["https://www.google.com/sitemap.xml"],
  "fetchedAt": "2026-04-16T12:34:56.000Z"
}
POST/api/v1/web/rss

Fetch and parse an RSS 2.0 or Atom feed. Returns feed metadata and normalized items with title, link, publish date, author, summary, and content.

Request Body

NameTypeRequiredDescription
urlstringYesFull HTTP(S) URL of the feed.
limitnumberNoMax items to return (1โ€“200, default 25).

Response

{
  "url": "https://news.ycombinator.com/rss",
  "feedTitle": "Hacker News",
  "feedDescription": "Links for the intellectually curious, ranked by readers.",
  "items": [
    {
      "title": "Show HN: A tiny OS in 300 lines of Rust",
      "link": "https://example.com/tiny-os",
      "pubDate": "Wed, 16 Apr 2026 09:12:34 +0000",
      "author": "user123",
      "summary": "I built a minimal Unix-like OS...",
      "content": null
    }
  ],
  "fetchedAt": "2026-04-16T12:34:56.000Z"
}

AI Utilities

POST/api/v1/ai/translate

Translate text between languages.

// Request
{
  "text": "Hello, how are you today?",
  "target_language": "Spanish",
  "source_language": "English"
}

// Response
{
  "translated_text": "Hola, ยฟcรณmo estรกs hoy?",
  "source_language": "English",
  "target_language": "Spanish",
  "cost": 0.00015
}
POST/api/v1/ai/rewrite

Rewrite text in different styles.

// Request
{
  "text": "We need to get this done ASAP",
  "style": "professional"
}

// Response
{
  "rewritten_text": "We should prioritize completing this task at your earliest convenience.",
  "style": "professional",
  "cost": 0.00012
}

// Available styles:
// professional, casual, formal, creative, concise, 
// elaborate, seo, email, social

Analytics

GET/api/v1/analytics

Get usage analytics for your account.

// GET /api/v1/analytics?period=30d
// Available periods: 7d, 30d, 90d

{
  "period": "30d",
  "total_cost": 45.50,
  "usage_by_feature": [
    {
      "feature": "chat",
      "cost": 28.00,
      "requests": 800,
      "input_tokens": 250000,
      "output_tokens": 100000
    },
    {
      "feature": "images",
      "cost": 12.00,
      "requests": 150,
      "input_tokens": 0,
      "output_tokens": 0
    }
  ],
  "generations_by_type": [
    { "type": "image", "count": 150 },
    { "type": "audio", "count": 45 },
    { "type": "video", "count": 12 }
  ]
}

Usage & Billing

GET/api/v1/usage

Get your current usage statistics and billing information.

{
  "billing": {
    "plan": "professional",
    "credits_total": 100.00,
    "credits_used": 45.50,
    "credits_remaining": 54.50,
    "overage_enabled": true,
    "period_start": "2025-01-01T00:00:00Z",
    "period_end": "2025-02-01T00:00:00Z"
  },
  "current_period": {
    "total_requests": 1250,
    "total_tokens": 458000,
    "total_cost": 45.50,
    "by_feature": [
      { "feature": "chat", "requests": 800, "tokens": 350000, "cost": 28.00 },
      { "feature": "writing", "requests": 300, "tokens": 100000, "cost": 12.50 },
      { "feature": "images", "requests": 150, "tokens": 0, "cost": 5.00 }
    ]
  },
  "daily_usage": [
    { "date": "2025-01-15", "requests": 45, "cost": 1.25 }
  ]
}

User Preferences

GET/api/v1/user/preferences

Get your account preferences.

{
  "name": "Alice Smith",
  "email": "[email protected]",
  "plan": "professional"
}
PUT/api/v1/user/preferences

Update your account preferences.

// Request
{ "name": "Alice Johnson" }

// Response
{ "success": true }

API Key Management

Manage your API keys programmatically. These endpoints require session authentication (logged in via web).

GET/api/v1/keys

List all your API keys.

{
  "keys": [
    {
      "id": "key_abc123",
      "name": "Production Key",
      "key_prefix": "kunya_ab12...",
      "is_active": true,
      "last_used_at": "2025-01-15T10:30:00Z",
      "created_at": "2025-01-01T00:00:00Z"
    }
  ]
}
POST/api/v1/keys

Create a new API key.

// Request
{ "name": "My New Key" }

// Response
{
  "id": "key_xyz789",
  "key": "kunya_aBcDeFgH...",  // Only shown once!
  "name": "My New Key",
  "created_at": "2025-01-15T12:00:00Z",
  "message": "Save this key securely. It will not be shown again."
}
DELETE/api/v1/keys/{id}

Delete an API key permanently.

curl -X DELETE https://kunya.ai/api/v1/keys/key_xyz789 \
  -H "Cookie: session=..."

SDKs & Libraries

Official SDKs are coming soon! In the meantime, you can use any HTTP client to interact with the API.

๐Ÿ“ฆ

JavaScript/TypeScript

Coming Soon
๐Ÿ

Python

Coming Soon
๐Ÿ”ท

Go

Planned
๐Ÿ’Ž

Ruby

Planned

Quick Start Example (JavaScript)

// Using fetch
async function chat(message) {
  const response = await fetch('https://kunya.ai/api/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer kunya_YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      messages: [{ role: 'user', content: message }],
      model: 'claude-sonnet-4.6',
      stream: false,
    }),
  });
  
  const data = await response.json();
  return data.choices[0].message.content;
}

// Usage
const reply = await chat('What is the meaning of life?');
console.log(reply);

Quick Start Example (Python)

import requests

def chat(message: str) -> str:
    response = requests.post(
        'https://kunya.ai/api/v1/chat/completions',
        headers={
            'Authorization': 'Bearer kunya_YOUR_API_KEY',
            'Content-Type': 'application/json',
        },
        json={
            'messages': [{'role': 'user', 'content': message}],
            'model': 'claude-sonnet-4.6',
            'stream': False,
        }
    )
    data = response.json()
    return data['choices'][0]['message']['content']

# Usage
reply = chat('What is the meaning of life?')
print(reply)

Support

Tickets

POST/api/v1/support/tickets

Create a support ticket.

{
  "subject": "Cannot access my account",
  "description": "I've been locked out since yesterday...",
  "requester_email": "[email protected]",
  "requester_name": "Jane Smith",
  "priority": "high",
  "channel": "email",
  "tags": ["login", "urgent"]
}
GET/api/v1/support/tickets

List tickets with filtering, search, and pagination.

curl -H "Authorization: Bearer kunya_YOUR_KEY" \
  "https://kunya.ai/api/v1/support/tickets?status=open&priority=high&q=login&limit=50"
GET/api/v1/support/tickets/:id

Get full ticket details including comments, customer, SLA, and AI analysis.

curl -H "Authorization: Bearer kunya_YOUR_KEY" \
  "https://kunya.ai/api/v1/support/tickets/TICKET_ID"
PUT/api/v1/support/tickets/:id

Update ticket fields (status, priority, category, tags, assignment).

{
  "status": "pending",
  "priority": "urgent",
  "assigned_user_id": "user_uuid",
  "tags": ["escalated"]
}
DELETE/api/v1/support/tickets/:id

Delete a ticket.

POST/api/v1/support/tickets/:id/merge

Merge another ticket into this one. Moves all comments and closes the source.

{ "source_ticket_id": "ticket_uuid_to_merge" }
POST/api/v1/support/tickets/bulk

Bulk update up to 100 tickets at once.

{
  "ticket_ids": ["id1", "id2", "id3"],
  "updates": { "status": "solved", "tags": ["resolved"] }
}
POST/api/v1/support/tickets/import

Bulk import tickets from external systems (e.g. Zendesk migration). Up to 100 per request. Deduplicates by external_id.

{
  "tickets": [
    {
      "external_id": "zen_12345",
      "subject": "Login not working",
      "requester_email": "[email protected]",
      "requester_name": "Jane Doe",
      "status": "solved",
      "priority": "high",
      "channel": "email",
      "tags": ["login"],
      "created_at": "2025-06-15T10:30:00Z",
      "comments": [
        { "author_type": "customer", "body": "I can't log in.", "created_at": "2025-06-15T10:30:00Z" },
        { "author_type": "agent", "author_name": "Support", "body": "Fixed!", "created_at": "2025-06-15T14:00:00Z" }
      ]
    }
  ],
  "skip_duplicates": true
}

Ticket Comments

GET/api/v1/support/tickets/:id/comments

List all comments on a ticket (chronological).

POST/api/v1/support/tickets/:id/comments

Add a public reply or internal note.

{
  "body": "Thanks for reaching out. I've looked into this...",
  "is_public": true,
  "author_type": "user",
  "author_name": "Support Agent"
}

Ticket Events (Audit Trail)

GET/api/v1/support/tickets/:id/events

Get the complete audit trail for a ticket with all field changes.

Ticket Metrics

GET/api/v1/support/tickets/:id/metrics

Get SLA and performance metrics: reply time, resolution time, agent replies, reopens, breaches.

Satisfaction Ratings

GET/api/v1/support/tickets/:id/satisfaction

Get the CSAT rating for a ticket.

POST/api/v1/support/tickets/:id/satisfaction

Submit a satisfaction rating.

{ "score": 5, "comment": "Great support!", "customer_id": "customer_uuid" }

Side Conversations

GET/api/v1/support/tickets/:id/side-conversations

List internal collaboration threads on a ticket.

POST/api/v1/support/tickets/:id/side-conversations

Create a side conversation for internal discussion.

{
  "subject": "Need input from engineering",
  "channel_type": "internal",
  "initial_message": "Can you check if this is a known bug?"
}
GET/api/v1/support/tickets/:id/side-conversations/:scId/messages

List messages in a side conversation.

POST/api/v1/support/tickets/:id/side-conversations/:scId/messages

Add a message to a side conversation.

Followers

GET/api/v1/support/tickets/:id/followers

List users following a ticket.

POST/api/v1/support/tickets/:id/followers

Add a follower.

{ "user_id": "user_uuid" }
DELETE/api/v1/support/tickets/:id/followers?user_id=uuid

Remove a follower.

Customers

GET/api/v1/support/customers

List customers with search and pagination.

POST/api/v1/support/customers

Create a customer (email or phone required).

{
  "email": "[email protected]",
  "name": "John Customer",
  "company": "Acme Corp",
  "organization_id": "org_uuid",
  "tags": ["vip"],
  "custom_fields": { "plan": "enterprise" }
}
GET/api/v1/support/customers/:id

Get customer details with organization and recent tickets.

PUT/api/v1/support/customers/:id

Update customer fields.

DELETE/api/v1/support/customers/:id

Delete a customer (blocked if open tickets exist).

GET/api/v1/support/customers/:id/tickets

List a customer's tickets.

Organizations

GET/api/v1/support/organizations

List organizations.

POST/api/v1/support/organizations

Create an organization.

{
  "name": "Acme Corp",
  "domains": ["acme.com", "acme.io"],
  "shared_tickets": true,
  "tags": ["enterprise"]
}
GET/api/v1/support/organizations/:id

Get organization with customer count.

PUT/api/v1/support/organizations/:id

Update organization.

DELETE/api/v1/support/organizations/:id

Delete organization.

Agent Groups

GET/api/v1/support/groups

List agent groups.

POST/api/v1/support/groups

Create a group.

{ "name": "Tier 1 Support", "description": "First-line support team" }
GET/api/v1/support/groups/:id

Get group with member list.

POST/api/v1/support/groups/:id/members

Add a member to a group.

{ "user_id": "user_uuid", "role": "member" }
DELETE/api/v1/support/groups/:id/members?user_id=uuid

Remove a member from a group.

Tags

GET/api/v1/support/tags

List all tags with usage counts.

POST/api/v1/support/tags

Create a tag.

{ "name": "billing", "color": "#FF5733" }

Macros

GET/api/v1/support/macros

List macros (filter by is_personal, user_id).

POST/api/v1/support/macros

Create a macro with actions.

{
  "name": "Close and Thank",
  "actions": [
    { "type": "add_comment", "value": { "body": "Thanks for contacting us!", "is_public": true } },
    { "type": "set_status", "value": "solved" },
    { "type": "add_tags", "value": ["resolved"] }
  ]
}

Action types: set_status, set_priority, set_assignee, set_group, add_tags, remove_tags, add_comment.

POST/api/v1/support/macros/:id/apply

Apply a macro to a ticket. Executes all actions and creates an audit event.

{ "ticket_id": "ticket_uuid" }

Triggers

Event-based automation rules that fire on ticket creation or update.

GET/api/v1/support/triggers

List triggers.

POST/api/v1/support/triggers

Create a trigger.

{
  "name": "Auto-assign billing tickets",
  "event_type": "ticket_created",
  "conditions": {
    "all": [{ "field": "category", "operator": "is", "value": "billing" }]
  },
  "actions": [
    { "type": "set_group", "field": "group_id", "value": "billing_group_uuid" },
    { "type": "set_priority", "field": "priority", "value": "high" }
  ]
}
GET/api/v1/support/triggers/:id

Get trigger with execution stats.

PUT/api/v1/support/triggers/:id

Update trigger conditions, actions, or status.

DELETE/api/v1/support/triggers/:id

Delete a trigger.

Automations

Time-based rules that run on a schedule.

POST/api/v1/support/automations

Create an automation.

{
  "name": "Follow up on stale tickets",
  "conditions": {
    "all": [
      { "field": "status", "operator": "is", "value": "pending" },
      { "field": "hours_since_updated", "operator": "greater_than", "value": 48 }
    ]
  },
  "actions": [
    { "type": "add_comment", "value": { "body": "Just checking in..." } },
    { "type": "set_status", "value": "open" }
  ]
}

Views

Saved ticket queries with configurable columns and sorting.

POST/api/v1/support/views

Create a view.

{
  "name": "My urgent tickets",
  "conditions": {
    "all": [{ "field": "priority", "operator": "is", "value": "urgent" }],
    "any": [
      { "field": "status", "operator": "is", "value": "new" },
      { "field": "status", "operator": "is", "value": "open" }
    ]
  },
  "columns": ["subject", "requester", "status", "priority", "updated_at"],
  "sort_by": "created_at",
  "sort_order": "desc"
}

Operators: is, is_not, contains, not_contains, greater_than, less_than, present, not_present. Fields: status, priority, channel, category, assigned_user_id, group_id, tags, created_at, updated_at.

GET/api/v1/support/views/:id/tickets

Execute a view and return matching tickets with pagination.

GET/api/v1/support/views/:id/count

Return just the ticket count for a view.

SLA Policies

POST/api/v1/support/slas

Create an SLA policy (targets in minutes).

{
  "name": "Urgent SLA",
  "first_response_target": 30,
  "resolution_target": 240,
  "conditions": { "priority": ["urgent", "high"] },
  "priority": 10
}
GET/api/v1/support/slas

List SLA policies (ordered by priority).

Queues

POST/api/v1/support/queues

Create a routing queue.

{
  "name": "Billing Queue",
  "routing_rules": [
    { "conditions": { "category": "billing" }, "assign_to_group": "group_uuid" }
  ],
  "default_sla_id": "sla_uuid"
}

Business Hours

POST/api/v1/support/business-hours

Create a business hours schedule.

{
  "name": "US Business Hours",
  "timezone": "America/New_York",
  "schedule": {
    "monday": { "start": "09:00", "end": "17:00" },
    "friday": { "start": "09:00", "end": "17:00" }
  },
  "holidays": [{ "date": "2025-12-25", "name": "Christmas" }]
}

Brands

Multi-brand support for different customer-facing identities.

POST/api/v1/support/brands

Create a brand.

{
  "name": "Acme Support",
  "subdomain": "acme",
  "support_email": "[email protected]",
  "brand_color": "#3B82F6",
  "help_center_enabled": true
}

Channels

POST/api/v1/support/channels

Configure a support channel.

{
  "name": "Main Support Email",
  "channel_type": "email",
  "config": { "email_address": "[email protected]" },
  "brand_id": "brand_uuid"
}

Custom Ticket Fields

POST/api/v1/support/ticket-fields

Create a custom field.

{
  "name": "Product Line",
  "key": "product_line",
  "field_type": "select",
  "options": [
    { "label": "Enterprise", "value": "enterprise" },
    { "label": "Starter", "value": "starter" }
  ],
  "is_required": true,
  "visible_to_customers": true
}

Field types: text, textarea, number, decimal, checkbox, date, select, multiselect, regex.

Ticket Forms

POST/api/v1/support/ticket-forms

Create a ticket form (collection of fields).

{
  "name": "Billing Issue Form",
  "field_ids": ["field_uuid_1", "field_uuid_2"],
  "is_default": false
}
GET/api/v1/support/ticket-forms/:id

Get form with resolved field details.

Help Center

Knowledge base with categories, sections, articles, voting, and search.

POST/api/v1/support/help-center/categories

Create an article category.

{ "name": "Getting Started", "description": "Learn the basics", "icon": "BookOpen" }
POST/api/v1/support/help-center/sections

Create a section within a category.

{ "name": "Account Setup", "category_id": "cat_uuid" }
POST/api/v1/support/help-center/articles

Create an article.

{
  "title": "How to reset your password",
  "body": "# Reset Your Password\n\nFollow these steps...",
  "section_id": "section_uuid",
  "status": "published",
  "labels": ["password", "account"],
  "promoted": true
}
GET/api/v1/support/help-center/search?q=password+reset

Full-text search with tsvector ranking, title boosting, and highlighted snippets.

POST/api/v1/support/help-center/articles/:id/votes

Vote on an article.

{ "value": 1 }
GET/api/v1/support/help-center/articles/:id/translations

List all translations of an article. Returns source + linked translations with locales.

POST/api/v1/support/help-center/articles/:id/translations

Create a translation of an article. Links via shared translation_group_id.

{
  "locale": "fr",
  "title": "Guide de rรฉinitialisation du mot de passe",
  "body": "Si vous avez oubliรฉ votre mot de passe...",
  "status": "draft"
}

AI Features

AI-powered ticket analysis, response generation, and intelligence.

POST/api/v1/support/ai/triage

AI-powered ticket triage. Returns priority, category, sentiment, language, tags, summary, and intent.

{ "ticket_id": "ticket_uuid" }

Also accepts raw text: { subject, description }

POST/api/v1/support/ai/suggest-response

Generate an AI-suggested reply for a ticket.

{ "ticket_id": "ticket_uuid", "tone": "empathetic", "language": "en" }
POST/api/v1/support/ai/summarize

Summarize a ticket's conversation. Returns summary, key_points, and action_items.

{ "ticket_id": "ticket_uuid" }
POST/api/v1/support/ai/sentiment

Analyze sentiment from text or a ticket.

{ "text": "This is unacceptable. I've been waiting for days!" }
POST/api/v1/support/ai/detect-intent

Detect customer intent. Returns intent, sub_intent, confidence, and entities.

{ "ticket_id": "ticket_uuid" }

Support Analytics

GET/api/v1/support/analytics/overview

Dashboard-level ticket analytics: totals, averages, CSAT, breakdowns by status/priority/channel.

curl -H "Authorization: Bearer kunya_YOUR_KEY" \
  "https://kunya.ai/api/v1/support/analytics/overview?start_date=2025-01-01&end_date=2025-01-31"
GET/api/v1/support/analytics/agents

Per-agent performance: tickets assigned, solved, avg response/resolution time, CSAT.

GET/api/v1/support/analytics/sla

SLA compliance: first response/resolution breach rates and overall compliance.

Support Webhooks

Subscribe to support events for real-time integrations.

POST/api/v1/support/webhooks

Create a webhook subscription. HMAC secret returned once on creation.

{
  "name": "Slack Integration",
  "url": "https://hooks.slack.com/services/...",
  "events": ["ticket.created", "ticket.updated", "ticket.solved", "comment.added", "csat.received"]
}
GET/api/v1/support/webhooks/:id

Get webhook with recent delivery log.

GET/api/v1/support/webhooks/:id/deliveries

Paginated delivery history.

POST/api/v1/support/webhooks/:id/test

Send a test webhook delivery.

Trigger & Automation Engine

Triggers fire automatically when ticket events occur (create, update, comment). Automations run on a cron schedule evaluating time-based conditions. Both support the same action types. Triggers are wired into the ticket create, update, and comment endpoints โ€” no separate API call needed.

How It Works

  • 1. Define triggers/automations via the existing CRUD endpoints
  • 2. When a ticket is created/updated or a comment is added, all matching triggers evaluate automatically
  • 3. Actions execute: set status, set priority, assign agent/group, add/remove tags, add comment, send email
  • 4. Automations run every 5 minutes via cron, evaluating time-based conditions (hours since created, updated, etc.)
  • 5. Cycle detection prevents infinite loops (max 10 trigger executions per event)
GET/api/cron/support-automations

Cron endpoint that evaluates time-based automations. Runs every 5 minutes. Requires CRON_SECRET authorization.

# Vercel cron runs automatically
# Manual trigger:
curl -H "Authorization: Bearer YOUR_CRON_SECRET" \
  https://api.kunya.ai/api/cron/support-automations
Trigger Condition Example
{
  "conditions": {
    "all": [
      { "field": "status", "operator": "is", "value": "new" },
      { "field": "priority", "operator": "is", "value": "urgent" }
    ],
    "any": [
      { "field": "tags", "operator": "contains", "value": "vip" }
    ]
  },
  "actions": [
    { "type": "set_assignee", "value": "agent-uuid" },
    { "type": "add_tags", "value": ["escalated"] },
    { "type": "send_email", "value": { "to": "[email protected]", "subject": "Urgent VIP ticket", "body": "A VIP ticket needs attention." } }
  ]
}

Supported Operators

is, is_not, contains, not_contains, greater_than, less_than, present, not_present, changed, changed_to, changed_from

Automation Time Conditions

hours_since_created, hours_since_updated, hours_since_status_change, hours_since_assignee_change

Email Integration

Full email channel support: inbound email creates tickets, agent replies send emails to customers, and email threading works via In-Reply-To headers.

POST/api/v1/support/inbound-email

SendGrid Inbound Parse webhook. Emails to your support address automatically create tickets or add comments to existing threads.

SendGrid Setup
# 1. Configure SendGrid Inbound Parse:
#    - Domain: support.yourdomain.com
#    - URL: https://api.kunya.ai/api/v1/support/inbound-email
#
# 2. Set MX records for support.yourdomain.com -> mx.sendgrid.net
#
# 3. (Optional) Set INBOUND_EMAIL_SECRET env var for webhook verification
#
# Inbound emails are parsed and:
# - If replying to existing ticket (via In-Reply-To header or [#123] in subject):
#   โ†’ Adds customer comment, reopens if pending/solved
# - If new email:
#   โ†’ Creates customer + ticket with channel='email'
#   โ†’ Sends confirmation email to customer

Automatic Email Triggers

  • โ†’ Agent replies: Public comments auto-send email to the customer via SendGrid
  • โ†’ Ticket created: Customer receives confirmation email with ticket number
  • โ†’ Ticket solved: CSAT survey email sent automatically with 1-5 rating links
  • โ†’ Threading: Reply-To headers use support+ticket-UUID@domain for automatic threading

Customer Portal API

End-customer facing API with email-based authentication. Customers can submit tickets, track status, reply to conversations, rate satisfaction, and browse help center articles โ€” all without an API key.

POST/api/v1/support/portal/auth

Request a portal access code via email. Send workspace_id and customer email.

{
  "email": "[email protected]",
  "workspace_id": "ws_xxx"
}
POST/api/v1/support/portal/auth/verify

Verify the 6-digit code and receive a 30-day portal token.

{
  "email": "[email protected]",
  "workspace_id": "ws_xxx",
  "code": "482913"
}
// Response:
{
  "token": "kunya_portal_abc123...",
  "expires_at": "2026-04-03T00:00:00Z",
  "customer": { "id": "...", "name": "...", "email": "..." }
}
GET/api/v1/support/portal/tickets

List the customer's own tickets. Auth: Bearer portal token.

curl -H "Authorization: Bearer kunya_portal_abc123..." \
  https://api.kunya.ai/api/v1/support/portal/tickets
POST/api/v1/support/portal/tickets

Submit a new ticket as an end-customer.

{
  "subject": "I can't reset my password",
  "description": "When I click the reset link, it shows a 404 error.",
  "priority": "normal"
}
GET/api/v1/support/portal/tickets/:id

Get ticket detail with public comments (ownership enforced).

GET/api/v1/support/portal/tickets/:id/comments

List public comments on a ticket.

POST/api/v1/support/portal/tickets/:id/comments

Customer adds a reply to their ticket.

POST/api/v1/support/portal/tickets/:id/rate

Submit satisfaction rating (1-5 score + optional comment).

{ "score": 5, "comment": "Fast and helpful!" }
GET/api/v1/support/portal/articles

Browse published help center articles. No auth required, pass workspace_id as query param.

# Browse by category
curl "https://api.kunya.ai/api/v1/support/portal/articles?workspace_id=ws_xxx&category=getting-started"

# Full-text search
curl "https://api.kunya.ai/api/v1/support/portal/articles?workspace_id=ws_xxx&q=password+reset"

Real-Time Events (SSE)

Server-Sent Events stream for live ticket updates. Subscribe to real-time ticket events without polling โ€” agent comments, status changes, assignments, and more push to connected clients.

GET/api/v1/support/events/stream

SSE stream of ticket events. Supports reconnection via the 'since' parameter.

Client-Side Usage
const eventSource = new EventSource(
  'https://api.kunya.ai/api/v1/support/events/stream?since=2026-03-01T00:00:00Z',
  { headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);

eventSource.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Ticket event:', data);
  // {
  //   id: "event-uuid",
  //   ticket_id: "ticket-uuid",
  //   event_type: "status_changed",
  //   actor_type: "agent",
  //   actor_name: "John Doe",
  //   changes: { status: { from: "open", to: "solved" } },
  //   created_at: "2026-03-03T14:30:00Z"
  // }
};

// Reconnect with last event ID for seamless recovery
eventSource.onerror = () => {
  // EventSource auto-reconnects; use 'since' param with last received timestamp
};

Stream Behavior

  • โ€ข Polls every 2 seconds for new events
  • โ€ข Sends keepalive comments every ~15 seconds
  • โ€ข Auto-closes after ~50 seconds (reconnect with since param)
  • โ€ข Returns events scoped to your workspace

Community Forum

Full community Q&A forum with threaded comments, voting, pinning, locking, and best-answer selection.

GET/api/v1/support/community/posts

List forum posts with filtering and sorting.

# Filter by type, sort by votes
curl -H "X-API-Key: KEY" \
  "https://api.kunya.ai/api/v1/support/community/posts?post_type=question&sort=upvotes&topic_id=xxx"
POST/api/v1/support/community/posts

Create a forum post.

{
  "title": "How do I integrate with the billing API?",
  "body": "I'm trying to connect Stripe webhooks but...",
  "post_type": "question",
  "topic_id": "category-uuid"
}
GET/api/v1/support/community/posts/:id

Get post with comments. Auto-increments view count.

PUT/api/v1/support/community/posts/:id

Update post (title, body, status, is_pinned, is_locked, best_answer_id).

DELETE/api/v1/support/community/posts/:id

Delete a forum post and all its comments.

GET/api/v1/support/community/posts/:id/comments

Threaded comments on a post (supports parent_id for replies).

POST/api/v1/support/community/posts/:id/comments

Add a comment to a post.

{ "body": "Try checking the webhook signature...", "parent_id": "comment-uuid" }
POST/api/v1/support/community/posts/:id/votes

Vote on a post (+1 or -1). Handles vote flipping.

POST/api/v1/support/community/comments/:id/votes

Vote on a comment (+1 or -1).

Agent Presence & Collision Detection

Real-time agent presence tracking. See who is viewing or editing a ticket to prevent conflicts. Agents heartbeat their activity; stale entries expire after 60 seconds.

POST/api/v1/support/presence

Heartbeat โ€” report that an agent is viewing a ticket. Call every 30 seconds.

{ "ticket_id": "ticket-uuid", "activity": "viewing" }
GET/api/v1/support/presence

List all active agents across tickets. Filter by ticket_id.

DELETE/api/v1/support/presence

Agent leaves a ticket. Pass ticket_id as query param.

GET/api/v1/support/presence/ticket/:id

Who is currently viewing this specific ticket?

Agent Availability & Routing

Manage agent online/offline/away status for intelligent ticket routing. Supports capacity limits, skills-based filtering, and channel-specific availability.

GET/api/v1/support/agents/status

List agent availability statuses. Filter by status, skill, channel, or online_only.

curl -H "Authorization: Bearer kunya_YOUR_KEY" \
  "https://kunya.ai/api/v1/support/agents/status?status=online&skill=billing&online_only=true"
POST/api/v1/support/agents/status

Set or update your agent status (idempotent upsert). Valid: online, away, busy, offline.

{
  "status": "online",
  "status_message": "Available for chats",
  "max_capacity": 10,
  "skills": ["billing", "technical", "refunds"],
  "channels": ["chat", "email", "phone"]
}
PUT/api/v1/support/agents/status

Alias for POST โ€” same upsert behavior.

Scheduled Report Exports

Schedule recurring report exports delivered via email as CSV. Supports overview, agent, SLA, CSAT, and raw ticket exports with custom filters and frequencies.

GET/api/v1/support/exports

List all scheduled exports for the workspace.

POST/api/v1/support/exports

Create a scheduled export.

{
  "name": "Weekly Ticket Overview",
  "report_type": "overview",
  "frequency": "weekly",
  "format": "csv",
  "recipient_emails": ["[email protected]", "[email protected]"],
  "filters": { "priority": "urgent" }
}
GET/api/v1/support/exports/:id

Get export details.

PUT/api/v1/support/exports/:id

Update an export schedule.

DELETE/api/v1/support/exports/:id

Delete a scheduled export.

POST/api/v1/support/exports/:id/run

Manually trigger an export now. Generates the report, builds CSV, and emails to recipients.

# Report types: overview, agents, sla, csat, tickets
# Overview: ticket counts by status, priority, channel
# Agents: per-agent resolution stats
# SLA: breach rates and compliance
# CSAT: satisfaction scores breakdown
# Tickets: full ticket list with all fields

Agent Roles & Permissions

Granular role-based access control for support agents. Define custom permission sets and assign them to team members.

GET/api/v1/support/roles

List all agent roles.

POST/api/v1/support/roles

Create a custom role.

{
  "name": "Senior Agent",
  "description": "Can manage tickets and view reports",
  "permissions": {
    "tickets": { "view": "all", "create": true, "update": true, "delete": false },
    "customers": { "view": true, "create": true, "update": true, "delete": false },
    "reports": { "view": true },
    "admin": { "manage_triggers": false, "manage_slas": false, "manage_roles": false }
  }
}
GET/api/v1/support/roles/:id

Get role with assigned user count.

PUT/api/v1/support/roles/:id

Update role permissions.

DELETE/api/v1/support/roles/:id

Delete a role (built-in roles protected).

GET/api/v1/support/roles/:id/assignments

List users assigned to this role.

POST/api/v1/support/roles/:id/assignments

Assign a user to a role.

{ "user_id": "user-uuid" }
DELETE/api/v1/support/roles/:id/assignments

Remove a user from a role. Pass user_id as query param.

Voice Integration

Hooks for connecting the voice agent API to the support platform. When the voice API is ready, it calls these endpoints to create/update tickets from phone calls.

POST/api/v1/support/voice/create-from-call

Create a support ticket from a phone call. Auto-creates customer by phone number.

{
  "call_id": "call-uuid",
  "caller_phone": "+1234567890",
  "caller_name": "Jane Doe",
  "subject": "Billing question",
  "description": "Customer called about a charge on their account.",
  "transcript": "Agent: Hello, how can I help?\nCaller: I see a charge...",
  "agent_id": "voice-agent-uuid",
  "priority": "normal"
}
POST/api/v1/support/voice/update-from-call

Add a call interaction to an existing ticket.

{
  "ticket_id": "ticket-uuid",
  "call_id": "call-uuid",
  "transcript": "Follow-up call transcript...",
  "summary": "Customer confirmed the issue is resolved.",
  "resolution": "solved"
}

Blog & SEO

Manage blog posts, generate AI content, track analytics, and optimize SEO across all your applications. All blog endpoints use your API key for authentication.

Posts CRUD

GET/api/v1/blog/posts

List all blog posts with optional filtering by status, category, and pagination.

Example
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://kunya.ai/api/v1/blog/posts?status=published&limit=20&offset=0"
POST/api/v1/blog/posts

Create a new blog post with title, content, SEO metadata, and publishing options.

{
  "title": "Your Article Title",
  "html_content": "<p>Article HTML content...</p>",
  "excerpt": "Short summary for previews",
  "category": "AI Tools",
  "tags": ["ai", "tools", "productivity"],
  "focus_keyword": "ai tools",
  "meta_title": "Best AI Tools 2026",
  "meta_description": "Discover the best AI tools...",
  "status": "draft",
  "locale": "en"
}
GET/api/v1/blog/posts/:id

Get a single post with full content and metadata.

PUT/api/v1/blog/posts/:id

Update an existing post's content, metadata, or status.

DELETE/api/v1/blog/posts/:id

Delete a blog post permanently.

AI Generation

POST/api/v1/blog/ai/generate-article

Generate a complete blog article with SEO optimization, competitive analysis, and voice profile matching.

{
  "title": "How to Use AI for Content Marketing",
  "brief": "Guide on leveraging AI tools for marketing",
  "model": "claude-sonnet-4.6",
  "target_length": "medium",
  "tone": "professional",
  "voice_profile_id": "optional-uuid",
  "seo_keywords": ["ai content marketing", "ai writing tools"],
  "include_faq": true,
  "include_examples": true
}
POST/api/v1/blog/ai/generate-paragraph

Generate or edit paragraphs within an article. Modes: continue, grammar, seo.

{
  "context": "<p>Existing article content...</p>",
  "title": "Article Title",
  "model": "claude-sonnet-4.6",
  "paragraph_count": 3,
  "edit_mode": "continue",
  "voice_profile_id": "optional-uuid"
}

Bulk Generation

POST/api/v1/blog/ai/bulk-generate

Start a bulk article generation task. The AI plans and writes multiple articles based on your objective. Returns a task ID for progress tracking.

{
  "objective": "Write 5 articles about AI productivity tools",
  "instructions": "Target 1200 words each, professional tone",
  "model": "claude-sonnet-4.6",
  "image_model": "gpt-image-2",
  "image_strategy": "ai_generated",
  "voice_profile_id": "optional-uuid",
  "auto_publish": false
}

Response includes task_id โ€” poll GET /api/v1/blog/tasks/:id for progress.

Batch Section Edit

POST/api/v1/blog/batch-edit

Surgically edit specific sections across many articles at once. The AI applies only the relevant parts of the instruction to each article โ€” articles that don't match are skipped automatically. Streams progress as NDJSON.

{
  "edit_instruction": "Update the Pricing section: GPT-4o input is now $3.25/M tokens, output $13/M tokens",
  "filter": {
    "destination": "models",
    "status": "published",
    "category": "AI Models",
    "locale": "en",
    "post_ids": ["uuid-1", "uuid-2"],
    "search_query": "GPT"
  },
  "model": "gpt-5-mini",
  "dry_run": false
}

All filter fields are optional. Use post_ids to target specific articles, or combine destination / status / category to filter broadly. Set dry_run: true to preview changes without saving.

Streaming Response (NDJSON โ€” one JSON object per line)
{ "type": "start", "total_posts": 12, "dry_run": false, "model": "gpt-5-mini" }
{ "type": "progress", "post_id": "uuid", "title": "GPT-4o Overview", "status": "edited", "changed": true, "diff": { "before": "...", "after": "..." } }
{ "type": "progress", "post_id": "uuid", "title": "Claude Overview", "status": "skipped", "changed": false }
{ "type": "done", "summary": { "total": 12, "edited": 3, "skipped": 8, "failed": 1 }, "dry_run": false }

Progress status values: processing, edited, skipped, failed. When dry_run is true, status is would_edit instead of edited.

Tasks & Progress

GET/api/v1/blog/tasks

List all blog agent tasks with status, progress, and results.

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://kunya.ai/api/v1/blog/tasks?status=running&limit=10"
GET/api/v1/blog/tasks/:id

Get detailed task info including subtasks, progress percentage, and results.

Response
{
  "data": {
    "id": "task-uuid",
    "status": "completed",
    "progress": 100,
    "total_steps": 5,
    "current_step": 5,
    "result_summary": "Done: 5 articles created, 0 failed.",
    "subtasks": [
      { "id": "...", "objective": "Article Title", "status": "completed", "result_summary": "1200 words + AI cover image" }
    ]
  }
}

Analytics

GET/api/v1/blog/analytics/:post_id

Get analytics for a specific post: unique views, scroll depth, read completion, time on page, and search metrics.

Response
{
  "data": {
    "post_id": "uuid",
    "unique_views": 342,
    "avg_scroll_depth": 76,
    "read_complete_rate": 45,
    "avg_time_on_page_seconds": 187,
    "search_metrics": [
      { "query": "ai writing tools", "impressions": 1200, "clicks": 89, "position": 4.2 }
    ]
  }
}

Sitemap

GET/api/v1/blog/sitemap

Get sitemap data as JSON for building custom sitemaps in sister applications.

Response
{
  "data": {
    "total": 42,
    "entries": [
      {
        "slug": "ai-content-marketing-guide",
        "title": "AI Content Marketing Guide",
        "locale": "en",
        "last_modified": "2026-03-01T12:00:00Z",
        "urls": {
          "en": "https://kunya.ai/blog/ai-content-marketing-guide",
          "pl": "https://kunya.pl/blog/ai-content-marketing-guide"
        }
      }
    ]
  }
}

Settings

GET/api/v1/blog/settings

Get blog layout and display settings for your workspace.

PUT/api/v1/blog/settings

Update blog settings: layout, fonts, sidebar, TOC, social share options, and more.

{
  "show_table_of_contents": true,
  "toc_position": "sidebar",
  "posts_per_page": 12,
  "show_social_share": true,
  "show_related_posts": true
}

AI Editor Chat

POST/api/v1/blog/ai/chat

Streaming AI chat for interactive blog content writing. Supports voice profiles, web search enrichment, and editor context. Returns text/event-stream.

{
  "messages": [
    { "role": "user", "content": "Write an introduction about AI in healthcare" }
  ],
  "model": "claude-sonnet-4.6",
  "article_title": "AI in Healthcare: A Complete Guide",
  "editor_content": "<p>Current article HTML...</p>",
  "voice_profile_id": "optional-uuid",
  "enable_web_search": true
}

Response is a streaming text body. Consume as a readable stream.

Blog Image Generation

POST/api/v1/blog/ai/generate-image

Generate cover images, illustrations, or infographics for blog posts. Enhances prompts with blog-specific context.

{
  "prompt": "A futuristic AI-powered content creation workspace",
  "model": "gpt-image-2",
  "type": "cover",
  "style": "professional",
  "quality": "medium",
  "article_title": "The Future of AI Content"
}
Response
{
  "data": {
    "url": "https://...",
    "revised_prompt": "...",
    "model": "gpt-image-2",
    "type": "cover",
    "style": "professional",
    "cost": 0.053
  }
}

Strategy Chat

POST/api/v1/blog/strategy-chat

Agentic strategy chat. The Blog Strategist AI analyzes your blog performance, suggests content ideas, creates agent tasks, and saves planned articles. Uses internal tool calling (up to 8 rounds).

{
  "messages": [
    { "role": "user", "content": "Analyze my blog's SEO health and suggest improvements" }
  ],
  "model": "gemini-3.5-flash"
}
Response
{
  "data": {
    "content": "## Blog SEO Analysis\n\nI analyzed your 24 articles...\n\n### Issues Found\n- 8 articles missing meta descriptions\n- 3 articles with 'Uncategorized' category...",
    "model": "gemini-3.5-flash"
  }
}

The strategist has tools to list articles, search, get stats, suggest ideas, save planned articles, and create agent tasks โ€” all executed automatically during the conversation.

Translate

POST/api/v1/blog/posts/:id/translate

Translate a blog post to another language. Creates a new draft with translated content and SEO metadata. Returns streaming NDJSON progress.

{
  "target_locale": "pl",
  "model": "gemini-3.5-flash"
}
Streaming Response (NDJSON)
{"step":"metadata","progress":15,"message":"Translating metadata to polski..."}
{"step":"content","progress":40,"message":"Translating content (~1200 words)..."}
{"step":"complete","progress":100,"done":true,"id":"new-post-uuid","title":"Translated Title","locale":"pl"}

Duplicate

POST/api/v1/blog/posts/:id/duplicate

Create a copy of a blog post. The copy is saved as draft with '(Copy)' appended to the title.

Response
{
  "data": {
    "id": "new-post-uuid",
    "slug": "original-slug-copy",
    "title": "Original Title (Copy)",
    "status": "draft"
  }
}

Categories

GET/api/v1/blog/categories

List all blog categories for your workspace.

POST/api/v1/blog/categories

Create a new blog category.

{
  "name": "AI Tools",
  "description": "Reviews and guides for AI tools",
  "color": "#7c3aed",
  "sort_order": 1
}
GET/api/v1/blog/categories/:id

Get a single category by ID.

PUT/api/v1/blog/categories/:id

Update a category's name, description, color, or sort order.

DELETE/api/v1/blog/categories/:id

Delete a category. Fails if posts are assigned to it.

Strategy Tasks

POST/api/v1/blog/agent/strategy

Create a content strategy agent task. The marketing agent analyzes your blog and creates an actionable content plan.

{
  "objective": "Plan Q2 content calendar for AI productivity",
  "timeframe": "Q2 2026",
  "focus_areas": ["AI writing", "automation", "SEO"],
  "target_audience": "Small business marketers"
}

Returns a task_id โ€” poll GET /api/v1/blog/tasks/:id for progress.

Templates

GET/api/v1/blog/templates

List blog layout templates (your own + public ones).

POST/api/v1/blog/templates

Create a new blog layout template.

{
  "name": "Long-form Guide",
  "description": "Template for comprehensive guides",
  "layout": { "sections": ["hero", "toc", "content", "faq", "cta"] },
  "is_default": false,
  "is_public": false
}

Game Studio

Game Studio

The Game Studio API lets you build, manage, and AI-generate Three.js games and interactive 3D experiences programmatically. Currently supports Three.js โ€” additional engines coming soon.

Overview

The Three.js Game Studio provides:

  • Project management โ€” Create, list, update, and delete game projects
  • Scene management โ€” Multi-scene projects with transition configs
  • AI code generation โ€” Stream AI-generated Three.js code from any supported model
  • Virtual File System โ€” Multi-file projects with structured file trees
  • Parallel agents โ€” Up to 4 AI agents working simultaneously on a project
  • Scene composition โ€” Combine multiple scenes into a single playable game

All Game Studio endpoints require session authentication (admin only). API key access coming soon.

Projects

GET/api/game-studio/threejs/projects

List all Three.js projects for the authenticated user. Returns project name, color, scene count, and timestamps.

GET/api/game-studio/projects/:id

Get a single project's details including metadata and command count.

PUT/api/game-studio/projects/:id

Update a project's name, description, color, or connection settings.

{
  "name": "Space Explorer",
  "description": "A 3D space exploration game",
  "color": "#6366f1"
}
DELETE/api/game-studio/projects/:id

Delete a project and all its scenes. This cannot be undone.

Scenes

GET/api/game-studio/threejs/scenes?projectId=:id

List all scenes in a project, ordered by scene order. Returns code, VFS files, chat history, and transition configs.

POST/api/game-studio/threejs/scenes

Create a new scene in a project.

{
  "projectId": "uuid",
  "name": "Level 2 - Forest",
  "code": "// Three.js code here..."
}
PUT/api/game-studio/threejs/scenes

Update a scene's metadata (name, order, transitions).

{
  "id": "scene-uuid",
  "name": "Boss Arena",
  "transitionType": "fade",
  "transitionDuration": 1000,
  "triggerType": "coordinates",
  "triggerConfig": { "x": 50, "z": 50, "radius": 5 }
}

Transition types: fade, loading_screen, crossfade, slide, none. Trigger types: key_press, coordinates, timer, score, custom.

DELETE/api/game-studio/threejs/scenes?id=:id

Delete a scene from a project.

PUT/api/game-studio/threejs/save

Quick-save scene state. Creates or updates project + scene. Supports the Virtual File System.

{
  "projectId": "uuid (optional - omit to create new project)",
  "sceneId": "uuid (optional - omit to create new scene)",
  "name": "My Game",
  "code": "// bundled Three.js code",
  "files": {
    "files": {
      "src/main.js": { "content": "// entry point...", "language": "javascript" },
      "src/entities/player.js": { "content": "// player code...", "language": "javascript" },
      "src/systems/physics.js": { "content": "// physics...", "language": "javascript" }
    }
  },
  "chatMessages": [],
  "codeHistory": []
}

The files field stores the Virtual File System โ€” a multi-file project structure. Legacy single-file projects use code only.

AI Code Generation

POST/api/game-studio/threejs/generate

Stream AI-generated Three.js code. Supports all Kunya AI models (OpenAI, Anthropic, Google, DeepSeek, xAI, MiniMax, OpenRouter). Returns Server-Sent Events.

Generate mode (full code replacement)
{
  "modelId": "claude-4-sonnet",
  "prompt": "Add a particle system that follows the mouse cursor",
  "currentCode": "// current Three.js code...",
  "messages": [
    { "role": "user", "content": "Create a spinning cube" },
    { "role": "assistant", "content": "Here's a cube..." }
  ],
  "graphicsPreset": "enhanced"
}
Tools mode (surgical edits via MCP tools)
{
  "modelId": "claude-4-sonnet",
  "prompt": "Add enemy spawning in a new file",
  "mode": "tools",
  "vfsFiles": {
    "src/main.js": { "content": "...", "language": "javascript" },
    "src/entities/player.js": { "content": "...", "language": "javascript" }
  },
  "messages": [],
  "graphicsPreset": "basic"
}

Graphics presets: basic, enhanced (PBR + bloom), retro (low-poly), high_fidelity (full post-processing).

SSE Events (text/event-stream):

// Text content (streamed token by token)
data: { "content": "Here's the updated code..." }

// Tool call (tools mode only)
data: { "tool_call": { "id": "call_1", "name": "edit_file", "args": { "path": "src/main.js", "old_string": "...", "new_string": "..." } } }

// Tool result (tools mode only)  
data: { "tool_result": { "id": "call_1", "name": "edit_file", "result": "Edited src/main.js", "isError": false } }

// File mutations (tools mode โ€” apply to VFS immediately)
data: { "mutations": [{ "type": "edit_file", "path": "src/main.js", "old_string": "...", "new_string": "..." }] }

// Completion
data: { "done": true, "cost": 0.0042, "tokens": 1250, "vfsFiles": { ... } }

Available tools (tools mode):

list_files โ€” List all project files with line counts

read_file โ€” Read a file's content

create_file โ€” Create a new file

edit_file โ€” Surgical string replacement in a file

delete_file โ€” Delete a file

rename_file โ€” Rename or move a file

search_code โ€” Regex search across all files

get_project_summary โ€” Read the living project summary

update_project_summary โ€” Update project summary after changes

run_preview โ€” Trigger preview rebuild

Scene Composition

POST/api/game-studio/threejs/compose

Compose multiple scenes into a single playable game. The AI generates a scene manager with transitions based on your scene configurations.

{
  "projectId": "uuid",
  "modelId": "claude-4-sonnet"
}

Streams the composed game code as SSE. Uses each scene's transition type, duration, trigger type, and trigger config to build seamless scene transitions.

Language & Learning

Language & Learning

Overview

Build AI-powered language learning applications โ€” Duolingo-style apps, pronunciation trainers, adaptive tutors, and vocabulary builders. These endpoints provide CEFR-aligned assessment, phoneme-level pronunciation feedback, categorized grammar analysis, and intelligent vocabulary extraction.

Pronunciation Scoring

Whisper transcription + AI phoneme analysis with targeted feedback

CEFR Assessment

Automated proficiency placement (A1-C2) from writing or speech

Grammar Analysis

Categorized error detection with learner-friendly explanations

Difficulty Scoring

Rate any text on the CEFR scale for curriculum design

Vocabulary Extraction

Extract vocab with definitions, frequency bands, and CEFR levels

Language Tutor Agent

Conversational tutor with adaptive level, error correction, and memory

These endpoints complement existing capabilities documented elsewhere: Audio (TTS & Transcription), AI Translation, Voice Agents, and Voice Cloning.

Pronunciation Scoring

POST/api/v1/language/pronunciation-score

Score pronunciation quality by comparing audio against target text. Transcribes with Whisper, then uses AI to analyze accuracy, fluency, and prosody at the word level.

Request Body

NameTypeRequiredDescription
audiostringYesBase64-encoded audio (WAV, MP3, WebM, OGG)
target_textstringYesThe text the speaker was trying to say
languagestringNoISO 639-1 code (default: "en"). E.g. "fr", "de", "ja", "es"
detail_levelstringNo"word" (default) or "sentence"
modelstringNoAI model for analysis (default: gemini-3.5-flash)

Response

{
  "overall_score": 78,
  "accuracy_score": 74,
  "fluency_score": 82,
  "prosody_score": 80,
  "transcribed_text": "Je voudrais un cafe sil vous plait",
  "words": [
    {
      "word": "voudrais",
      "spoken": "voudrai",
      "score": 65,
      "feedback": "The final 's' in 'voudrais' is silent but the 'ai' should be more open, like 'eh'"
    },
    {
      "word": "s'il",
      "spoken": "sil",
      "score": 90,
      "feedback": null
    }
  ],
  "tempo_analysis": {
    "words_per_minute": 95,
    "assessment": "slightly slow โ€” target ~120 wpm for natural French"
  },
  "overall_feedback": "Good attempt! Focus on the nasal vowels and the open 'ai' sound in conditional verb forms.",
  "recommended_practice": [
    "Practice 'ai/ais/ait' endings: voudrais, aimerais, pourrais",
    "Listen and repeat: French conditional tense phrases at natural speed"
  ],
  "target_text": "Je voudrais un cafรฉ, s'il vous plaรฎt",
  "language": "fr",
  "cost": 0.012
}

Difficulty Scoring

POST/api/v1/language/difficulty-score

Rate any text on the CEFR scale (A1-C2) with detailed breakdown by vocabulary, grammar, and sentence complexity. Essential for curriculum design and content grading.

Request Body

NameTypeRequiredDescription
textstringYesText to analyze (max 5,000 characters)
languagestringNoLanguage of the text (default: "en")
modelstringNoAI model (default: gemini-3.5-flash)

Response

{
  "level": "B2",
  "sub_level": "B2.1",
  "confidence": 0.91,
  "readability_score": 45,
  "breakdown": {
    "vocabulary": { "level": "B2", "notes": "Contains academic vocabulary and low-frequency terms" },
    "grammar": { "level": "B2", "notes": "Uses passive voice, relative clauses, and conditional structures" },
    "sentence_complexity": { "level": "C1", "notes": "Several multi-clause sentences with embedded subordination" },
    "topic_familiarity": { "level": "B2", "notes": "Specialized (technology) but accessible to informed readers" }
  },
  "statistics": {
    "word_count": 247,
    "avg_sentence_length": 18.2,
    "unique_vocabulary_ratio": 0.68,
    "estimated_vocabulary_level": 5200
  },
  "suitable_for": "Upper-intermediate learners (B2+) with interest in technology topics",
  "language": "en",
  "cost": 0.003
}

Grammar Analysis

POST/api/v1/language/grammar-check

Categorized grammar error detection with explanations, corrections, and severity ratings. Unlike a simple spellchecker, this classifies errors by type (verb tense, articles, prepositions, etc.) and explains the grammar rule.

Request Body

NameTypeRequiredDescription
textstringYesText to analyze (max 5,000 characters)
languagestringNoLanguage of the text (default: "en")
learner_levelstringNoCEFR level of the writer (A1-C2). Adjusts explanation complexity.
modelstringNoAI model (default: gemini-3.5-flash)

Response

{
  "corrected_text": "Yesterday I went to the store and bought some apples.",
  "error_count": 3,
  "errors": [
    {
      "original": "go",
      "correction": "went",
      "category": "verb_tense",
      "severity": "major",
      "explanation": "Use past simple ('went') for completed actions in the past. 'Yesterday' signals past tense.",
      "rule": "Past simple for completed past actions"
    },
    {
      "original": "buyed",
      "correction": "bought",
      "category": "verb_tense",
      "severity": "major",
      "explanation": "'Buy' is an irregular verb. The past form is 'bought', not 'buyed'.",
      "rule": "Irregular past tense"
    },
    {
      "original": "some apple",
      "correction": "some apples",
      "category": "plural",
      "severity": "minor",
      "explanation": "'Some' is used with plural countable nouns: 'some apples'.",
      "rule": "Countable noun plurals with quantifiers"
    }
  ],
  "error_summary": { "verb_tense": 2, "plural": 1 },
  "overall_accuracy": 72,
  "strengths": ["Good sentence structure", "Correct use of articles"],
  "focus_areas": ["Irregular past tense forms", "Countable/uncountable noun agreement"],
  "language": "en",
  "cost": 0.004
}

Error categories: verb_tense, subject_verb_agreement, article, preposition, word_order, spelling, punctuation, pronoun, plural, word_choice, register, idiom.

CEFR Assessment

POST/api/v1/language/cefr-assess

Automated CEFR proficiency assessment from writing samples or conversation transcripts. Evaluates vocabulary range, grammatical accuracy, fluency, and task achievement against official CEFR descriptors.

Request Body

NameTypeRequiredDescription
textstringYesWriting sample or conversation transcript (max 10,000 characters)
languagestringNoLanguage being assessed (default: "en")
skillstringNo"writing" (default), "speaking", "reading", "listening", or "overall"
rubricstringNo"general" (default), "goethe_institut", "dele", "delf", "cambridge"
modelstringNoAI model (default: claude-sonnet-4.6 for higher accuracy)

Response

{
  "level": "B1",
  "sub_level": "B1.2",
  "confidence": 0.87,
  "skill": "writing",
  "breakdown": {
    "vocabulary_range": { "level": "B1", "notes": "~3200 active lemmas, adequate for familiar topics" },
    "grammatical_accuracy": { "level": "A2+", "notes": "Subjunctive used correctly 2/5 times, consistent article errors" },
    "fluency_coherence": { "level": "B2", "notes": "Good paragraph organization, logical connectors" },
    "task_achievement": { "level": "B1", "notes": "Addresses the topic but lacks nuanced argumentation" }
  },
  "evidence": [
    "Used past subjunctive correctly: 'Si yo tuviera mรกs tiempo...'",
    "Vocabulary range covers travel, daily life, and some workplace topics",
    "Self-corrected errors in 60% of cases"
  ],
  "strengths": ["Good use of discourse markers", "Natural paragraph flow"],
  "weaknesses": ["Inconsistent subjunctive mood", "Limited use of passive voice"],
  "recommended_focus": ["subjunctive_mood", "passive_voice", "idiomatic_expressions"],
  "estimated_vocabulary_size": 3200,
  "next_level_requirements": "To reach B2: master subjunctive in all tenses, expand vocabulary to 4500+ lemmas, develop ability to argue and hypothesize",
  "language": "es",
  "cost": 0.015
}

Vocabulary Extraction

POST/api/v1/language/vocabulary-extract

Extract vocabulary from any text with definitions, example sentences, frequency bands, and CEFR levels. Filters by learner level so only useful (above-level) words are returned. Ideal for building flashcard decks from reading material.

Request Body

NameTypeRequiredDescription
textstringYesSource text to extract vocabulary from (max 8,000 characters)
languagestringNoLanguage of the text (default: "en")
learner_levelstringNoLearner CEFR level (default: "B1"). Only words above this level are extracted.
max_itemsnumberNoMax vocabulary items to return (default: 20, max: 50)
include_phrasesbooleanNoInclude multi-word phrases and collocations (default: true)
translation_languagestringNoIf set, includes translations in this language (e.g. "en" for English translations of Spanish vocab)
modelstringNoAI model (default: gemini-3.5-flash)

Response

{
  "items": [
    {
      "term": "durchsetzen",
      "lemma": "durchsetzen",
      "part_of_speech": "verb",
      "definition": "etwas gegen Widerstand erreichen oder verwirklichen",
      "translation": "to enforce / to push through",
      "example_sentence": "Die Regierung konnte die neue Regelung nicht durchsetzen.",
      "frequency_band": "top_5000",
      "cefr_level": "B2",
      "context_from_text": "...versuchte, ihre Interessen durchzusetzen...",
      "notes": "Separable verb: 'Er setzt seine Meinung durch.' Reflexive form 'sich durchsetzen' means 'to prevail'."
    }
  ],
  "text_cefr_level": "B2",
  "total_unique_words": 187,
  "items_above_learner_level": 12,
  "language": "de",
  "learner_level": "B1",
  "cost": 0.005
}

Language Tutor Agent

The Language Tutor is a pre-built agent template that teaches languages through adaptive conversation. Create one via the Agents API using template template-language-tutor.

Capabilities

  • Adaptive CEFR-level detection and adjustment during conversation
  • Implicit error correction (recasting) and explicit grammar explanations
  • Role-play scenarios: ordering food, job interviews, doctor visits, etc.
  • Vocabulary building with collocations, frequency context, and spaced introduction
  • Cultural context and pragmatics that textbooks miss
  • Session memory: tracks progress, recurring errors, and learned vocabulary across conversations
  • Exam prep support: DELE, DELF, Goethe-Zertifikat, JLPT, HSK, TOPIK, Cambridge
POST/api/v1/agents

Create a Language Tutor agent from the template.

{
  "name": "French Tutor",
  "template_id": "template-language-tutor",
  "instructions": "You are teaching French to an English speaker at B1 level. Focus on conversational fluency and the subjunctive mood. The learner is preparing for DELF B2.",
  "config": {
    "tone": "friendly",
    "memoryEnabled": true
  }
}

Then chat via POST /api/v1/agents/:id/chat. For voice-based tutoring, pair with a Voice Agent.

These existing endpoints are essential building blocks for language learning apps. Full documentation is in their respective sections.

POST
/api/v1/ai/translate

Translate text between any language pair โ€” see AI Utilities

POST
/api/v1/audio/speech

Text-to-speech in 10+ languages (ElevenLabs, Google, Qwen) โ€” see Audio

POST
/api/v1/audio/transcriptions

Speech-to-text with Whisper (dictation, listening exercises) โ€” see Audio

POST
/api/v1/audio/translate

Transcribe + translate audio in one step โ€” see Audio

POST
/api/v1/voice/agents

Voice agents for real-time spoken conversation practice โ€” see Voice Agents

POST
/api/v1/audio/clone

Clone voices for custom teacher personas โ€” see Voice Cloning

POST
/api/v1/ai/rewrite

Rewrite text in different styles/registers โ€” see AI Utilities

Desktop IDE

API routes for the Kunya Desktop IDE (Tauri app). Uses session Bearer token from desktop login โ€” not API keys. The desktop reads local files; the server handles embeddings, agent loops, inline edit, and tab completion.

POST/api/v1/ide/index

Index workspace file batches for semantic search (tree-sitter chunking + Gemini embeddings).

{
  "workspacePath": "/Users/dev/my-project",
  "files": [
    { "relativePath": "src/app.ts", "content": "export function main() {}" },
    { "relativePath": "src/removed.ts", "deleted": true }
  ]
}
GET/api/v1/ide/index?workspacePath=...

Get semantic index status (file/chunk counts, indexing state).

POST/api/v1/ide/search

Semantic search over indexed codebase chunks.

{
  "workspacePath": "/Users/dev/my-project",
  "query": "authentication middleware",
  "limit": 10
}
POST/api/v1/ide/agent

Streaming IDE agent (SSE). Server runs semantic_search; sys_* tools execute on desktop.

{
  "workspacePath": "/Users/dev/my-project",
  "messages": [{ "role": "user", "content": "Fix the login error handling" }],
  "pinnedFiles": ["src/auth/login.ts"],
  "activeFile": "src/auth/login.ts",
  "workspaceRules": "From AGENTS.md and .cursor/rules",
  "mentionedFiles": [{ "path": "src/auth/login.ts", "content": "..." }],
  "model": "claude-sonnet-4.6"
}

SSE events: content, tool_call, awaiting_local_tools, done

POST/api/v1/ide/inline-edit

Streaming inline edit (โŒ˜K) โ€” returns replacement code for a selection.

{
  "filePath": "src/utils.ts",
  "language": "typescript",
  "instruction": "add null check",
  "selectedText": "return user.name;"
}
POST/api/v1/ide/completion

Tab completion โ€” returns text to insert at cursor (ghost text in Monaco).

{
  "filePath": "src/app.ts",
  "language": "typescript",
  "prefix": "export function hello() {\n  const x = ",
  "suffix": "\n}"
}

Response

{ "data": { "completion": "42;" } }

CMS

CMS

The CMS adds editorial workflows, content versioning, batch releases, connected sites, and structured content schemas to your blog. All CMS routes require Professional plan or higher. Routes return 403 with FEATURE_REQUIRES_UPGRADE if the user's plan is insufficient.

Overview

The CMS provides:

  • Content versioning โ€” Snapshot, compare, and restore any post revision
  • Editorial workflows โ€” Multi-stage approval pipelines (Draft โ†’ Review โ†’ Approved โ†’ Published)
  • Batch releases โ€” Group posts into releases and publish them together
  • Connected sites โ€” Push content to external sites via webhooks
  • Content schemas โ€” Define structured content types with custom fields
  • Bulk import โ€” Import posts from CSV or Markdown files

Base path: /api/cms. All endpoints require session authentication.

Versions

POST/api/cms/versions

Create a version snapshot of a post. Captures title, content, excerpt, and metadata at the current point in time.

{
  "postId": "uuid",
  "label": "Before major rewrite"
}
GET/api/cms/versions?postId=:id

List all versions for a post, ordered newest first. Returns version label, author, and creation timestamp.

POST/api/cms/versions/:id

Restore a post to the state captured in a specific version. Overwrites current content with the version snapshot.

Workflows

GET/api/cms/workflows

List all editorial workflows for the authenticated user. Returns workflow name, stages, and post counts per stage.

POST/api/cms/workflows

Create a new editorial workflow with ordered stages.

{
  "name": "Blog Review Pipeline",
  "stages": ["Draft", "Editor Review", "Legal Review", "Approved", "Published"]
}
POST/api/cms/workflows/advance

Advance a post to the next stage in its assigned workflow.

{
  "postId": "uuid",
  "workflowId": "uuid"
}

Releases

GET/api/cms/releases

List all content releases. Returns release name, status, scheduled date, and included post count.

POST/api/cms/releases

Create a new content release and optionally assign posts.

{
  "name": "Spring Launch 2026",
  "scheduledAt": "2026-04-01T09:00:00Z",
  "postIds": ["uuid1", "uuid2", "uuid3"]
}
POST/api/cms/releases/:id/publish

Publish all posts in a release simultaneously. Sets each post status to published and triggers connected site webhooks.

Connected Sites

GET/api/cms/sites

List all connected external sites. Returns site name, URL, webhook endpoint, and sync status.

POST/api/cms/sites

Connect a new external site. Posts will be pushed to the site via webhook on publish.

{
  "name": "Marketing Blog",
  "url": "https://blog.example.com",
  "webhookUrl": "https://blog.example.com/api/content-hook",
  "secret": "whsec_..."
}
PUT/api/cms/sites/:id

Update a connected site's name, URL, webhook endpoint, or secret.

DELETE/api/cms/sites/:id

Disconnect a site. Stops pushing content to the site on publish.

Content Schemas

GET/api/cms/schemas

List all content type schemas. Returns schema name, field definitions, and entry count.

POST/api/cms/schemas

Create a new content type schema with custom fields.

{
  "name": "Product Update",
  "fields": [
    { "name": "version", "type": "string", "required": true },
    { "name": "changelog", "type": "richtext", "required": true },
    { "name": "releaseDate", "type": "date", "required": false }
  ]
}
GET/api/cms/schemas/:id/entries

List all content entries for a specific schema. Supports pagination via limit and offset query parameters.

POST/api/cms/schemas/:id/entries

Create a new content entry matching the schema's field definitions.

{
  "data": {
    "version": "2.5.0",
    "changelog": "<p>Added CMS support...</p>",
    "releaseDate": "2026-05-10"
  }
}

Import

POST/api/cms/import

Import posts from CSV or Markdown files. CSV must include title and content columns. Markdown files use front-matter for metadata.

{
  "format": "csv",
  "data": "title,content,category\nMy Post,<p>Hello world</p>,News",
  "publish": false
}

Supported formats: csv, markdown. Set publish: true to immediately publish imported posts.

Need help? Contact us at [email protected]

ยฉ 2026 Kunya. All rights reserved.