Gateway API Documentation

Kling v3 Motion ControlServer to ServerWhite Label

Base URL: https://raysky.extremeaffiliate.web.id

Billing: per second | Max durasi: 30 detik

Portal user: /portal/login

Quick Start

1

Topup Saldo

Login ke portal lalu topup QRIS.

/portal/login
2

Cek Saldo

Cek saldo sebelum generate.

GET /v1/balance
3

Create Job

Kirim job motion control via backend server.

POST /v1/motion/generate
4

Polling Result

Ambil status job sampai selesai.

GET /v1/motion/:jobId

Token akses hanya disimpan di backend server, bukan di frontend/browser.

Autentikasi

Gunakan salah satu header berikut untuk endpoint /v1/*.

x-access-token: <ACCESS_TOKEN>
atau
Authorization: Bearer <ACCESS_TOKEN>

Endpoint Utama

MethodPathKeterangan
GET/v1/pricingHarga aktif dan konfigurasi billing per detik.
GET/v1/balanceSaldo user dan estimasi sisa generate.
GET/v1/transactionsRiwayat saldo debit/kredit.
POST/v1/motion/generateBuat job motion control. Opsi mode: std atau pro.
GET/v1/motion/:jobIdCek status job.
GET/v1/media/:mediaIdDetail file hasil.

Topup QRIS dilakukan via portal: /portal/login.

Contoh Request

Pricing

curl -X GET 'https://raysky.extremeaffiliate.web.id/v1/pricing' \
  -H 'x-access-token: ACCESS_TOKEN'

Generate Video

curl -X POST 'https://raysky.extremeaffiliate.web.id/v1/motion/generate' \
  -H 'Content-Type: application/json' \
  -H 'x-access-token: ACCESS_TOKEN' \
  -d '{
  "imageUrl": "https://.../image.jpg",
  "referenceVideoUrl": "https://.../ref.mp4",
  "mode": "pro",
  "prompt": "",
  "durationSec": 30
}'

Charge formula: ceil(durationSec * RATE_BY_MODE), dengan mode=std|pro.

Backend Proxy (Node.js)

import express from "express";
import fetch from "node-fetch";

const app = express();
app.use(express.json());

const GATEWAY_BASE = "https://raysky.extremeaffiliate.web.id";
const ACCESS_TOKEN = process.env.GATEWAY_TOKEN;

app.post("/api/motion/generate", async (req, res) => {
  try {
    const r = await fetch(GATEWAY_BASE + "/v1/motion/generate", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-access-token": ACCESS_TOKEN
      },
      body: JSON.stringify(req.body)
    });
    const data = await r.json();
    res.status(r.status).json(data);
  } catch (err) {
    res.status(500).json({ ok: false, error: { message: "gateway unreachable" } });
  }
});

app.get("/api/motion/:jobId", async (req, res) => {
  const r = await fetch(GATEWAY_BASE + "/v1/motion/" + encodeURIComponent(req.params.jobId), {
    headers: { "x-access-token": ACCESS_TOKEN }
  });
  const data = await r.json();
  res.status(r.status).json(data);
});

app.get("/api/balance", async (_req, res) => {
  const r = await fetch(GATEWAY_BASE + "/v1/balance", {
    headers: { "x-access-token": ACCESS_TOKEN }
  });
  const data = await r.json();
  res.status(r.status).json(data);
});

app.listen(3000);

Error Code

HTTPKodeKeterangan
401missing_client_key / invalid_client_keyToken akses tidak ada atau tidak valid.
402insufficient_balanceSaldo tidak cukup untuk generate.
429rate_limitedTerlalu banyak request.
5xxupstream_error / lainnyaGangguan sementara, lakukan retry bertahap.