# SDKS

KrosAI provides official SDKs to simplify integration with your applications.

## Voice SDK (JavaScript)

Connect WebRTC voice agents to phone numbers with the KrosAI Voice SDK.

### Installation

{% code title="Install (npm)" %}

```bash
npm install @krosai/voice-sdk
```

{% endcode %}

### Quick Start

{% code title="quickstart.ts" %}

```typescript
import { KrosAI } from '@krosai/voice-sdk';

const krosai = new KrosAI({ 
  apiKey: 'kros_live_your_key' 
});

// Connect your voice agent to a phone number
const call = await krosai.call({
  phoneNumber: '+2348012345678',
  audioStream: myAgentAudioStream,
});

// Handle call events
call.on('connected', () => console.log('Call connected'));
call.on('ended', (data) => console.log('Call ended:', data.reason));

// Control the call
call.mute();
call.unmute();
await call.hangup();
```

{% endcode %}

### Features

* **WebRTC to Phone:** Connect any WebRTC audio stream to phone calls
* **Event Streaming:** Real-time call status and audio events
* **Audio Controls:** Mute, unmute, and volume control
* **Low Latency:** Sub-second audio transmission

→ [Full Voice SDK Documentation](/voice/outbound-calls.md)

## React SDK

React hooks and components for voice integration.

### Installation

{% code title="Install (npm)" %}

```bash
npm install @krosai/voice-sdk @krosai/voice-sdk-react
```

{% endcode %}

### Quick Start

{% code title="App.tsx" %}

```tsx
import { KrosAIProvider, useKrosAICall } from '@krosai/voice-sdk-react';

function App() {
  return (
    <KrosAIProvider apiKey="kros_live_your_key">
      <PhoneAgent />
    </KrosAIProvider>
  );
}

function PhoneAgent() {
  const { 
    call, 
    startCall, 
    endCall, 
    status, 
    duration,
    isMuted,
    toggleMute 
  } = useKrosAICall();

  const handleCall = async () => {
    await startCall({
      phoneNumber: '+2348012345678',
      audioStream: myAgentAudioStream,
    });
  };

  return (
    <div>
      <p>Status: {status}</p>
      <p>Duration: {duration}s</p>
      
      {!call ? (
        <button onClick={handleCall}>Start Call</button>
      ) : (
        <>
          <button onClick={toggleMute}>
            {isMuted ? 'Unmute' : 'Mute'}
          </button>
          <button onClick={endCall}>End Call</button>
        </>
      )}
    </div>
  );
}
```

{% endcode %}

### Hooks

| Hook                   | Description                   |
| ---------------------- | ----------------------------- |
| `useKrosAICall()`      | Main hook for call management |
| `useAudioLevels(call)` | Real-time audio level meters  |
| `useKrosAIClient()`    | Access the raw SDK client     |

## REST API

For server-side integrations, use the REST API directly:

{% code title="listPhoneNumbers.ts" %}

```typescript
// TypeScript API Client
async function listPhoneNumbers() {
  const response = await fetch('https://api.krosai.com/v1/phone-numbers', {
    headers: {
      'x-api-key': process.env.KROSAI_API_KEY!,
    },
  });
  return response.json();
}

async function initiateCall(toNumber: string, fromNumber: string, endpointId: string) {
  const response = await fetch('https://api.krosai.com/v1/outbound-calls', {
    method: 'POST',
    headers: {
      'x-api-key': process.env.KROSAI_API_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      to_number: toNumber,
      from_number: fromNumber,
      endpoint_id: endpointId,
    }),
  });
  return response.json();
}
```

{% endcode %}

## Python SDK (Coming Soon)

A Python SDK is in development:

{% code title="preview\.py" %}

```python
# Preview - API may change
from krosai import KrosAI

client = KrosAI(api_key='kros_live_your_key')

# List phone numbers
numbers = client.phone_numbers.list()

# Initiate an outbound call
call = client.calls.create(
    from_number='+2348012345678',
    to_number='+14155551234',
    endpoint_id='ep_abc123'
)

print(f'Call initiated: {call.id}')
```

{% endcode %}

{% hint style="info" %}
Interested in early access? Contact us at <sdk@krosai.com>
{% endhint %}

## Community Libraries

Community-maintained libraries (unofficial):

| Language | Library       | Author    |
| -------- | ------------- | --------- |
| Go       | `krosai-go`   | Community |
| Ruby     | `krosai-ruby` | Community |
| PHP      | `krosai-php`  | Community |

{% hint style="warning" %}
Community libraries are not officially supported. Use at your own discretion.
{% endhint %}

## API Rate Limits

SDK requests are subject to rate limits:

| Tier       | Requests/Second | Requests/Day |
| ---------- | --------------- | ------------ |
| Free       | 10              | 1,000        |
| Pro        | 50              | 50,000       |
| Business   | 200             | 500,000      |
| Enterprise | Custom          | Custom       |

Rate limit headers are included in responses:

{% code title="Rate limit headers" %}

```
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1704891600
```

{% endcode %}

## Error Handling

All SDKs use consistent error codes:

{% code title="error-handling.ts" %}

```typescript
import { KrosAIError } from '@krosai/voice-sdk';

try {
  await krosai.call({ phoneNumber: 'invalid' });
} catch (error) {
  if (error instanceof KrosAIError) {
    switch (error.code) {
      case 'INVALID_PHONE_NUMBER':
        console.error('Invalid phone format');
        break;
      case 'INSUFFICIENT_BALANCE':
        console.error('Add credits to continue');
        break;
      case 'RATE_LIMIT_EXCEEDED':
        console.error('Slow down requests');
        break;
      default:
        console.error('Unknown error:', error.message);
    }
  }
}
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.krosai.com/getting-started/sdks.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
