> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript/TypeScript SDK

> Using the OpenAI Node.js SDK with Mavera

## Installation

```bash theme={"dark"}
npm install openai
# or
yarn add openai
# or
pnpm add openai
```

**Minimum:** Node.js 18+ (for native `fetch`). The OpenAI SDK works with Mavera's Responses API via `baseURL` override.

### Install Troubleshooting

<AccordionGroup>
  <Accordion title="Wrong package">
    Install the **official** `openai` package. Avoid `openai-api`, `openai-node`, or similar. Verify with `npm list openai`.
  </Accordion>

  <Accordion title="ESM vs CommonJS">
    The SDK supports both. Use `"type": "module"` in package.json for ESM, or `require("openai")` for CommonJS. For TypeScript, ensure `moduleResolution` is compatible.
  </Accordion>

  <Accordion title="TypeScript type errors for persona_id">
    The OpenAI types don't include `persona_id`. Add it directly to the request object; use `// @ts-expect-error` above the line, or extend the types if needed.
  </Accordion>

  <Accordion title="Node version">
    Node 18+ required. Check with `node -v`. For older Node, consider upgrading or using the REST API directly.
  </Accordion>
</AccordionGroup>

## Migrating from OpenAI

If you're switching from OpenAI to Mavera, change **only** these:

1. **baseURL** — `baseURL: "https://app.mavera.io/api/v1"`
2. **apiKey** — Use your Mavera key (starts with `mvra_live_`)
3. **model** — Use `mavera-1`
4. **persona\_id** — Add `persona_id: "..."` to every `responses.create()` call (JavaScript accepts it directly; no `extra_body`)

Streaming, tools, and structured outputs work with minor adjustments. See [Migrate OpenAI to Mavera](/cookbooks/migrate-openai-to-mavera).

## Configuration

```javascript theme={"dark"}
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: "mvra_live_your_key_here",
  baseURL: "https://app.mavera.io/api/v1",
});
```

<Tip>
  Store your API key in an environment variable: `MAVERA_API_KEY`
</Tip>

```javascript theme={"dark"}
const client = new OpenAI({
  apiKey: process.env.MAVERA_API_KEY,
  baseURL: "https://app.mavera.io/api/v1",
});
```

## Responses API

### Basic Usage

```javascript theme={"dark"}
const response = await client.responses.create({
  model: "mavera-1",
  input: "What are the latest trends in AI?",
  instructions: "You are a helpful assistant.",
  // @ts-ignore - Mavera custom field
  persona_id: "YOUR_PERSONA_ID",
});

console.log(response.output[0].content[0].text);
console.log("Credits used:", response.usage.credits_used);
```

### Streaming

```javascript theme={"dark"}
const stream = client.responses.stream({
  model: "mavera-1",
  input: "Write a short story",
  // @ts-ignore - Mavera custom field
  persona_id: "YOUR_PERSONA_ID",
});

for await (const event of stream) {
  if (event.type === "response.output_text.delta") {
    process.stdout.write(event.delta);
  }
}
```

### With Analysis Mode

```javascript theme={"dark"}
const response = await client.responses.create({
  model: "mavera-1",
  input: "How do millennials feel about remote work?",
  // @ts-ignore - Mavera custom field
  persona_id: "YOUR_PERSONA_ID",
  analysis_mode: true,
  reasoning_effort: "high",
});

const analysis = response.analysis;
console.log(`Confidence: ${analysis.confidence}/10`);
```

## REST API Endpoints

For non-Chat endpoints, use `fetch`:

```javascript theme={"dark"}
const headers = {
  Authorization: "Bearer mvra_live_your_key_here",
  "Content-Type": "application/json",
};
const baseURL = "https://app.mavera.io/api/v1";

// List personas
const personasRes = await fetch(`${baseURL}/personas`, { headers });
const { data: personas } = await personasRes.json();

// Mave Agent
const maveRes = await fetch(`${baseURL}/mave/chat`, {
  method: "POST",
  headers,
  body: JSON.stringify({ message: "Analyze the EV market" }),
});
const maveResult = await maveRes.json();

// Create Focus Group
const fgRes = await fetch(`${baseURL}/focus-groups`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    name: "Product Feedback",
    sample_size: 50,
    persona_ids: ["persona_1", "persona_2"],
    questions: [...],
  }),
});
```

