API Documentation

Authentication

All API requests require an API key. Include your API key as a query parameter key in each request.

https://api.vidcdn.xyz/v2/api/videos?key=YOUR_API_KEY

Examples

Account

Account Info

GET /account/info

Retrieves account information for the authenticated user.

Response

{
  "status": true,
  "data": {
    "username": "User Name",
    "email": "[email protected]",
    "account_type": "Premium",
    "created_at": "2022-01-01T00:00:00Z"
  }
}

Account Stats

GET /account/stats

Retrieves account statistics for the authenticated user.

Response

{
  "status": true,
  "data": {
    "total_videos": 50,
    "total_views": 10000,
    "total_storage": 5000000000,
    "account_type": "Premium",
    "plays_remaining": 1000,
    "premium_start_date": "2023-01-01T00:00:00Z",
    "premium_expire_date": "2024-01-01T00:00:00Z"
  }
}

Examples

Video

List Videos

GET /videos

Retrieves a paginated list of videos for the authenticated user.

Query Parameters

  • page (optional): Page number (default: 1)
  • per_page (optional): Number of items per page (default: 10)
  • folder_id (optional): ID of the folder to filter videos

Response

{
  "status": true,
  "data": {
    "videos": [
      {
        // video object
      },
      // ...
    ],
    "total": 100,
    "pages": 10,
    "current_page": 1
  }
}

Manage Video

Get Video Details

GET /videos/<video_id>

Retrieves details of a specific video.

Update Video

PUT /videos/<video_id>

Updates a specific video's details.

Request Body
{
  "title": "Updated Video Title",
  "intro": {
    "start": 0.0,
    "end": 10.5
  },
  "outro": {
    "start": 590.0,
    "end": 600.0
  },
  "folder_id": 1  // Optional: ID of the folder to move the video to (null for root)
}

Delete Video

DELETE /videos/<video_id>

Deletes a specific video.

Examples

Folder

List Folders

GET /folders

Retrieves a list of folders for the authenticated user.

Response

{
  "status": true,
  "data": [
    {
      "id": 1,
      "name": "Folder 1",
      "parent_id": null,
      "parent_name": null,
      "total_files": 5
    },
    {
      "id": 2,
      "name": "Subfolder",
      "parent_id": 1,
      "parent_name": "Folder 1",
      "total_files": 3
    },
    // ... more folders
  ]
}

Create Folder

POST /folders

Creates a new folder for the authenticated user.

Request Body

{
  "name": "New Folder",
  "parent_id": null  // Optional, set to create a subfolder
}

Response

{
  "status": true,
  "message": "Folder created successfully",
  "folder": {
    "id": 3,
    "name": "New Folder",
    "parent_id": null,
    "parent_name": null,
    "total_files": 0
  }
}

Update Folder

PUT /folders?folder_id=<folder_id>

Updates an existing folder for the authenticated user.

Request Body

{
  "name": "Updated Folder Name",
  "parent_id": 1  // Optional, update parent folder
}

Response

{
  "status": true,
  "message": "Folder updated successfully",
  "folder": {
    "id": 3,
    "name": "Updated Folder Name",
    "parent_id": 1,
    "parent_name": "Folder 1",
    "total_files": 2
  }
}

Delete Folder

DELETE /folders?folder_id=<folder_id>

Deletes a specific folder for the authenticated user.

Response

{
  "status": true,
  "message": "Folder deleted successfully"
}

Upload

Get Upload Server

GET /upload-server

Retrieves the upload server information for video upload.

Parameters

  • key: Your API key (query parameter)

Response

{
  "status": true,
  "data": {
    "id": 1,
    "upload_url": "https://example.com/upload?key=YOUR_API_KEY"
  }
}

Error Responses

// Invalid API key
{
  "status": false,
  "message": "Invalid API key"
}

// No available servers
{
  "status": false,
  "message": "No available servers"
}

Get Upload Server Examples

Upload Video

The API uses the TUS protocol for resumable uploads. First get the upload URL from the upload-server endpoint, then use it for the upload process.

1. Create Upload

POST {upload_url}

Initiates a new upload session using the URL obtained from upload-server.

Required Headers
  • Tus-Resumable: Must be "1.0.0"
  • Upload-Length: Total size of the file in bytes
  • Upload-Metadata: Base64 encoded metadata
  • Content-Type: Must be "application/offset+octet-stream"
Metadata Format

The Upload-Metadata header should contain base64 encoded values in the format: key {base64_value}

  • filename: Name of the file (required)
  • folderId: Target folder ID (optional, defaults to "root")
  • isPublic: "true" or "false" for video visibility (optional, defaults to "true")
Example Metadata
// Required metadata
const metadata = {
  filename: Buffer.from('video.mp4').toString('base64')
};

