Chistream / API Docs
Kembali

Chistream API

API publik buat integrasi download YouTube/TikTok/Instagram/Facebook ke bot WhatsApp, aplikasi, atau apapun yang kamu buat sendiri. Butuh API key - generate gratis lewat tombol di halaman utama.

Base URL

https://chistream.my.id

Autentikasi

Header: X-API-Key

Rate Limit

5/menit/key (default)

1. Dapetin API Key

Wajib punya akun dulu. Paling gampang lewat daftar/login, terus generate key di dashboard - atau langsung lewat API kayak di bawah. Key cuma ditampilin sekali - simpen baik-baik.

# 1a. Daftar akun (skip kalau udah punya)
curl -X POST https://chistream.my.id/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{"username": "namamu", "password": "password_kamu"}'

# 1b. Login buat dapetin token
curl -X POST https://chistream.my.id/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "namamu", "password": "password_kamu"}'

# Balasan: { "success": true, "token": "eyJ...", "user": {...} }

# 1c. Generate API key pakai token dari langkah login
curl -X POST https://chistream.my.id/api/keys/generate \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJ..." \
  -d '{"label": "Bot WhatsApp saya"}'

# Balasan:
# { "success": true, "key": "cs_xxxxxxxxxxxxxxxxxxxxxxxx", "warning": "..." }

Default limit tiap akun baru: 5 request/menit. Butuh lebih? Upgrade plan di billing.

⏳ Key otomatis kadaluarsa 5 hari sejak dibuat - generate key baru lewat dashboard kalau udah lewat.

API Key buat Coba Langsung

Tempel API key kamu di sini sekali - dipakai otomatis sama semua tombol "Jalankan" di dokumentasi ini (biar bisa langsung liat respons ASLI dari server, bukan contoh doang). Cuma disimpen di browser kamu sendiri (localStorage), gak dikirim ke mana-mana selain ke API Chistream pas kamu klik Jalankan.

2. Endpoint yang Tersedia

POST /api/v1/download

Bikin job download baru. Body JSON: url (link video), format (contoh: mp3, mp4_360p, mp4_720p). Balikin jobId buat dicek statusnya.

GET /api/v1/status/:jobId

Cek progress/status job. Poll tiap beberapa detik sampai status jadi COMPLETED (ambil downloadUrl) atau FAILED/CANCELLED.

GET /api/v1/search?q=...

Cari video YouTube berdasarkan kata kunci (5 hasil teratas).

⚠️ File hasil download otomatis terhapus dari server 10 menit setelah selesai diproses (Burn After Download), jadi ambil filenya secepatnya.

Donghua (donghub.vip)

GET /api/donghua/home?page=1 TANPA BATAS

Daftar update Donghua terbaru dari beranda, dengan pagination.

GET /api/donghua/search?q=... TANPA BATAS

Cari judul Donghua berdasarkan kata kunci.

GET /api/donghua/detail?url=... TANPA BATAS

Info lengkap + daftar episode dari 1 judul Donghua (pakai link dari hasil search/home).

GET /api/donghua/stream?url=... TANPA BATAS

Ambil link stream/embed mentah dari 1 episode (pakai link episode dari detail). Cuma link, bukan file.

POST /api/donghua/download KENA KUOTA TIER

Body JSON: url (link episode). Beda sama /stream - ini ngasih FILE beneran (lewat sistem job yang sama kayak /api/v1/download). Kuota per bulan: Free 1x, Basic 10x, Pro 100x - reset tiap 30 hari.

GET /api/donghua/quota

Cek sisa kuota download-file Donghua bulan ini buat akun kamu.

Coba Langsung (Live)

Isi API key di kotak biru di atas, terus klik Jalankan - request beneran dikirim ke server Chistream dan respons aslinya muncul di bawah. Cuma field API key yang bisa diganti; URL/parameter lainnya udah dikunci ke contoh yang aman biar gak disalahgunakan.

cari video YouTube
$ curl -H "X-API-Key: ••••••••" GET https://chistream.my.id/api/v1/search?q=faded alan walker

                    
bikin job download (mp3)
$ curl -X POST -H "X-API-Key: ••••••••" -d '{"url":"...","format":"mp3"}' https://chistream.my.id/api/v1/download

                    
cek status job di atas
$ curl -H "X-API-Key: ••••••••" GET https://chistream.my.id/api/v1/status/{jobId}

Jalankan dulu contoh "bikin job download" di atas buat isi {jobId}-nya otomatis.


                    
update Donghua terbaru
$ curl -H "X-API-Key: ••••••••" GET https://chistream.my.id/api/donghua/home?page=1

                    
sisa kuota download Donghua
$ curl -H "X-API-Key: ••••••••" GET https://chistream.my.id/api/donghua/quota

                    

3. Contoh Alur Lengkap (Download → Cek Status)

# 1. Bikin job download
curl -X POST https://chistream.my.id/api/v1/download \
  -H "X-API-Key: cs_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://youtu.be/VIDEO_ID", "format": "mp3"}'

# Balasan: { "success": true, "jobId": "abc-123", "title": "..." }

# 2. Poll status pakai jobId di atas (ulangi tiap 2-3 detik)
curl https://chistream.my.id/api/v1/status/abc-123 \
  -H "X-API-Key: cs_xxxxxxxxxxxxxxxxxxxxxxxx"

# Kalau status COMPLETED, ambil field "downloadUrl" dari balasannya
const API_KEY = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx';
const BASE_URL = 'https://chistream.my.id';

