---
name: turavu
version: 1.0.0
description: Video catalog and streaming API. Store video metadata, generate embed codes, organize into channels, track play analytics.
homepage: https://www.turavu.com
metadata: {"category":"media","api_base":"https://www.turavu.com/api/v1"}
---

# TuraVu

**Video catalog and streaming API.**

Store video metadata, generate responsive embed codes, organize content into channels, and track play analytics — without managing media infrastructure. Actual video files live on YouTube, Vimeo, Mux, or Cloudflare Stream. Part of Tura Cloud. Authentication uses TuraLogin API keys (Bearer token).

## Skill Files

| File | URL |
|------|-----|
| **SKILL.md** (this file) | `https://www.turavu.com/SKILL.md` |
| **AGENTS.md** | `https://www.turavu.com/AGENTS.md` |
| **API.md** | `https://www.turavu.com/API.md` |
| **QUICKSTART.md** | `https://www.turavu.com/QUICKSTART.md` |
| **skill.json** (metadata) | `https://www.turavu.com/skill.json` |

**Base URL:** `https://www.turavu.com/api/v1`

**Authentication:** `Authorization: Bearer <API_KEY>` — Use TuraLogin API keys from https://www.turalogin.com/dashboard/keys

---

## Overview

TuraVu manages the catalog layer, not the CDN:

✅ **Video catalog** — Add videos with titles, descriptions, tags, and embed URLs  
✅ **Channels** — Group videos into ordered channels or playlists  
✅ **Embed codes** — Get a responsive iframe embed for any video  
✅ **Play analytics** — Track starts, completions, and watch time per video  

You handle:
- Actual video hosting (YouTube, Vimeo, Mux, Cloudflare Stream, etc.)
- Upload and transcoding (via your chosen provider)
- Access control and gating (use TuraLogin + TuraSubscribe)

---

## Quick Start

### 1. Get Your API Key

TuraVu uses **TuraLogin API keys**. Get one at https://www.turalogin.com/dashboard/keys

- Test: `tl_test_xxxxxxxxxxxxxxxx`
- Production: `tl_live_xxxxxxxxxxxxxxxx`

### 2. Add a Video

```bash
curl -X POST https://www.turavu.com/api/v1/vu/videos \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Getting Started with TuraVu",
    "description": "A walkthrough of the TuraVu API.",
    "embedUrl": "https://www.youtube.com/embed/dQw4w9WgXcQ",
    "channel": "tutorials",
    "tags": ["intro", "tutorial"],
    "duration": 312
  }'
```

**Response:**
```json
{
  "id": "vid_abc123xyz",
  "title": "Getting Started with TuraVu",
  "embedUrl": "https://www.youtube.com/embed/dQw4w9WgXcQ",
  "channel": "tutorials",
  "tags": ["intro", "tutorial"],
  "duration": 312,
  "playCount": 0,
  "createdAt": "2026-02-22T10:00:00Z"
}
```

### 3. Get an Embed Code

