Rivya AI Docs

Rivya TypeScript SDK

Use the Rivya TypeScript SDK beta to call Public API v1 for models, generations, files, credits, webhooks, and Chat including SSE streaming.

Last reviewed on 2026/05/11

Rivya provides a TypeScript SDK beta for server-side Public API integrations.

The SDK is a thin client over Rivya Public API v1. The lower-level contract remains OpenAPI and Schema Contract, and SDK methods must stay aligned with that schema.

Status

The package is currently maintained inside this repository as a private beta. It is not published to npm until the package name, metadata, changelog, and release process are explicitly approved.

The SDK supports:

  • model listing
  • asynchronous generation create and retrieve
  • Files API upload and retrieve
  • credit balance retrieval
  • webhook endpoint management, test deliveries, event listing, delivery listing, and secret rotation
  • webhook signature verification
  • non-streaming and streaming Chat completions, plus API-created chat sessions

Chat streaming is available in this private beta through server-side SSE parsing. Keep secret API keys on your server.

Install In This Repo

Use the local package source while the SDK is in beta:

pnpm --dir packages/rivya-sdk typecheck

Application code should keep the secret API key on the server:

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

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

Do not place secret API keys in browser bundles, localStorage, analytics events, screenshots, or shared tickets.

List Models

models.list is public and does not require an API key:

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

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

Create A Generation

Use generations.create for asynchronous image, video, or audio generation:

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

Then poll with generations.retrieve:

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

Use Idempotency-Key for production write requests. The SDK exposes this as idempotencyKey.

Upload Files

Use files.upload for reference images, videos, or audio:

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",
  client_request_id: "asset-123"
});

console.log(uploaded.id, uploaded.url);

Use files.retrieve to read uploaded metadata again:

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

When using a file in a generation, pass the returned public fields through params.referenceMediaItems:

await rivya.generations.create({
  model: "nano-banana-2",
  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
      }
    ]
  }
});

Check Credits

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

Manage Webhooks

Create a webhook endpoint:

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

The signing_secret is returned only after create or rotate calls. Store it on your server.

Other webhook helpers:

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

Verify delivery signatures before trusting webhook payloads:

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

The SDK helper uses the same HMAC-SHA256 contract documented in API Webhooks.

Chat

Use chat.completions.create for one non-streaming Chat API turn:

const completion = await rivya.chat.completions.create(
  {
    model: "gpt-5-2-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);

Continue with the returned session_id:

await rivya.chat.completions.create({
  model: "gpt-5-2-chat",
  session_id: completion.session_id,
  message: "Now turn that into a 5-step execution checklist."
});

Read API-created sessions:

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

Use chat.completions.stream to consume Server-Sent Events as an async iterator:

const stream = await rivya.chat.completions.stream(
  {
    model: "gpt-5-2-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 is for display only. The committed result is available after message.completed, and can be read later with chat.sessions.retrieve.

Errors

The SDK throws RivyaAPIError for non-2xx Public API responses:

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 includes the HTTP status, public error code, message, request id when available, and a safe response-header subset.

Validation

Run the SDK checks before treating a change as complete:

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

pnpm sdk:check includes a static contract check and a no-network runtime check for error parsing, safe error headers, idempotency headers, Bearer auth, public model listing, Chat streaming SSE parsing, Chat streaming error events, and webhook signature verification.

Table of Contents