Rivya TypeScript SDK สำหรับนักพัฒนา
ใช้ Rivya TypeScript SDK รุ่นทดสอบเพื่อเรียก Public API v1 สำหรับโมเดล งานสร้าง ไฟล์ เครดิต เว็บฮุก และแชต รวมถึงการสตรีมผ่าน SSE
ตรวจล่าสุดเมื่อ 2026/08/29
Rivya มี TypeScript SDK รุ่นทดสอบสำหรับเชื่อมต่อ Public API จากฝั่งเซิร์ฟเวอร์
SDK เป็นไคลเอนต์ขนาดเล็กที่ทำงานบนสัญญาเชื่อมต่อของ Rivya Public API v1 โดย สัญญาและโครงสร้าง OpenAPI ยังคงเป็นข้อกำหนดระดับล่าง และเมธอดของ SDK ต้องสอดคล้องกับโครงสร้างดังกล่าว
SDK อธิบายพฤติกรรมไคลเอนต์ที่ระบบรองรับ การส่งคำขอจริงยังต้องเปิด Public API ในระบบที่นำไปใช้งาน ใช้คีย์ของบัญชีที่ถูกต้อง และเลือกโมเดลที่สถานะ API ปัจจุบันอนุญาตให้เรียกใช้งาน
สถานะ
ขณะนี้แพ็กเกจได้รับการดูแลภายในคลังโค้ดนี้ในฐานะรุ่นทดสอบแบบส่วนตัว และจะยังไม่เผยแพร่บน npm จนกว่าจะอนุมัติชื่อแพ็กเกจ ข้อมูลประกอบ บันทึกการเปลี่ยนแปลง และกระบวนการเผยแพร่อย่างชัดเจน
SDK รองรับ:
รายการโมเดล
สร้างและเรียกดูงานแบบอะซิงโครนัส
อัปโหลดและเรียกดูไฟล์ผ่าน API
ดึงยอดเครดิต
จัดการปลายทางเว็บฮุก ทดสอบการส่ง เรียกดูเหตุการณ์และประวัติการส่ง รวมถึงหมุนเวียนข้อมูลลับ
ตรวจสอบลายเซ็นเว็บฮุก
เรียกแชตทั้งแบบปกติและแบบสตรีม รวมถึงเซสชันแชตที่สร้างผ่าน API
รุ่นทดสอบส่วนตัวนี้รองรับการสตรีมแชตผ่านตัวแยกวิเคราะห์ SSE ฝั่งเซิร์ฟเวอร์ โปรดเก็บคีย์ API ไว้บนเซิร์ฟเวอร์ของคุณเท่านั้น
ติดตั้งภายในคลังโค้ดนี้
ใช้ซอร์สแพ็กเกจในเครื่องระหว่างที่ SDK ยังเป็นรุ่นทดสอบ:
pnpm --dir packages/rivya-sdk typecheckโค้ดแอปพลิเคชันควรเก็บคีย์ API ไว้บนเซิร์ฟเวอร์:
import { RivyaClient } from "@rivya/sdk";
const rivya = new RivyaClient({
apiKey: process.env.RIVYA_API_KEY
});อย่าใส่คีย์ API ในชุดไฟล์ฝั่งเบราว์เซอร์ localStorage เหตุการณ์วิเคราะห์ ภาพหน้าจอ หรือทิกเก็ตที่แชร์ร่วมกัน
เรียกรายการโมเดล
models.list เป็นปลายทางสาธารณะและไม่ต้องใช้คีย์ API:
const models = await rivya.models.list();
for (const model of models.data) {
console.log(model.id, model.api_status, model.supported_api_inputs);
}สร้างงาน
ใช้ generations.create เพื่อสร้างภาพ วิดีโอ หรือเสียงแบบอะซิงโครนัส:
const generation = await rivya.generations.create(
{
model: "z-image",
prompt: "A clean editorial product image on a soft studio background",
client_request_id: "order-123-preview"
},
{
idempotencyKey: "order-123-preview"
}
);
console.log(generation.id, generation.status);จากนั้น ตรวจสถานะซ้ำ ด้วย generations.retrieve:
const current = await rivya.generations.retrieve(generation.id);
console.log(current.status, current.result?.primary_url);ใช้ Idempotency-Key กับคำขอเขียนข้อมูลในระบบจริง โดย SDK เปิดรับค่าเดียวกันผ่านชื่อ idempotencyKey
อัปโหลดไฟล์
ใช้ files.upload สำหรับ ภาพอ้างอิง, วิดีโอ หรือ เสียง:
import { readFile } from "node:fs/promises";
const file = new Blob([await readFile("./reference.png")], {
type: "image/png"
});
const uploaded = await rivya.files.upload({
file,
filename: "reference.png",
kind: "image",
model: "nano-banana-2-lite",
client_request_id: "asset-123"
});
console.log(uploaded.id, uploaded.url);ใช้ files.retrieve เพื่ออ่าน ข้อมูลประกอบ ของไฟล์ที่อัปโหลดแล้วอีกครั้ง:
const sameFile = await rivya.files.retrieve(uploaded.id);
console.log(sameFile.mime_type, sameFile.duration_token);เมื่อใช้ไฟล์ใน การสร้าง ให้ส่ง สาธารณะ ช่องข้อมูล ที่ได้กลับมาผ่าน params.referenceMediaItems:
await rivya.generations.create({
model: "nano-banana-2-lite",
prompt: "Restyle this product photo for a clean editorial catalog page",
params: {
referenceMediaItems: [
{
url: uploaded.url,
kind: uploaded.kind,
name: uploaded.file_name,
mimeType: uploaded.mime_type,
durationSeconds: uploaded.duration_seconds ?? undefined,
durationToken: uploaded.duration_token ?? undefined,
width: uploaded.video_width ?? uploaded.width ?? undefined,
height: uploaded.video_height ?? uploaded.height ?? undefined,
sizeBytes: uploaded.video_file_size_bytes ?? uploaded.size_bytes,
imageDimensionsToken: uploaded.image_dimensions_token ?? undefined,
framesPerSecond: uploaded.frames_per_second ?? undefined,
videoBitrateMbps: uploaded.video_bitrate_mbps ?? undefined,
videoMetadataToken: uploaded.video_metadata_token ?? undefined
}
]
}
});รูปอ้างอิงทุกภาพของ Image5 และ Grok Imagine ภาพ 2.0 ต้องใช้ width, height, size_bytes และ image_dimensions_token จากคำตอบการอัปโหลดเดิมที่ผูกกับโมเดล การเรียก files.retrieve ภายหลังอาจคืนโทเคนเป็น null ในกรณีนั้นให้อัปโหลดรูปต้นฉบับใหม่แทนการคาดเดาประเภท MIME ขนาดภาพ หรือจำนวนไบต์ ขั้นตอนแยกงานยังบังคับใช้ขีดจำกัดทางเรขาคณิตสำหรับรูปภาพหนึ่งรูป ส่วน Grok ภาพ 2 รองรับรูปอ้างอิง JPEG, PNG หรือ WebP ที่ลงลายเซ็นแล้ว 1–5 รูปสำหรับการแก้ไขภาพแบบมาตรฐาน
สำหรับวิดีโออ้างอิงของ Video8 ให้นำ video_width, video_height, frames_per_second, video_bitrate_mbps, video_file_size_bytes และ video_metadata_token จากคำตอบการอัปโหลดเดิมที่ผูกกับโมเดล มาใส่ใน width, height, framesPerSecond, videoBitrateMbps, sizeBytes และ videoMetadataToken ตามลำดับ เก็บ durationSeconds และ durationToken เป็นหลักฐานระยะเวลาที่ลงลายเซ็นแยกต่างหาก หากโทเคนใดหายไปเมื่อเรียก files.retrieve ภายหลัง ให้อัปโหลดวิดีโอต้นฉบับใหม่
Wan 3.0 ใช้การจับคู่ฟิลด์ SDK แบบเดียวกันในโหมด text, frames และ reference ซึ่งเลือกใช้ได้ครั้งละหนึ่งโหมด อัปโหลดข้อมูลอ้างอิงแต่ละรายการด้วย model: "wan-3-0-video" รูปภาพต้องใช้ฟิลด์รูปภาพที่ลงลายเซ็น วิดีโอต้องใช้ทั้งระยะเวลาและข้อมูลประกอบที่ลงลายเซ็น ส่วนเสียงต้องใช้ค่าเดิมของ mime_type, size_bytes, duration_seconds และ duration_token กำหนด seedance_scene, variant, resolution, aspect_ratio, duration, audio และ seed ซึ่งเป็นตัวเลือกภายใน params ระยะเวลาอัจฉริยะใช้ค่า -1 มีค่าสำรอง 30 วินาที และใช้ร่วมกับวิดีโออ้างอิงไม่ได้ ส่วนทางลัดจากไฟล์เป็นวิดีโอและจากลิงก์เป็นวิดีโอยังไม่พร้อมใช้งาน
ตรวจ เครดิต
const credits = await rivya.credits.retrieve();
console.log(credits.current_credits);จัดการ เว็บฮุก
เมื่อ ระบบที่นำไปใช้งาน และบัญชีเปิดสิทธิ์ใช้ เว็บฮุก ให้สร้าง เว็บฮุก จุดเชื่อมต่อ:
const endpoint = await rivya.webhooks.create({
name: "Production webhook",
url: "https://example.com/rivya/webhook",
event_types: ["generation.succeeded", "generation.failed"]
});
console.log(endpoint.id, endpoint.signing_secret);signing_secret จะคืนเฉพาะหลัง สร้าง หรือ หมุน การเรียก เท่านั้น เก็บไว้บน เซิร์ฟเวอร์ ของคุณ
เมธอดช่วยเหลืออื่นสำหรับเว็บฮุก:
await rivya.webhooks.list();
await rivya.webhooks.retrieve(endpoint.id);
await rivya.webhooks.update(endpoint.id, { status: "disabled" });
await rivya.webhooks.test(endpoint.id);
await rivya.webhooks.rotateSecret(endpoint.id);
await rivya.webhooks.deliveries.list(endpoint.id, { limit: 20 });
await rivya.webhookEvents.list({ limit: 20 });ตรวจลายเซ็นการส่งก่อนเชื่อถือเพย์โหลดของเว็บฮุก:
import { verifyRivyaWebhookSignature } from "@rivya/sdk";
const ok = await verifyRivyaWebhookSignature({
rawBody,
timestamp: request.headers.get("rivya-webhook-timestamp") || "",
signatureHeader: request.headers.get("rivya-webhook-signature") || "",
signingSecret: process.env.RIVYA_WEBHOOK_SIGNING_SECRET || ""
});
if (!ok) {
throw new Error("Invalid Rivya webhook signature");
}เมธอดช่วยเหลือของ SDK ใช้สัญญา HMAC-SHA256 ชุดเดียวกับที่ระบุไว้ใน API เว็บฮุก
การใช้งาน การสนทนา
ใช้ chat.completions.create สำหรับเรียก Chat API หนึ่งรอบแบบไม่สตรีม:
const completion = await rivya.chat.completions.create(
{
model: "claude-sonnet-5-chat",
message: "Write a concise launch plan for a new product image campaign",
client_request_id: "chat-001"
},
{
idempotencyKey: "chat-001"
}
);
console.log(completion.session_id, completion.message.content);สนทนาต่อด้วย session_id ที่ได้กลับมา:
await rivya.chat.completions.create({
model: "claude-sonnet-5-chat",
session_id: completion.session_id,
message: "Now turn that into a 5-step execution checklist."
});อ่านเซสชันที่สร้างผ่าน API:
await rivya.chat.sessions.list({ limit: 20 });
await rivya.chat.sessions.retrieve(completion.session_id);ใช้ chat.completions.stream เพื่ออ่านเหตุการณ์ที่เซิร์ฟเวอร์ส่งมาอย่างต่อเนื่อง (SSE) ผ่านตัววนซ้ำแบบอะซิงโครนัส:
const stream = await rivya.chat.completions.stream(
{
model: "claude-sonnet-5-chat",
message: "Write a concise launch plan for a new product image campaign",
client_request_id: "chat-stream-001"
},
{
idempotencyKey: "chat-stream-001"
}
);
for await (const event of stream) {
if (event.event === "message.delta") {
process.stdout.write(event.data.delta);
}
if (event.event === "message.completed") {
console.log(event.data.message.id);
}
}message.delta ใช้สำหรับแสดงผลเท่านั้น ผลลัพธ์ที่ ตัดสินใจใช้ แล้วจะพร้อมหลัง message.completed และอ่านภายหลังได้ด้วย chat.sessions.retrieve
ข้อผิดพลาด
SDK จะส่งข้อผิดพลาด RivyaAPIError เมื่อ Public API ตอบกลับด้วยสถานะที่ไม่ใช่ 2xx:
import { RivyaAPIError } from "@rivya/sdk";
try {
await rivya.generations.retrieve("task_missing");
} catch (error) {
if (error instanceof RivyaAPIError) {
console.log(error.status, error.code, error.requestId);
}
}RivyaAPIError มีสถานะ HTTP รหัสข้อผิดพลาดสาธารณะ ข้อความ รหัสคำขอเมื่อมี และส่วนหัวคำตอบเฉพาะรายการที่เปิดเผยได้อย่างปลอดภัย
การตรวจสอบ
รันการตรวจสอบ SDK ก่อนถือว่าการเปลี่ยนแปลงเสร็จสมบูรณ์:
pnpm sdk:check
pnpm --dir packages/rivya-sdk typecheck
pnpm content:api-docspnpm sdk:check รวมการตรวจสัญญาแบบสถิตและการตรวจรันไทม์โดยไม่ใช้เครือข่าย ครอบคลุมการแยกวิเคราะห์ข้อผิดพลาด ส่วนหัวข้อผิดพลาดที่ปลอดภัย ส่วนหัวสำหรับป้องกันคำขอซ้ำ การยืนยันตัวตนแบบ Bearer รายการโมเดลสาธารณะ การแยกวิเคราะห์ SSE ของแชตสตรีม เหตุการณ์ข้อผิดพลาดจากแชตสตรีม และการตรวจลายเซ็นเว็บฮุก