```bash
curl "https://www.turavu.com/api/v1/vu/videos/vid_abc123xyz/embed" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

**Response:**
```json
{
  "html": "<iframe src=\"https://www.youtube.com/embed/dQw4w9WgXcQ\" width=\"100%\" style=\"aspect-ratio:16/9;\" allowfullscreen></iframe>",
  "embedUrl": "https://www.youtube.com/embed/dQw4w9WgXcQ"
}
```

---

## Full API Reference

### POST /api/v1/vu/videos

Add a video to the catalog.

**Request Body:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `title` | string | Yes | Video title |
| `embedUrl` | string | Yes | Provider embed URL (YouTube, Vimeo, etc.) |
| `description` | string | No | Video description (markdown) |
| `channel` | string | No | Channel slug |
| `tags` | string[] | No | Tag strings |
| `duration` | number | No | Duration in seconds |
| `thumbnailUrl` | string | No | Thumbnail image URL |
| `transcript` | string | No | Full text transcript |

---

### GET /api/v1/vu/videos

List videos in the catalog.

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `channel` | string | Filter by channel |
| `tag` | string | Filter by tag |
| `q` | string | Search by title/description |
| `limit` | number | Max results (default: 20, max: 100) |
| `cursor` | string | Pagination cursor |

**Success Response (200):**
```json
{
  "videos": [
    {
      "id": "vid_abc123",
      "title": "Getting Started",
      "channel": "tutorials",
      "duration": 312,
      "playCount": 47,
      "thumbnailUrl": "https://img.youtube.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
      "createdAt": "2026-02-22T10:00:00Z"
    }
  ],
  "nextCursor": "eyJpZCI6InZpZF9hYmMxMjMifQ==",
  "hasMore": true
}
```

---

### GET /api/v1/vu/videos/:id

Get a single video with full metadata.

---

### PATCH /api/v1/vu/videos/:id

Update video metadata.

---

### DELETE /api/v1/vu/videos/:id

Remove a video from the catalog.

---

### GET /api/v1/vu/videos/:id/embed

Get a responsive embed code for a video.

**Query Parameters:**

| Parameter | Type | Description |
|-----------|------|-------------|
| `width` | string | Width attribute (default: `100%`) |
| `autoplay` | boolean | Add autoplay param |

---

### POST /api/v1/vu/events

Record a play event.

**Request Body:**

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `videoId` | string | Yes | Video being played |
| `event` | string | Yes | `play`, `pause`, `complete`, `progress` |
| `userId` | string | No | Viewer ID if authenticated |
| `progressPct` | number | No | 0–100 for progress events |

---

### GET /api/v1/vu/videos/:id/stats

Get play analytics for a video.

**Success Response (200):**
```json
{
  "videoId": "vid_abc123",
  "plays": 312,
  "uniqueViewers": 248,
  "completions": 187,
  "completionRate": 75.4,
  "avgWatchTimeSec": 245
}
```

---

### POST /api/v1/vu/channels

Create a channel.

**Request Body:** `{ "slug": "tutorials", "name": "Tutorials", "description": "..." }`

---

### GET /api/v1/vu/channels/:slug/videos

List videos in a channel in order.

---

## Framework Examples

### Next.js (App Router)

```typescript
// app/api/vu/videos/route.ts
export async function POST(request: Request) {
  const body = await request.json();

  const res = await fetch('https://www.turavu.com/api/v1/vu/videos', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.TURAVU_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });

  return Response.json(await res.json(), { status: res.status });
}

// Server component — render a video
async function VideoPlayer({ videoId }: { videoId: string }) {
  const res = await fetch(
    `https://www.turavu.com/api/v1/vu/videos/${videoId}/embed`,
    { headers: { 'Authorization': `Bearer ${process.env.TURAVU_API_KEY}` } }
  );
  const { html } = await res.json();
  return <div dangerouslySetInnerHTML={{ __html: html }} />;
}
```

### Express.js

```javascript
router.get('/video/:id/embed', async (req, res) => {
  const response = await fetch(
    `https://www.turavu.com/api/v1/vu/videos/${req.params.id}/embed`,
    { headers: { 'Authorization': `Bearer ${process.env.TURAVU_API_KEY}` } }
  );
  const data = await response.json();
  res.json(data);
});
```

---

## Error Codes

| Status | Error | Description |
|--------|-------|-------------|
| 400 | `title is required` | Missing title |
| 400 | `embedUrl is required` | Missing embed URL |
| 400 | `Invalid event type` | Must be play, pause, complete, or progress |
| 401 | `Unauthorized` | Missing or invalid API key |
| 404 | `Video not found` | Invalid video ID |
| 404 | `Channel not found` | Invalid channel slug |
| 429 | `Too many requests` | Rate limit exceeded |

---

## Support & Resources

- 🌐 Website: https://www.turavu.com
- 🔑 API Keys: https://www.turalogin.com/dashboard/keys
