# Quickstart

Get started with Bizora in under 5 minutes.

## Prerequisites

- API key from https://platform.bizora.ai
- Python 3.7+ or Node.js 14+ for OpenAI client SDK usage

## Step 1: Get Your API Key

1. Log in to https://platform.bizora.ai
2. Navigate to **API Keys** section
3. Click **Create API Key**
4. Copy and save your key securely

## Choose an Integration Path

Bizora supports several integration patterns, depending on where you want tax research to run:

- **OpenAI client SDKs:** Use the standard OpenAI Python or JavaScript client with Bizora's base URL. This is the fastest path for application backends and services that already use OpenAI-compatible chat completions.
- **Direct HTTP:** Call `POST /chat/completions` with `curl`, `fetch`, or any HTTP client. This is useful for lightweight integrations, testing, and platforms where installing an SDK is not preferred.
- **MCP clients:** Connect Claude, Cursor, Kiro, Codex, or another MCP-compatible client to Bizora's MCP server. This is recommended when you want an agent or IDE assistant to call Bizora tax research tools directly.

This Quickstart focuses on OpenAI-compatible SDK and HTTP usage. For MCP setup, see [MCP Server](/mcp).

## Step 2: Install the OpenAI Client SDK

### Python

```bash
pip install openai
```

### JavaScript/TypeScript

```bash
npm install openai
# or
yarn add openai
```

## Step 3: Make Your First Request

Ask a tax question and get streaming responses in real-time:

```python
import openai

# Initialize client with your API key
client = openai.OpenAI(
    api_key="sk_live_YOUR_API_KEY",
    base_url="https://api-bizora.ai"
)

# Ask a tax question with streaming
stream = client.chat.completions.create(
    model="bizora-1.0",
    messages=[{"role": "human", "content": "What is section 179?"}],
    stream=True
)

# Print the answer as it arrives
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

```javascript
import OpenAI from 'openai';

// Initialize client with your API key
const client = new OpenAI({
  apiKey: 'sk_live_YOUR_API_KEY',
  baseURL: 'https://api-bizora.ai'
});

// Ask a tax question with streaming
const stream = await client.chat.completions.create({
  model: 'bizora-1.0',
  messages: [{ role: 'human', content: 'What is section 179?' }],
  stream: true
});

// Print the answer as it arrives
for await (const chunk of stream) {
  if (chunk.choices[0]?.delta?.content) {
    process.stdout.write(chunk.choices[0].delta.content);
  }
}
```

```bash
# Use -N flag for streaming, -X POST for method
curl -X POST -N https://api-bizora.ai/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -d '{
    "model": "bizora-1.0",
    "messages": [
      {"role": "human", "content": "What is section 179?"}
    ],
    "stream": true
  }'
```

## Step 4: Enable Streaming

Get responses in real-time as they're generated:

```python
# Add stream=True to get responses in real-time
stream = client.chat.completions.create(
    model="bizora-1.0",
    messages=[{"role": "human", "content": "What is section 179?"}],
    stream=True
)

# Print each chunk as it arrives
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
```

```javascript
// Add stream: true to get responses in real-time
const stream = await client.chat.completions.create({
  model: 'bizora-1.0',
  messages: [{ role: 'human', content: 'What is section 179?' }],
  stream: true
});

// Print each chunk as it arrives
for await (const chunk of stream) {
  if (chunk.choices[0]?.delta?.content) {
    process.stdout.write(chunk.choices[0].delta.content);
  }
}
```

```bash
# Add -N flag for streaming and -X POST for method
curl -X POST -N https://api-bizora.ai/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -d '{
    "model": "bizora-1.0",
    "messages": [
      {"role": "human", "content": "What is section 179?"}
    ],
    "stream": true
  }'
```

## Step 5: Handle Custom Messages

When streaming, the API sends additional information like research steps, sources, and suggestions:

```python
# Stream responses and get custom messages
stream = client.chat.completions.create(
    model="bizora-1.0",
    messages=[{"role": "human", "content": "What is section 179?"}],
    stream=True
)