async function downloadFromChistream(url, format = 'mp3') {
  // 1. Bikin job download
  const startRes = await fetch(`${BASE_URL}/api/v1/download`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': API_KEY,
    },
    body: JSON.stringify({ url, format }),
  });
  const startData = await startRes.json();
  if (!startData.success) throw new Error(startData.error);

  const jobId = startData.jobId;

  // 2. Poll sampai selesai
  while (true) {
    await new Promise((r) => setTimeout(r, 2000));
    const statusRes = await fetch(`${BASE_URL}/api/v1/status/${jobId}`, {
      headers: { 'X-API-Key': API_KEY },
    });
    const statusData = await statusRes.json();

    if (statusData.status === 'COMPLETED') return statusData;
    if (statusData.status === 'FAILED' || statusData.status === 'CANCELLED') {
      throw new Error(statusData.error || 'Download gagal');
    }
  }
}

downloadFromChistream('https://youtu.be/VIDEO_ID', 'mp3')
  .then((r) => console.log('Selesai:', r.downloadUrl))
  .catch((e) => console.error('Error:', e.message));
const axios = require('axios');

const API_KEY = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx';
const BASE_URL = 'https://chistream.my.id';
const headers = { 'X-API-Key': API_KEY };

async function downloadFromChistream(url, format = 'mp3') {
  const { data: start } = await axios.post(
    `${BASE_URL}/api/v1/download`,
    { url, format },
    { headers }
  );
  if (!start.success) throw new Error(start.error);

  let result;
  while (true) {
    await new Promise((r) => setTimeout(r, 2000));
    const { data: status } = await axios.get(
      `${BASE_URL}/api/v1/status/${start.jobId}`,
      { headers }
    );
    if (status.status === 'COMPLETED') { result = status; break; }
    if (status.status === 'FAILED' || status.status === 'CANCELLED') {
      throw new Error(status.error || 'Download gagal');
    }
  }
  return result;
}

downloadFromChistream('https://youtu.be/VIDEO_ID', 'mp3')
  .then((r) => console.log('Selesai:', r.downloadUrl))
  .catch((e) => console.error('Error:', e.message));
import requests
import time

API_KEY = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx'
BASE_URL = 'https://chistream.my.id'
headers = {'X-API-Key': API_KEY}


def download_from_chistream(url, fmt='mp3'):
    start = requests.post(
        f'{BASE_URL}/api/v1/download',
        json={'url': url, 'format': fmt},
        headers=headers,
    ).json()
    if not start.get('success'):
        raise Exception(start.get('error'))

    job_id = start['jobId']

    while True:
        time.sleep(2)
        status = requests.get(
            f'{BASE_URL}/api/v1/status/{job_id}', headers=headers
        ).json()

        if status['status'] == 'COMPLETED':
            return status
        if status['status'] in ('FAILED', 'CANCELLED'):
            raise Exception(status.get('error', 'Download gagal'))


result = download_from_chistream('https://youtu.be/VIDEO_ID', 'mp3')
print('Selesai:', result['downloadUrl'])
<?php

$apiKey = 'cs_xxxxxxxxxxxxxxxxxxxxxxxx';
$baseUrl = 'https://chistream.my.id';

function chistreamRequest($method, $path, $apiKey, $body = null) {
    $ch = curl_init("https://chistream.my.id{$path}");
    $headers = ["X-API-Key: {$apiKey}"];
    if ($body !== null) {
        $headers[] = 'Content-Type: application/json';
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $res = curl_exec($ch);
    curl_close($ch);
    return json_decode($res, true);
}

$start = chistreamRequest('POST', '/api/v1/download', $apiKey, [
    'url' => 'https://youtu.be/VIDEO_ID',
    'format' => 'mp3',
]);

if (!$start['success']) {
    die('Error: ' . $start['error']);
}

$jobId = $start['jobId'];

while (true) {
    sleep(2);
    $status = chistreamRequest('GET', "/api/v1/status/{$jobId}", $apiKey);

    if ($status['status'] === 'COMPLETED') {
        echo 'Selesai: ' . $status['downloadUrl'];
        break;
    }
    if (in_array($status['status'], ['FAILED', 'CANCELLED'])) {
        die('Download gagal: ' . ($status['error'] ?? ''));
    }
}
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

const apiKey = "cs_xxxxxxxxxxxxxxxxxxxxxxxx"
const baseURL = "https://chistream.my.id"

func chistreamRequest(method, path string, body any) map[string]any {
	var reqBody io.Reader
	if body != nil {
		b, _ := json.Marshal(body)
		reqBody = bytes.NewReader(b)
	}
	req, _ := http.NewRequest(method, baseURL+path, reqBody)
	req.Header.Set("X-API-Key", apiKey)
	if body != nil {
		req.Header.Set("Content-Type", "application/json")
	}
	resp, _ := http.DefaultClient.Do(req)
	defer resp.Body.Close()

	var out map[string]any
	json.NewDecoder(resp.Body).Decode(&out)
	return out
}

func main() {
	start := chistreamRequest("POST", "/api/v1/download", map[string]string{
		"url":    "https://youtu.be/VIDEO_ID",
		"format": "mp3",
	})
	if start["success"] != true {
		panic(start["error"])
	}
	jobID := start["jobId"].(string)

	for {
		time.Sleep(2 * time.Second)
		status := chistreamRequest("GET", "/api/v1/status/"+jobID, nil)

		switch status["status"] {
		case "COMPLETED":
			fmt.Println("Selesai:", status["downloadUrl"])
			return
		case "FAILED", "CANCELLED":
			panic(status["error"])
		}
	}
}

4. Kode Error

Status Arti
401API key gak ada / gak valid / dinonaktifin.
400Body/parameter request gak lengkap (misal url kosong).
404jobId gak ditemukan.
429Kelewat 5 request/menit buat key ini - tunggu bentar.
500Error internal server (link salah, video private, dll).

5. Catatan