DeepManim
API Docs

Agent Skill

Copy the instructions below and give them to your AI agent (Claude, GPT, Cursor, etc.) so it knows how to use the DeepManim API on your behalf.

SKILL.md
# DeepManim API Skill

You can use the DeepManim API to generate, improve, and narrate animated explainer videos from text prompts.

## Base URL

```
https://api.deepmanim.com/api/v1
```

## Authentication

All requests require an API key in the Authorization header:

```
Authorization: Bearer dm_k_YOUR_API_KEY
```

## Workflow

The typical workflow is:

1. **Generate** a video from a text prompt via `POST /generate`
2. **Poll** the returned job via `GET /jobs/{job_id}` until `status` is `"completed"`
3. **Improve** the video with follow-up instructions via `POST /improve` (optional, repeatable)
4. **Add audio** narration via `POST /audio` after you're happy with the visuals
5. **Improve narration** via `POST /improve-narration` if needed

Generate and improve calls start at 1.5 credits and vary by preset. Audio and improve-narration calls cost 1 credit. Reading data is free.

## Endpoints

### POST /generate
Generate a new video from a text prompt. Audio narration is included by default.

Request body:
```json
{
  "message": "Explain the Pythagorean theorem",
  "session_id": null
}
```
- `message` (required): The prompt describing what to animate.
- `session_id` (optional): Pass an existing session ID to continue a conversation.

Response:
```json
{
  "job_id": "abc-123",
  "session_id": "def-456",
  "status": "pending"
}
```

### POST /improve
Improve or modify an existing video. Does NOT include audio — add it separately via /audio after all modifications.

Request body:
```json
{
  "session_id": "def-456",
  "message": "Make the background darker and slow down the animation"
}
```

Response:
```json
{
  "job_id": "ghi-789",
  "session_id": "def-456",
  "status": "pending"
}
```

### POST /audio
Add narration audio to an existing video.

Request body:
```json
{
  "session_id": "def-456",
  "message_id": "msg-123",
  "high_quality": false
}
```

### POST /improve-narration
Improve existing narration on a video.

Request body:
```json
{
  "session_id": "def-456",
  "message_id": "msg-123",
  "high_quality": true
}
```

### GET /jobs/{job_id}
Poll job status. The `phase` field indicates progress:
`brainstorming` → `crafting_vision` → `assembling_pieces` → `polishing` → `done`

Response when completed:
```json
{
  "job_id": "abc-123",
  "status": "completed",
  "phase": "done",
  "estimated_time_remaining_seconds": 0,
  "result": {
    "video_url": "https://...",
    "description": "An animation of the Pythagorean theorem...",
    "session_id": "def-456",
    "message_id": "msg-789",
    "duration_seconds": 24.6,
    "has_audio": true,
    "follow_up": "What are some real-world applications?"
  }
}
```

Possible `status` values: `pending`, `processing`, `completed`, `failed`, `cancelled`.

### POST /jobs/{job_id}/cancel
Cancel a running or pending job.

### GET /sessions
List all your sessions.

### GET /sessions/{session_id}
Get a session with full message history.

### DELETE /sessions/{session_id}
Delete a session and all its messages.

### GET /sessions/{session_id}/jobs
List jobs for a session. Optional query param: `?status=completed`

### GET /messages/{message_id}
Get a single message by ID.

### GET /credits
Get credit balance: `balance`, `total_used`, `total_purchased`, `plan`.

### GET /me
Get current user info: `id`, `email`, `display_name`.

## Error Codes

- `401` — Missing or invalid API key
- `402` — Insufficient credits
- `404` — Resource not found
- `400` — Invalid request

## Polling Strategy

Jobs typically take 60–120 seconds. Poll `GET /jobs/{job_id}` every 3–5 seconds. Use the `estimated_time_remaining_seconds` field to adjust polling frequency. Stop polling when `status` is `completed`, `failed`, or `cancelled`.

## Example: Full Workflow

```python
import requests, time

API_KEY = "dm_k_YOUR_KEY"
BASE = "https://api.deepmanim.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# 1. Generate
r = requests.post(f"{BASE}/generate", headers=headers, json={"message": "Explain gravity"})
job_id = r.json()["job_id"]
session_id = r.json()["session_id"]

# 2. Poll until done
while True:
    job = requests.get(f"{BASE}/jobs/{job_id}", headers=headers).json()
    if job["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(4)

# 3. Get the result
video_url = job["result"]["video_url"]
message_id = job["result"]["message_id"]

# 4. Optionally improve
r = requests.post(f"{BASE}/improve", headers=headers, json={
    "session_id": session_id,
    "message": "Add more color and make it slower"
})
# Poll the new job_id the same way...

# 5. Add audio after improvements
r = requests.post(f"{BASE}/audio", headers=headers, json={
    "session_id": session_id,
    "message_id": message_id,
    "high_quality": False
})
# Poll the new job_id...
```