Dokumentacja Rivya AI

Rivya TypeScript SDK

Używaj wersji beta zestawu Rivya TypeScript SDK do obsługi modeli, generowania, plików, kredytów, webhooków i czatu w Public API v1, także przez strumień SSE.

Ostatni przegląd: 2026/08/29

Rivya udostępnia betę TypeScript SDK dla serwerowych integracji Public API.

SDK jest cienkim klientem nad Rivya Public API v1. Kontraktem niższego poziomu pozostaje Kontrakt OpenAPI i schemat, a metody SDK muszą być zgodne z tym schematem.

SDK opisuje wdrożone zachowanie klienta. Żądania nadal wymagają włączonego Public API, ważnego klucza konta i modelu, którego bieżący status API pozwala na żądaną operację.

Stan

Pakiet jest obecnie utrzymywany w tym repozytorium jako prywatna beta. Nie jest publikowany do npm, dopóki nazwa pakietu, metadane, changelog i proces wydania nie zostaną wyraźnie zatwierdzone.

SDK obsługuje:

  • listowanie modeli

  • tworzenie i pobieranie asynchronicznych generowań

  • przesyłanie i pobieranie plików przez Files API

  • pobieranie salda kredytów

  • zarządzanie endpointami webhooków, testowe dostawy, listowanie zdarzeń, listowanie dostaw i rotację sekretu

  • weryfikację podpisów webhooków

  • odpowiedzi czatu bez strumienia i ze strumieniem oraz sesje utworzone przez API

Strumieniowe odpowiedzi czatu są dostępne w tej prywatnej wersji beta dzięki przetwarzaniu SSE po stronie serwera. Trzymaj tajne klucze API na swoim serwerze.

Instalacja w Tym Repozytorium

Gdy SDK jest w becie, używaj lokalnego źródła pakietu:

pnpm --dir packages/rivya-sdk typecheck

Kod aplikacji powinien trzymać sekretny klucz API po stronie serwera:

import { RivyaClient } from "@rivya/sdk";

const rivya = new RivyaClient({
  apiKey: process.env.RIVYA_API_KEY
});

Nie umieszczaj sekretnych kluczy API w bundle'ach przeglądarkowych, localStorage, zdarzeniach analitycznych, zrzutach ekranu ani współdzielonych zgłoszeniach.

Listuj Modele

models.list jest publiczne i nie wymaga klucza API:

const models = await rivya.models.list();

for (const model of models.data) {
  console.log(model.id, model.api_status, model.supported_api_inputs);
}

Utwórz Generowanie

Użyj generations.create do asynchronicznego generowania obrazu, wideo albo audio:

const generation = await rivya.generations.create(
  {
    model: "z-image",
    prompt: "Czyste, redakcyjne zdjęcie produktu na miękkim tle studyjnym",
    client_request_id: "order-123-preview"
  },
  {
    idempotencyKey: "order-123-preview"
  }
);

console.log(generation.id, generation.status);

Następnie odpytuj przez generations.retrieve:

const current = await rivya.generations.retrieve(generation.id);
console.log(current.status, current.result?.primary_url);

Używaj Idempotency-Key dla produkcyjnych żądań zapisu. SDK udostępnia to jako idempotencyKey.

Przesyłanie plików

Użyj files.upload dla obrazów, wideo albo audio referencyjnego:

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);

Użyj files.retrieve, aby ponownie odczytać metadane przesłanego pliku:

const sameFile = await rivya.files.retrieve(uploaded.id);
console.log(sameFile.mime_type, sameFile.duration_token);

Gdy używasz pliku w generowaniu, przekaż zwrócone pola publiczne przez params.referenceMediaItems:

await rivya.generations.create({
  model: "nano-banana-2-lite",
  prompt: "Zmień styl zdjęcia produktu tak, aby pasowało do czystej, redakcyjnej strony katalogu",
  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
      }
    ]
  }
});

Każdy obraz referencyjny Image5 lub Grok Imagine Image 2.0 wymaga pól width, height, size_bytes i image_dimensions_token z pierwotnej odpowiedzi na przesłanie pliku powiązanego z modelem. Późniejsze wywołanie files.retrieve może zwrócić token jako null; zamiast zgadywać typ MIME, wymiary lub rozmiar w bajtach, ponownie prześlij obraz źródłowy. Layer Decomposition dodatkowo egzekwuje limity geometrii dla jednego obrazu; Grok Image 2 akceptuje od jednego do pięciu podpisanych obrazów referencyjnych w formacie JPEG, PNG lub WebP do standardowej edycji.

