API Reference
Integrate ConceptViz diagram generation into your applications via REST API
All API requests require an API key passed via the Authorization header.
Authorization: Bearer cvk_your_api_key_here
You can create and manage API keys in your Settings > API Keys dashboard.
Your API key grants full access to your account credits. Keep it secret and never expose it in client-side code.
https://conceptviz.app/api/v1
Generation is asynchronous. You submit a request, receive a task ID, then poll for results.
| Parameter | Type | Required | Description |
|---|
prompt | string | Yes* | A single text prompt describing the diagram |
prompts | string[] | Yes* | Array of prompts for batch generation (max 4) |
quality | string | No | Image resolution: "2k" (default) or "4k" |
aspectRatio | string | No | Aspect ratio (e.g. "16:9", "1:1") |
Provide either prompt (single) or prompts (batch) — not both. If both are provided, prompts takes priority.
{
"taskId": "vaW29_MJ1wbnyFU4bl_pd",
"status": "pending",
"credits_used": 1,
"credits_remaining": 79,
"poll_url": "/api/v1/task/vaW29_MJ1wbnyFU4bl_pd"
}
GET /api/v1/task/{taskId}
Poll this endpoint every 3–5 seconds until status is completed or failed. Typical generation takes 30–90 seconds.
{
"status": "completed",
"images": [
{
"url": "https://r2.conceptviz.app/images/abc123.png",
"prompt": "water cycle diagram"
}
]
}
{
"status": "failed",
"error": "Image generation failed. Please try again later.",
"code": "GENERATION_FAILED",
"credits_refunded": true
}
{
"status": "processing"
}
| Quality | Credits per Image |
|---|
2k | 1 |
4k | 2 |
Credits are consumed when the task is submitted. If generation fails, credits are automatically refunded.
# Step 1: Submit
RESPONSE=$(curl -s -X POST https://conceptviz.app/api/v1/generate \
-H "Authorization: Bearer cvk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"prompt": "water cycle diagram showing evaporation, condensation, and precipitation",
"quality": "2k"
}')
TASK_ID=$(echo $RESPONSE | jq -r '.taskId')
import requests
import time
API_KEY = "cvk_your_api_key_here"
BASE_URL = "https://conceptviz.app/api/v1"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
const API_KEY = "cvk_your_api_key_here";
const BASE_URL = "https://conceptviz.app/api/v1";
// Step 1: Submit
const submitResponse = await fetch(`${BASE_URL}/generate`, {
method: "POST"
The API returns standard HTTP status codes with JSON error bodies:
{
"error": "Human-readable error message",
"code": "ERROR_CODE"
}
| HTTP Status | Code | Description |
|---|
400 | INVALID_BODY | Request body is not valid JSON |
400 | PROMPT_REQUIRED | No prompt or prompts provided |
400 | TOO_MANY_PROMPTS | More than 4 prompts in one request |
401 | UNAUTHORIZED | Missing or invalid Authorization header |
401 | INVALID_API_KEY | API key is invalid or disabled |
402 | INSUFFICIENT_CREDITS | Not enough credits (includes credits_remaining) |
403 | PLAN_LIMIT_EXCEEDED | Batch size exceeds your plan limit |
404 | TASK_NOT_FOUND | Task ID not found or doesn't belong to your account |
500 | GENERATION_FAILED | Image generation failed (credits auto-refunded) |
response = requests.post(f"{BASE_URL}/generate", headers=headers, json=payload)
if response.status_code == 402:
data = response.json()
| Constraint | Value |
|---|
| Max images per request | 4 |
| Max API keys per account | 5 |
| Generation time | 30–90 seconds typical |
| Poll interval | 3–5 seconds recommended |
| Available qualities | 2k, 4k |
echo
"Task ID:
$TASK_ID
"
# Step 2: Poll until complete
while true; do
RESULT=$(curl -s https://conceptviz.app/api/v1/task/$TASK_ID \
-H "Authorization: Bearer cvk_your_api_key_here")
STATUS=$(echo $RESULT | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then
echo $RESULT | jq .
break
fi
sleep 5
done
"Content-Type": "application/json",
}
# Step 1: Submit
response = requests.post(
f"{BASE_URL}/generate",
headers=HEADERS,
json={
"prompt": "photosynthesis process diagram",
"quality": "2k",
},
)
data = response.json()
task_id = data["taskId"]
print(f"Task submitted: {task_id}")
print(f"Credits used: {data['credits_used']}, remaining: {data['credits_remaining']}")
# Step 2: Poll for result
while True:
result = requests.get(f"{BASE_URL}/task/{task_id}", headers=HEADERS).json()
print(f"Status: {result['status']}")
if result["status"] == "completed":
for image in result["images"]:
print(f"Image URL: {image['url']}")
break
elif result["status"] == "failed":
print(f"Error: {result['error']}")
print(f"Credits refunded: {result.get('credits_refunded', False)}")
break
time.sleep(5)
,
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
prompts: [
"cell division mitosis diagram",
"DNA double helix structure",
],
quality: "2k",
}),
});
const { taskId, credits_used, credits_remaining } = await submitResponse.json();
console.log(`Task: ${taskId}, credits used: ${credits_used}`);
// Step 2: Poll for result
while (true) {
const pollResponse = await fetch(`${BASE_URL}/task/${taskId}`, {
headers: { Authorization: `Bearer ${API_KEY}` },
});
const result = await pollResponse.json();
console.log(`Status: ${result.status}`);
if (result.status === "completed") {
console.log("Images:", result.images);
break;
} else if (result.status === "failed") {
console.error("Failed:", result.error);
break;
}
await new Promise((r) => setTimeout(r, 5000));
}
print(f"Not enough credits. Remaining: {data.get('credits_remaining', 0)}")
elif response.status_code != 200:
print(f"Error: {response.json()['error']}")
else:
data = response.json()
task_id = data["taskId"]
# Start polling...
API Reference | ConceptViz | AI-Powered Science Diagrams for Teachers & Scientists