// With optional parameters
const metadata = {
  filename: Buffer.from('video.mp4').toString('base64'),
  folderId: Buffer.from('1').toString('base64'),  // optional
  isPublic: Buffer.from('false').toString('base64')  // optional
};

// Convert to metadata string
const metadataStr = Object.entries(metadata)
  .map(([k, v]) => `${k} ${v}`)
  .join(',');
Response Headers
  • Location: URL for subsequent PATCH requests
  • Tus-Resumable: "1.0.0"
  • Upload-Offset: "0" for new uploads

2. Upload Chunks

PATCH {upload_url}/{file_id}

Uploads a chunk of the file. Recommended chunk size is 5MB.

Required Headers
  • Tus-Resumable: "1.0.0"
  • Upload-Offset: Current offset in bytes
  • Content-Type: "application/offset+octet-stream"
  • Content-Length: Size of the current chunk in bytes
Response
  • Status code: 204 No Content on success
  • Upload-Offset: New offset after successful chunk upload

3. Check Upload Status

HEAD {upload_url}/{file_id}

Check the current status of an upload.

Required Headers
  • Tus-Resumable: "1.0.0"
Response Headers
  • Upload-Offset: Current upload position
  • Upload-Length: Total file size
  • Upload-Metadata: Original metadata

Complete Example

// Example of complete upload process
const axios = require('axios');
const fs = require('fs');

const API_KEY = 'your_api_key';
const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB chunks

async function uploadFile(filePath) {
  // 1. Get upload URL
  const serverResponse = await axios.get('https://api.vidcdn.xyz/v2/api/upload-server', {
    params: { key: API_KEY }
  });
  const uploadUrl = serverResponse.data.data.upload_url;

  // 2. Create upload
  const fileSize = fs.statSync(filePath).size;
  const filename = path.basename(filePath);
  
  const metadata = {
    filename: Buffer.from(filename).toString('base64'),
    folderId: Buffer.from('root').toString('base64'),
    isPublic: Buffer.from('true').toString('base64')
  };
  const metadataStr = Object.entries(metadata)
    .map(([k, v]) => `${k} ${v}`)
    .join(',');

  const createResponse = await axios.post(uploadUrl, null, {
    params: { key: API_KEY },
    headers: {
      'Tus-Resumable': '1.0.0',
      'Upload-Length': String(fileSize),
      'Upload-Metadata': metadataStr,
      'Content-Type': 'application/offset+octet-stream'
    }
  });

  const fileId = createResponse.headers.location.split('/').pop().split('?')[0];

  // 3. Upload chunks
  let offset = 0;
  const fileHandle = fs.openSync(filePath, 'r');

  try {
    while (offset < fileSize) {
      const chunkSize = Math.min(CHUNK_SIZE, fileSize - offset);
      const buffer = Buffer.alloc(chunkSize);
      const bytesRead = fs.readSync(fileHandle, buffer, 0, chunkSize, offset);

      await axios.patch(
        `${uploadUrl}/${fileId}`,
        buffer.slice(0, bytesRead),
        {
          params: { key: API_KEY },
          headers: {
            'Tus-Resumable': '1.0.0',
            'Upload-Offset': String(offset),
            'Content-Type': 'application/offset+octet-stream',
            'Content-Length': String(bytesRead)
          }
        }
      );

      offset += bytesRead;
      console.log(`Progress: ${(offset/fileSize*100).toFixed(2)}%`);
    }
  } finally {
    fs.closeSync(fileHandle);
  }

  return fileId;
}

Error Responses

// Invalid API key
{
  "error": "Invalid API key"
}

// Missing or invalid Tus-Resumable header
{
  "error": "Tus-Resumable header required"
}

// Invalid Upload-Offset
{
  "error": "Upload-Offset conflict"
}

// Upload not found
{
  "error": "Upload not found"
}

// Chunk upload failed
{
  "error": "Failed to write chunk"
}

Upload Examples

Remote Upload

The Remote Upload API allows you to add remote URLs for server-side downloading and processing.

List Remote Uploads

GET /remote-upload

Retrieves a list of remote uploads for the authenticated user.

Query Parameters
  • page: Page number (default: 1)
  • per_page: Number of items per page (default: 10)
  • sort: Sort field (default: created_at)
  • order: Sort order (asc or desc, default: desc)
Response
{
  "status": true,
  "data": [
    {
      "id": 1,
      "status": "pending",
      "video_id": "abc123",
      "url": "https://example.com/video.mp4",
      "progress": "0",
      "eta": null,
      "speed": null,
      "created_at": "2023-06-01T12:00:00Z"
    },
    // ... more remote upload objects
  ],
  "total": 100,
  "pages": 10,
  "current_page": 1
}

