---
name: Pcci
description: Use when building end-to-end encrypted AI applications with chat completions, audio processing, and vision models. Reach for this skill when integrating OpenAI-compatible APIs, managing API keys and scopes, handling rate limits, or implementing secure authentication with encryption.
metadata:
    mintlify-proj: pcci
    version: "1.0"
---

# Prem API Skill

## Product summary

Prem API is an **end-to-end encrypted**, **OpenAI-compatible** API for chat completions, audio transcription/translation, and vision models. All data is encrypted client-side before transmission — servers never see plaintext. Use the TypeScript SDK (`@premai/api-sdk`) or run the bundled proxy (`pcci-proxy`) to expose OpenAI-compatible routes. Key files: `.env` (stores `PREM_API_KEY`, `PROXY_URL`, `ENCLAVE_URL`), SDK initialization with `createRvencClient()`. Primary docs: https://docs.prem.io

## When to use

- **Building encrypted AI applications**: Chat completions, audio processing, or vision tasks where data privacy is required
- **Integrating with OpenAI clients**: Use the proxy server to drop in as a replacement for OpenAI's API
- **Managing API authentication**: Creating, scoping, and restricting API keys per environment or team
- **Handling rate limits and quotas**: Implementing retry logic, monitoring token/audio usage, managing concurrent requests
- **Audio workflows**: Transcribing audio to text or translating audio from any language to English
- **Vision/multimodal tasks**: Analyzing images, extracting structured data from documents, or comparing images
- **Troubleshooting encryption or authentication failures**: Understanding key exchange, error codes, and support IDs

## Quick reference

### SDK initialization

```typescript
import createRvencClient from "@premai/api-sdk";

// Auto-generate encryption keys
const client = await createRvencClient({
  apiKey: process.env.PREM_API_KEY,
  clientKEK: process.env.CLIENT_KEK,
  requestTimeoutMs: 60000,
  maxBufferSize: 20 * 1024 * 1024,
});

// Or pre-generate and reuse keys
import { generateEncryptionKeys } from "@premai/api-sdk";
const encryptionKeys = await generateEncryptionKeys();
const client = await createRvencClient({
  apiKey: process.env.PREM_API_KEY,
  encryptionKeys,
});
```

### Environment variables

| Variable | Source | Purpose |
|----------|--------|---------|
| `PREM_API_KEY` | Dashboard > API Keys | Authentication token |
| `PROXY_URL` | `dashboard.prem.io/endpoints.json` | Gateway endpoint (e.g., `https://gateway.prem.io`) |
| `ENCLAVE_URL` | `dashboard.prem.io/endpoints.json` | Enclave endpoint (e.g., `https://conf-engine.prem.io`) |
| `CLIENT_KEK` | Auto-generated or pre-generated | Master encryption key (optional if using auto-generation) |

### API scopes (least privilege)

| Scope | Use case |
|-------|----------|
| `chats.completion` | Chat completions only |
| `audio.transcription` | Audio-to-text only |
| `audio.translation` | Audio translation only |
| `files.encrypted.read` | Read encrypted files |
| `files.encrypted.create` | Upload encrypted files |
| `files.encrypted.delete` | Delete encrypted files |
| `api_keys.read` | View API keys |
| `tools.execute` | Execute tools and integrations |

### Common endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/rvenc/chat/completions` | POST | Chat completions (streaming or non-streaming) |
| `/rvenc/audio/transcriptions` | POST | Transcribe audio to text |
| `/rvenc/audio/translations` | POST | Translate audio to English |
| `/models` | GET | List available models |

### Rate limit tiers (BASE tier example)

| Metric | Limit | Refill |
|--------|-------|--------|
| Requests/sec (inference) | 5 | 1 req/sec |
| Tokens/minute | 38,000 | 38,000 tokens/min |
| Audio/minute | 10 sec | 10 sec/min |
| Concurrent requests | 5 | — |

Upgrade tier by increasing paid usage. Contact support@premai.io for enterprise limits.

## Decision guidance

### When to use SDK vs proxy

| Scenario | Use SDK | Use Proxy |
|----------|---------|-----------|
| TypeScript/Node.js app | ✓ | — |
| Existing OpenAI client code | — | ✓ |
| Multiple languages/frameworks | — | ✓ |
| Direct control over encryption | ✓ | — |
| Drop-in OpenAI replacement | — | ✓ |

### When to pre-generate encryption keys

| Scenario | Auto-generate | Pre-generate |
|----------|---------------|--------------|
| Single request | ✓ | — |
| Multiple requests in same session | — | ✓ |
| Performance-critical | — | ✓ |
| Testing/prototyping | ✓ | — |

### When to use IP restrictions vs scopes

| Scenario | IP Restrict | Scope Limit |
|----------|-------------|------------|
| Production API key | ✓ | ✓ |
| CI/CD pipeline | ✓ | ✓ |
| Development key | — | ✓ |
| Temporary key | ✓ | ✓ |

## Workflow

### 1. Set up authentication