## TypeScript Support

The SDK includes full TypeScript types:

```typescript theme={"dark"}
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.MAVERA_API_KEY,
  baseURL: "https://app.mavera.io/api/v1",
});

const response = await client.responses.create({
  model: "mavera-1",
  input: "Hello",
  // @ts-ignore - Mavera custom field
  persona_id: "YOUR_PERSONA_ID",
});
```

## Error Handling

```typescript theme={"dark"}
import OpenAI from "openai";

try {
  const response = await client.responses.create({...});
} catch (error) {
  if (error instanceof OpenAI.AuthenticationError) {
    console.error("Invalid API key");
  } else if (error instanceof OpenAI.RateLimitError) {
    console.error("Rate limited - implement backoff");
  } else if (error instanceof OpenAI.APIError) {
    if (error.status === 402) {
      console.error("Insufficient credits");
    } else {
      console.error("API error:", error.message);
    }
  }
}
```

## Edge Runtime / Vercel

Works in Edge Runtime environments:

```typescript theme={"dark"}
// app/api/chat/route.ts
import OpenAI from "openai";

export const runtime = "edge";

const client = new OpenAI({
  apiKey: process.env.MAVERA_API_KEY,
  baseURL: "https://app.mavera.io/api/v1",
});

export async function POST(req: Request) {
  const { message } = await req.json();

  const response = await client.responses.create({
    model: "mavera-1",
    input: message,
    // @ts-ignore - Mavera custom field
    persona_id: process.env.PERSONA_ID,
  });

  return Response.json(response);
}
```

## React / Next.js Example

```tsx theme={"dark"}
"use client";

import { useState } from "react";

export function Chat() {
  const [message, setMessage] = useState("");
  const [response, setResponse] = useState("");

  const handleSubmit = async () => {
    const res = await fetch("/api/chat", {
      method: "POST",
      body: JSON.stringify({ message }),
    });
    const data = await res.json();
    setResponse(data.output[0].content[0].text);
  };

  return (
    <div>
      <input value={message} onChange={(e) => setMessage(e.target.value)} />
      <button onClick={handleSubmit}>Send</button>
      <p>{response}</p>
    </div>
  );
}
```

## Full Example Script (Node.js)

A runnable script: list personas, send a chat, print the response.

```javascript theme={"dark"}
// mavera_chat.mjs — run with: node mavera_chat.mjs "Your question here"
import OpenAI from "openai";

const apiKey = process.env.MAVERA_API_KEY;
if (!apiKey) {
  console.error("Set MAVERA_API_KEY environment variable");
  process.exit(1);
}

const client = new OpenAI({
  apiKey,
  baseURL: "https://app.mavera.io/api/v1",
});

async function main() {
  const question = process.argv[2] || "What matters most to you when choosing a product?";

  const personasRes = await fetch("https://app.mavera.io/api/v1/personas", {
    headers: { Authorization: `Bearer ${apiKey}` },
  });
  const { data: personas } = await personasRes.json();
  const personaId = personas?.[0]?.id;
  if (!personaId) {
    console.error("No personas found");
    process.exit(1);
  }
  console.log(`Using persona: ${personas[0].name}\n`);

  const response = await client.responses.create({
    model: "mavera-1",
    input: question,
    // @ts-ignore - Mavera custom field
    persona_id: personaId,
  });

  console.log(response.output[0].content[0].text);
  console.log(`\nCredits used: ${response.usage.credits_used}`);
}

main().catch(console.error);
```

Run: `MAVERA_API_KEY=mvra_live_xxx node mavera_chat.mjs "How do you feel about subscription pricing?"`

<CardGroup cols={2}>
  <Card title="Quickstart: Chat" icon="rocket" href="/quickstart-chat">
    First chat in 5 minutes
  </Card>

  <Card title="Migrate OpenAI → Mavera" icon="plug" href="/cookbooks/migrate-openai-to-mavera">
    Switching from OpenAI
  </Card>

  <Card title="Streaming Chat in React" icon="stream" href="/cookbooks/streaming-chat-react">
    React component for streaming
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/responses/create-a-response">
    Responses API spec
  </Card>
</CardGroup>