Start Remote Upload

POST /remote-upload

Starts a new remote upload task.

Request Body
{
  "url": "https://example.com/video.mp4",
  "title": "Video Title" (optional),
  "folder_id": 1 (optional),
  "is_public": true (optional)
}
Response
{
  "status": true,
  "message": "Remote upload started",
  "data": {
    "id": 2,
    "status": "pending",
    "video_id": "def456",
    "url": "https://example.com/video.mp4",
    "created_at": "2023-06-01T13:00:00Z"
  }
}

Delete Remote Upload

DELETE /remote-upload/:id

Deletes a specific remote upload task.

Response
{
  "status": true,
  "message": "Remote upload deleted"
}

Retry Remote Upload

POST /remote-upload/:id/retry

Retries a failed remote upload task.

Response
{
  "status": true,
  "message": "Remote upload retry initiated",
  "data": {
    "id": 4,
    "status": "pending",
    "video_id": "jkl012",
    "url": "https://example.com/video3.mp4",
    "created_at": "2023-06-01T14:00:00Z"
  }
}

Retry All Failed Uploads

POST /remote-upload/retry-all

Retries all failed remote upload tasks.

Response
{
  "status": true,
  "message": "Retrying 5 failed uploads"
}

Remote Upload Examples

Player Events

Player Messages

The player sends messages to the parent window using the postMessage API. These messages provide information about the current playback state.

Message Structure

{
  channel: 'vidcdn',
  event: 'time',
  time: number,
  duration: number,
  percent: number
}

Message Types

  • time: Sent every 5 seconds during playback
    • Provides current playback time, total duration, and percentage played
    • Useful for tracking viewing progress and updating UI elements like progress bars
    • Can be used to implement features like resume playback or analytics
  • complete: Sent when the video playback is complete
    • Indicates that the entire video has been watched
    • Can be used to trigger actions like showing related videos or updating watch history
    • Useful for analytics to track completed views

Message Details

Each message type includes the following information:

  • channel: Always set to 'vidcdn' to identify the source of the message
  • event: Either 'time' or 'complete' to indicate the message type
  • time: Current playback time in seconds
  • duration: Total duration of the video in seconds
  • percent: Percentage of the video that has been played (0-100)

Listening for Messages

To receive these messages in your parent application, you need to add an event listener:

window.addEventListener('message', (event) => {
  if (event.data && event.data.channel === 'vidcdn') {
    const message = JSON.parse(event.data);
    switch (message.event) {
      case 'time':
        console.log('Current time:', message.time);
        console.log('Duration:', message.duration);
        console.log('Percent played:', message.percent);
        break;
      case 'complete':
        console.log('Video playback completed');
        break;
    }
  }
});

You can use these messages to track playback progress, update your UI, or trigger other actions in your application based on the video playback state.

Error Handling

Overview

In case of an error, the API will return an appropriate HTTP status code along with a JSON response containing an error message and additional details when applicable.

Error Codes

Common HTTP status codes you may encounter:

  • 400 Bad Request: The request was invalid or cannot be served.
  • 401 Unauthorized: The request requires authentication.
  • 403 Forbidden: The server understood the request but refuses to authorize it.
  • 404 Not Found: The requested resource could not be found.
  • 429 Too Many Requests: You have sent too many requests in a given amount of time.
  • 500 Internal Server Error: The server encountered an unexpected condition that prevented it from fulfilling the request.

Error Examples

Invalid API Key

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "status": false,
  "message": "Invalid API key"
}

Resource Not Found

HTTP/1.1 404 Not Found
Content-Type: application/json

{
  "status": false,
  "message": "The requested video could not be found"
}

Rate Limit Exceeded

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{
  "status": false,
  "message": "Rate limit exceeded. Please try again later.",
  "retry_after": 60
}

Report

Overview

The Report API allows you to retrieve user statistics with custom filters.

Usage

GET /api/report

Retrieves a customized report of user statistics.

Query Parameters

  • start_date (optional): Start date for the report (format: YYYY-MM-DD)
  • end_date (optional): End date for the report (format: YYYY-MM-DD)
  • video_id (optional): ID of the video to filter stats

Response

{
  "status": true,
  "data": {
    "report": [
      {
        "date": "2023-01-01",
        "views": 100,
        "plays": 50,
        "downloads": 20
      },
      {
        "date": "2023-01-02",
        "views": 120,
        "plays": 60,
        "downloads": 25
      },
      // ...
    ],
    "summary": {
      "total_views": 220,
      "total_plays": 110,
      "total_downloads": 45,
      "date_range": {
        "start": "2023-01-01",
        "end": "2023-01-02"
      }
    }
  }
}

Examples