1. Open [Dashboard](https://dashboard.prem.io) and sign in
2. Go to **API Keys** section
3. Create a new API key, set scopes (e.g., `chats.completion`), optionally add IP restrictions
4. Copy the key to `.env` as `PREM_API_KEY`
5. Fetch endpoint URLs from `dashboard.prem.io/endpoints.json` and add to `.env` as `PROXY_URL` and `ENCLAVE_URL`

### 2. Initialize the client

```typescript
import createRvencClient from "@premai/api-sdk";

const client = await createRvencClient({
  apiKey: process.env.PREM_API_KEY,
  clientKEK: process.env.CLIENT_KEK,
});
```

### 3. Make your first request

```typescript
// Chat completion
const response = await client.chat.completions.create({
  model: "openai/gpt-oss-120b",
  messages: [{ role: "user", content: "Hello!" }],
});
console.log(response.choices[0].message.content);

// Streaming
const stream = await client.chat.completions.create({
  model: "openai/gpt-oss-120b",
  messages: [{ role: "user", content: "Count to 10" }],
  stream: true,
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content || "");
}
```

### 4. Handle errors and rate limits

```typescript
async function retryWithBackoff(fn, maxRetries = 6) {
  let retries = 0;
  while (true) {
    try {
      return await fn();
    } catch (error) {
      if (error?.status !== 429 || retries >= maxRetries) throw error;
      const delay = parseInt(error.headers["retry-after"], 10) * 1000;
      retries++;
      console.log(`Rate limited. Retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Usage
const response = await retryWithBackoff(() =>
  client.chat.completions.create({
    model: "openai/gpt-oss-120b",
    messages: [{ role: "user", content: "Hello!" }],
  })
);
```

### 5. Use the proxy for OpenAI compatibility

```bash
# Terminal 1: Start proxy
npx -p @premai/api-sdk pcci-proxy
# Runs on http://127.0.0.1:3000

# Terminal 2: Use with OpenAI SDK
```

```typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.PREM_API_KEY,
  baseURL: "http://127.0.0.1:3000/v1",
});

const response = await client.chat.completions.create({
  model: "openai/gpt-oss-120b",
  messages: [{ role: "user", content: "Hello!" }],
});
```

## Common gotchas

- **Missing environment variables**: All three (`PREM_API_KEY`, `PROXY_URL`, `ENCLAVE_URL`) are required. Fetch endpoint URLs from `dashboard.prem.io/endpoints.json` — they change.
- **API key lacks required scope**: A 403 error means the key doesn't have the scope for that endpoint (e.g., `chats.completion`). Check the key's scopes in the dashboard.
- **Rate limit hit but not retrying**: 429 errors require exponential backoff. Continuously resending the same request will fail. Always check the `Retry-After` header.
- **Encryption keys not persisted**: If you don't pre-generate and store encryption keys, each request generates new ones. For multi-request sessions, pre-generate once and reuse.
- **Proxy not running**: If using the OpenAI SDK, ensure `pcci-proxy` is running on the specified `baseURL`. The proxy caches clients per API key for performance.
- **Support ID not captured**: Every error response includes a `support_id` (format: `support_{uuidv7}`). Log it immediately — support IDs are kept only 7 days.
- **Concurrent request limit silently exceeded**: If you hit the concurrent limit, requests return 429. Implement a request queue to control parallelism.
- **Audio model doesn't support streaming**: `openai/whisper-large-v3` is non-streaming only. Don't set `stream: true` for audio transcription/translation.
- **Plaintext keys in source control**: Never commit `.env` files or API keys. Use environment variables or secure vaults.
- **Forgetting to handle streaming chunks**: When using `stream: true`, iterate with `for await` and check `chunk.choices[0]?.delta?.content` — not all chunks have content.

## Verification checklist

Before submitting work:

- [ ] API key created in dashboard with appropriate scopes (not full permissions)
- [ ] Environment variables set: `PREM_API_KEY`, `PROXY_URL`, `ENCLAVE_URL`
- [ ] Client initialized with `createRvencClient()` or proxy running
- [ ] First request succeeds (test with a simple chat completion)
- [ ] Error handling includes retry logic with exponential backoff for 429 errors
- [ ] `support_id` is logged for debugging (included in all error responses)
- [ ] Rate limits understood: check tier limits for tokens/minute, concurrent requests, audio duration
- [ ] Encryption keys pre-generated and reused if making multiple requests in same session
- [ ] Streaming requests iterate with `for await` and check for `delta.content`
- [ ] IP restrictions applied to production keys
- [ ] No plaintext keys in code or version control

## Resources

- **Full page navigation**: https://docs.prem.io/llms.txt
- **Quickstart**: https://docs.prem.io/basics/build/quickstart
- **API Reference**: https://docs.prem.io/developer-resources/reference/rvenc/chat-completions
- **Rate Limits & Quotas**: https://docs.prem.io/developer-resources/get-started/rate-limits
- **Encryption Architecture**: https://docs.prem.io/developer-resources/get-started/encryption
- **Error Handling**: https://docs.prem.io/developer-resources/get-started/errors
- **API Keys & Scopes**: https://docs.prem.io/developer-resources/get-started/api-keys
- **Recipes (step-by-step guides)**: https://docs.prem.io/recipes/overview

---

> For additional documentation and navigation, see: https://docs.prem.io/llms.txt