Dla referencyjnego pliku wideo Video8 użyj pól video_width, video_height, frames_per_second, video_bitrate_mbps, video_file_size_bytes i video_metadata_token z pierwotnej odpowiedzi na przesłanie pliku powiązanego z modelem jako odpowiednio width, height, framesPerSecond, videoBitrateMbps, sizeBytes i videoMetadataToken. Zachowaj durationSeconds i durationToken jako osobne podpisane potwierdzenie czasu trwania. Jeśli któregoś tokenu brakuje w późniejszym wyniku files.retrieve, ponownie prześlij źródłowy plik wideo.

Wan 3.0 używa tego samego mapowania pól SDK we wzajemnie wykluczających się scenach text, frames i reference. Każdą referencję prześlij z model: "wan-3-0-video"; obrazy wymagają podpisanych pól obrazu, wideo wymaga zarówno podpisanego czasu trwania, jak i metadanych wideo, a audio wymaga pierwotnych wartości mime_type, size_bytes, duration_seconds i duration_token. Ustaw seedance_scene, variant, resolution, aspect_ratio, duration, audio i opcjonalny seed wewnątrz params. Inteligentny czas trwania ma wartość -1, rezerwuje 30 sekund i nie może być łączony z referencyjnym plikiem wideo; skróty przekształcania pliku w wideo i linku w wideo pozostają niedostępne.

Sprawdź Kredyty

const credits = await rivya.credits.retrieve();
console.log(credits.current_credits);

Zarządzaj Webhookami

Gdy dostęp do webhooków jest włączony dla wdrożenia i konta, utwórz punkt końcowy webhooka:

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 jest zwracany tylko przy tworzeniu punktu końcowego albo zmianie sekretu. Przechowuj go na swoim serwerze.

Inne helpery webhooków:

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 });

Weryfikuj podpisy dostaw, zanim zaufasz payloadom webhooków:

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");
}

Helper SDK używa tego samego kontraktu HMAC-SHA256, który dokumentuje API Webhooks.

Chat

Użyj chat.completions.create dla jednej niestreamingowej tury Chat API:

const completion = await rivya.chat.completions.create(
  {
    model: "claude-sonnet-5-chat",
    message: "Napisz zwięzły plan uruchomienia nowej kampanii obrazów produktowych",
    client_request_id: "chat-001"
  },
  {
    idempotencyKey: "chat-001"
  }
);

console.log(completion.session_id, completion.message.content);

Kontynuuj ze zwróconym session_id:

await rivya.chat.completions.create({
  model: "claude-sonnet-5-chat",
  session_id: completion.session_id,
  message: "Teraz zmień go w pięciopunktową listę działań."
});

Odczytuj sesje utworzone przez API:

await rivya.chat.sessions.list({ limit: 20 });
await rivya.chat.sessions.retrieve(completion.session_id);

Użyj chat.completions.stream, aby odbierać zdarzenia Server-Sent Events jako iterator asynchroniczny:

const stream = await rivya.chat.completions.stream(
  {
    model: "claude-sonnet-5-chat",
    message: "Napisz zwięzły plan uruchomienia nowej kampanii obrazów produktowych",
    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 służy tylko do wyświetlania. Zatwierdzony wynik jest dostępny po message.completed i można go później odczytać przez chat.sessions.retrieve.

Błędy

SDK rzuca RivyaAPIError dla odpowiedzi Public API innych niż 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 zawiera status HTTP, publiczny kod i komunikat błędu, identyfikator żądania, jeśli jest dostępny, oraz bezpieczny podzbiór nagłówków odpowiedzi.

Walidacja

Uruchom kontrole SDK, zanim uznasz zmianę za ukończoną:

pnpm sdk:check
pnpm --dir packages/rivya-sdk typecheck
pnpm content:api-docs

pnpm sdk:check obejmuje statyczną kontrolę kontraktu oraz test bez dostępu do sieci: sprawdza przetwarzanie błędów, bezpieczne nagłówki odpowiedzi z błędem, nagłówki idempotencji, autoryzację Bearer, publiczną listę modeli, przetwarzanie strumienia SSE czatu, zdarzenia błędów w tym strumieniu oraz weryfikację podpisów webhooków.

Powiązane Strony