InkSlop API

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


Authentication

All endpoints require an API key passed as a Bearer token.

Authorization: Bearer isk_your_key_here

Create 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.


API Keys

Create a key

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_key is returned only once. Store it immediately.

List keys

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
  }
]

Revoke a key

DELETE /api/v1/keys/{key_id}
{ "revoked": true, "key_id": "a1b2c3..." }

Channels

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.


Videos

Submit a video

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"
}

Poll progress

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.

List videos

GET /api/v1/videos?limit=20&offset=0

Returns an array of video summary objects. limit max is 100.

Publish a completed video

POST /api/v1/videos/{task_id}/publish

The 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"
}

AI Metadata

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).


Error handling

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" }

Rate limits

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.


Quick start example

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?