for chunk in stream:
    # AI content - the actual answer
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    
    # Custom messages - steps, sources, suggestions
    elif hasattr(chunk, 'custom_data'):
        msg_type = chunk.custom_data.get('type')
        
        if msg_type == 'step_message':
            # Shows what the AI is doing
            print(f"\n🔄 {chunk.custom_data.get('title')}")
        
        elif msg_type == 'source_message':
            # Shows which documents were referenced
            sources = chunk.custom_data.get('content', [])
            print(f"\n📚 {len(sources)} sources found")
        
        elif msg_type == 'suggestions':
            # Follow-up question suggestions
            suggestions = chunk.custom_data.get('suggestions', [])
            print(f"\n💡 {len(suggestions)} suggested questions")
```

```javascript
// Stream responses and get custom messages
const stream = await client.chat.completions.create({
  model: 'bizora-1.0',
  messages: [{ role: 'human', content: 'What is section 179?' }],
  stream: true
});

for await (const chunk of stream) {
  // AI content - the actual answer
  if (chunk.choices[0]?.delta?.content) {
    process.stdout.write(chunk.choices[0].delta.content);
  }
  
  // Custom messages - steps, sources, suggestions
  else if (chunk.custom_data) {
    const { type } = chunk.custom_data;
    
    if (type === 'step_message') {
      // Shows what the AI is doing
      console.log(`\n🔄 ${chunk.custom_data.title}`);
    }
    else if (type === 'source_message') {
      // Shows which documents were referenced
      const sources = chunk.custom_data.content || [];
      console.log(`\n📚 ${sources.length} sources found`);
    }
    else if (type === 'suggestions') {
      // Follow-up question suggestions
      const suggestions = chunk.custom_data.suggestions || [];
      console.log(`\n💡 ${suggestions.length} suggested questions`);
    }
  }
}
```

## Common Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `model` | string | Yes | Must be `"bizora-1.0"` |
| `messages` | array | Yes | Array of message objects |
| `stream` | boolean | No | Enable streaming (default: `false`) |
| `askMode` | string | No | Use `tax_research_fast_research`, `tax_research_deep_research`, `audit_research`, or `auto` for backend route selection |
| `allowedAskModes` | array | No | Constrain auto-routing when `askMode` is `auto` |
| `ZeroDataRetention` | boolean | No | Disabled by default. Pass `true` only if you require zero data retention. |

Prefer canonical `askMode` values for new integrations. Use `tax_research_deep_research` for complex tax questions that need deeper, multi-step research, and `audit_research` for complex financial and accounting analysis.

## Multi-Turn Conversations

Build context by including previous messages. Use `"human"` for user messages and `"ai"` for AI responses:

```python
# Include conversation history for context
messages = [
    {"role": "human", "content": "What is section 179?"},
    {"role": "ai", "content": "Section 179 allows businesses to deduct the full purchase price of qualifying equipment..."},
    {"role": "human", "content": "What are the dollar limits?"}
]

response = client.chat.completions.create(
    model="bizora-1.0",
    messages=messages
)

print(response.choices[0].message.content)
```

```javascript
// Include conversation history for context
const messages = [
  { role: 'human', content: 'What is section 179?' },
  { role: 'ai', content: 'Section 179 allows businesses to deduct the full purchase price of qualifying equipment...' },
  { role: 'human', content: 'What are the dollar limits?' }
];

const response = await client.chat.completions.create({
  model: 'bizora-1.0',
  messages: messages
});

console.log(response.choices[0].message.content);
```

## Next Steps

- [MCP Server](/mcp) - Use Bizora with MCP-compatible clients
- [Chat Completions API](./chat-completions/overview) - Complete API documentation with streaming examples
- [Error Handling](./chat-completions/error-handling) - Handle errors properly
- [Rate Limits](./chat-completions/rate-limits) - Understand rate limits

## Need Help?

- admin@bizora.ai
- Security Bugs: admin@bizora.ai
- Dashboard: https://platform.bizora.ai
