The InkSlop API lets you generate and publish videos programmatically — from a single script or a batch of hundreds.
Base URL: https://inkslop.com/api/proxy/api/v1
All endpoints require an API key passed as a Bearer token.
Authorization: Bearer isk_your_key_hereCreate API keys in the Dashboard → Accounts tab. Keys are prefixed with isk_ and are shown once at creation — store them securely. You can also use a Logto session JWT for key management endpoints.
POST /api/v1/keys{ "name": "My automation" }Response:
{
"key_id": "a1b2c3...",
"name": "My automation",
"api_key": "isk_abcdef...",
"created_at": "2026-05-18T12:00:00Z"
}
api_keyis returned only once. Store it immediately.
GET /api/v1/keys[
{
"key_id": "a1b2c3...",
"name": "My automation",
"created_at": "2026-05-18T12:00:00Z",
"last_used_at": "2026-05-18T14:30:00Z",
"revoked": false
}
]DELETE /api/v1/keys/{key_id}{ "revoked": true, "key_id": "a1b2c3..." }List the YouTube and TikTok channels you have connected in the dashboard.
GET /api/v1/channels[
{
"id": 3,
"platform": "youtube",
"account_name": "My Channel",
"channel_id": "UCxxxxxxx",
"is_oauth": true
}
]Use the id field when submitting videos for auto-publish.
POST /api/v1/videos| Field | Type | Description |
|---|---|---|
script |
string | DSL script. See DSL Reference. |
video_name |
string | Display name (no extension). Optional. |
resolution |
string | "9:16" (portrait, default) or "16:9" |
estimated_duration |
float | Duration hint in seconds (default 30). Used for credit pre-check. |
notify_on_complete |
bool | Send an email when generation finishes. |
publish |
object | Auto-publish config. Optional. |
Minimal request — generate only:
{
"script": "[tts engine=\"kokoro_tts\" voice=\"af_heart\"]\nHello world!\n[/tts]",
"video_name": "hello-world",
"resolution": "9:16"
}With manual publish metadata:
{
"script": "...",
"publish": {
"channel_id": 3,
"title": "My Video",
"description": "A video created with InkSlop.",
"tags": ["ai", "shorts"],
"privacy": "public"
}
}With AI-generated metadata:
{
"script": "...",
"publish": {
"channel_id": 3,
"ai_generate_meta": true,
"privacy": "public"
}
}Publish config fields:
| Field | Type | Description |
|---|---|---|
channel_id |
int | Channel ID from GET /channels |
title |
string | Video title. Leave empty with ai_generate_meta: true. |
description |
string | Video description. |
tags |
array | List of tag strings. |
privacy |
string | public, private, or unlisted |
review_before_publish |
bool | Queue the upload for manual approval in the dashboard before it goes live. |
ai_generate_meta |
bool | Use AI to generate title, description, and tags from the script. |
Response:
{
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending"
}GET /api/v1/videos/{task_id}| Status | Meaning |
|---|---|
pending |
Queued, not started yet |
processing |
Rendering in progress |
done |
Complete, video_url and download_url are available |
error |
Failed, check message |
Response (done):
{
"task_id": "550e8400...",
"status": "done",
"progress": 100,
"message": "Generation complete.",
"video_url": "https://inkslop.com/files/abc123",
"download_url": "https://inkslop.com/files/abc123/download",
"credits_used": 2.3,
"duration_seconds": 28.4,
"user_file_id": 42
}Poll every 5-10 seconds until status is done or error.
GET /api/v1/videos?limit=20&offset=0Returns an array of video summary objects. limit max is 100.
POST /api/v1/videos/{task_id}/publishThe video must have status: done. Enqueues an upload to YouTube or TikTok.
{
"channel_id": 3,
"title": "My Video",
"description": "Description here.",
"tags": ["shorts", "ai"],
"privacy": "public",
"ai_generate_meta": false
}Response:
{
"platform": "youtube",
"job_id": 17,
"status": "pending"
}Generate a title, description, and tags for any script using AI.
POST /api/v1/meta/generate{
"script": "...",
"platform": "youtube"
}Response:
{
"title": "5 Things Nobody Tells You About Electric Cars",
"description": "We break down the real cost, range, and daily experience of owning an EV in 2026.",
"tags": ["electric cars", "ev", "tesla", "sustainability", "auto"]
}platform can be youtube (10 tags, longer description) or tiktok (5 tags, shorter).
All errors return a JSON body with a detail field.
| Status | Meaning |
|---|---|
| 400 | Bad request — check your input |
| 401 | Invalid or revoked API key |
| 402 | Insufficient credits or subscription required |
| 404 | Resource not found |
| 409 | Conflict — e.g. video not done yet |
| 429 | Rate limit exceeded |
| 502 | External service unavailable (Polar, Google AI) |
Example:
{ "detail": "Insufficient credits. Balance: 0.5, required: 2.0" }Limits are per user across all API keys.
| Endpoint | Limit |
|---|---|
POST /videos |
10/min, 25/hr, 50/day |
GET /videos/{id} |
60/min |
GET /videos |
60/min |
POST /meta/generate |
10/min, 60/hr |
POST /keys |
5/min |
When rate-limited, the response is 429 Too Many Requests.
import time, requests
BASE = "https://inkslop.com/api/proxy/api/v1"
KEY = "isk_your_key_here"
H = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
SCRIPT = """
[music file="music/Carefree.opus" volume="0.3" fit="loop"]
[tts engine="kokoro_tts" voice="af_heart" subtitles="true"]
Did you know the mantis shrimp can punch with the force of a bullet?
Their eyes can see 16 types of colour receptors. Humans have only 3.
[/tts]
[/music]
"""
# Submit
r = requests.post(f"{BASE}/videos", headers=H, json={
"script": SCRIPT,
"video_name": "mantis-shrimp",
"resolution": "9:16",
"estimated_duration": 15,
})
task_id = r.json()["task_id"]
print("Task:", task_id)
# Poll until done
while True:
r = requests.get(f"{BASE}/videos/{task_id}", headers=H)
data = r.json()
print(f" {data['progress']}% — {data['message']}")
if data["status"] in ("done", "error"):
break
time.sleep(8)
if data["status"] == "done":
print("Download:", data["download_url"])
print("Credits used:", data["credits_used"])Ready to start building?