---
name: Pcci
description: Use when building applications that need client-encrypted LLM inference with confidential-computing evidence, integrating chat completions or audio processing with end-to-end encryption, configuring agents or automation systems that require secure data handling, or evaluating confidential processing for regulated industries (healthcare, finance, legal).
metadata:
    mintlify-proj: pcci
    version: "1.0"
---

# Prem API Skill

## Product summary

Prem API provides OpenAI- and Anthropic-compatible chat and audio routes with client-side encryption and confidential-computing evidence. The TypeScript SDK or local Confidential Proxy encrypts request payloads before network egress; the Prem gateway handles ciphertext plus operational metadata; a Trusted Execution Environment (TEE) decrypts and processes requests inside sealed hardware. Use this for regulated data, sensitive prompts, or workloads requiring explicit processing boundaries and hardware-signed attestation.

**Key files and commands:**
- SDK: `@premai/api-sdk` (npm package)
- Proxy: `confidential-proxy` (bundled CLI)
- Config: `PREM_API_KEY`, `CLIENT_KEK`, `PROXY_URL`, `ENCLAVE_URL` (environment variables)
- Endpoints: Fetch from `dashboard.prem.io/endpoints.json` at deploy time
- Primary docs: https://docs.prem.io

## When to use

Reach for this skill when:
- Building unattended agents, batch jobs, or automation loops that call LLM APIs
- Integrating chat completions with client-side encryption (TypeScript SDK or local proxy)
- Connecting OpenAI-compatible or Anthropic-compatible clients to encrypted routes
- Configuring agents (OpenCode, Claude Code, OpenClaw, Hermes, Goose) to use confidential processing
- Handling sensitive data (patient records, financial data, legal documents, source code, trade secrets)
- Needing to verify processing happens inside a Trusted Execution Environment with attestation
- Evaluating confidential inference for compliance or security requirements
- Troubleshooting rate limits, retries, idempotency, or streaming responses

Do not use for non-sensitive data where broader model catalogs matter more than confidentiality—use Router (beta) instead.

## Quick reference

### Integration paths

| Path | Best for | Encryption | Code changes | Confidential |
|------|----------|-----------|--------------|--------------|
| **TypeScript SDK** | Node.js agents, single-process automation | In-process | Use `@premai/api-sdk` instead of `openai` | Yes |
| **Confidential Proxy** | Polyglot frameworks (Python, Go), existing OpenAI/Anthropic SDKs | Local HTTP process | Point `baseURL` at proxy | Yes |
| **Router (Beta)** | Broader model catalog, non-sensitive data | None | Point at `https://router.prem.io/v1` | No |

### Required environment variables (both confidential paths)

```bash
export PREM_API_KEY="your-api-key"           # From dashboard
export CLIENT_KEK="$(openssl rand -hex 32)"  # 32 bytes, 64 hex chars, you generate
export PROXY_URL="https://gateway.prem.io"   # Fetch from dashboard.prem.io/endpoints.json
export ENCLAVE_URL="https://conf-engine.prem.io"  # Fetch from dashboard.prem.io/endpoints.json
```

For Router: use `PREM_ROUTER_API_KEY` instead of `PREM_API_KEY`. Do not reuse Confidential API credentials with Router.

### TypeScript SDK quickstart

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

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

const response = await client.chat.completions.create({
  model: "glm-5.2",
  messages: [{ role: "user", content: "Hello, privately." }],
  reasoning_effort: "none",
  max_completion_tokens: 4096,
});

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

### Confidential Proxy quickstart

```bash
# Start the proxy
npx -p @premai/api-sdk@1.0.59 confidential-proxy \
  --compat openai \
  --kek "$CLIENT_KEK"

# Point OpenAI SDK at it
const client = new OpenAI({
  apiKey: process.env.PREM_API_KEY,
  baseURL: "http://127.0.0.1:8787/v1",
});
```

### Proxy daemon commands

```bash
confidential-proxy start --compat openai --kek "$CLIENT_KEK"
confidential-proxy status
confidential-proxy stop
```

### Common model IDs

- `glm-5.2`: GLM-5.2 (reasoning capable)
- `kimi-k3`: Kimi K3 (Router only)
- Check available models: `GET /v1/models` (authenticated)

### Error handling

All errors return: `{ status, error, support_id }`. Log `support_id` for every error; contact support within one week with the ID.

Common codes:
- `400`: Bad request (malformed payload)
- `401`: Unauthorized (missing/invalid API key)
- `403`: Forbidden (insufficient permissions)
- `429`: Rate limited (check `Retry-After` header; may be missing upstream)
- `500`, `503`: Server error (retry with exponential backoff)

## Decision guidance

### When to use TypeScript SDK vs Confidential Proxy

| Condition | Use SDK | Use Proxy |
|-----------|---------|-----------|
| Node.js backend, single process | ✓ | |
| Python, Go, or other language | | ✓ |
| Existing OpenAI SDK codebase | | ✓ |
| Existing Anthropic SDK codebase | | ✓ |
| Unattended agent loop | ✓ | ✓ |
| Need to parallelize on same key | Use multiple keys | Use multiple keys |

### When to use Confidential API vs Router

| Condition | Confidential API | Router |
|-----------|------------------|--------|
| Sensitive data (PII, secrets, regulated) | ✓ | |
| Need broader model catalog | | ✓ |
| Need attestation evidence | ✓ | |
| Non-sensitive prompts only | | ✓ |
| Compliance/audit requirement | ✓ | |

### Proxy compatibility modes

| Mode | Routes | Use when |
|------|--------|----------|
| `openai` (default) | `/v1/*` | Using OpenAI SDK only |
| `anthropic` | `/v1/*` | Using Anthropic SDK only |
| `both` | `/openai/v1/*` and `/anthropic/v1/*` | Running both SDKs against same proxy |

## Workflow

### 1. Set up credentials and endpoints

1. Create an API key in dashboard.prem.io/api-keys
2. Generate a 32-byte client KEK: `openssl rand -hex 32`
3. Fetch current endpoints: `curl https://dashboard.prem.io/endpoints.json`
4. Store all four values in environment variables (never commit to source control)

### 2. Choose integration path

- **Node.js agent**: Use TypeScript SDK directly
- **Python/Go agent or existing OpenAI/Anthropic SDK**: Use Confidential Proxy
- **Non-sensitive data, need broader models**: Use Router

### 3. Implement with error handling and idempotency

- Set `reasoning_effort: "none"` by default (reasoning is billed and consumes token budget)
- Add `Idempotency-Key` header to all retried requests
- Check `finish_reason` before treating `content` as final
- Implement exponential backoff for `429` responses; don't assume `Retry-After` header exists
- Serialize calls per API key or use distinct keys per concurrent worker

### 4. Verify before deployment

- Confirm model IDs appear in `GET /v1/models` for your key
- Test with small payloads first
- Check rate limits for your tier (BASE, TIER_1, TIER_2, TIER_3)
- Verify attestation is enabled (default: `attest: true`)
- Log `support_id` on every error

### 5. Monitor and maintain

- Watch for `429` rate limit errors; upgrade tier if needed
- Rotate API keys regularly
- Keep KEK backed up in secure location
- Monitor token usage in dashboard
- Set monthly budget limits

## Common gotchas

- **Reasoning is on by default and is billed.** Set `reasoning_effort: "none"` in automated pipelines unless you explicitly consume the reasoning trace. Reasoning tokens count against your rate limit and token budget.

- **One active stream per API key on encrypted endpoint.** The `/rvenc/chat/completions` endpoint always responds over `text/event-stream`. If a second call comes in on the same key while one is in flight, you get `429: "You already have an active chat stream."` Serialize calls per key or use distinct keys per concurrent worker.

- **429 responses don't all look the same.** Some include `Retry-After` header; others (from upstream backends) return generic body with no header. Branch on HTTP status code, not body shape. Fall back to exponential backoff when `Retry-After` is missing.

- **Retries need idempotency keys.** Blind retries after timeout or `5xx` can duplicate actions (file uploads, resource creation). Send `Idempotency-Key` header on every retried request.

- **Check finish_reason and content.** A `null` or empty `message.content` is not necessarily a failed call. If `finish_reason` is `"length"`, reasoning or a long answer consumed the token budget. Treat as truncation; retry with larger `max_completion_tokens` or lower `reasoning_effort`.

- **Don't hardcode endpoints.** Fetch `PROXY_URL` and `ENCLAVE_URL` from `dashboard.prem.io/endpoints.json` at deploy time, not from code.

- **Don't reuse credentials between paths.** Confidential API uses `PREM_API_KEY` + `CLIENT_KEK`. Router uses `PREM_ROUTER_API_KEY` only. Do not substitute one for the other.

- **Model availability varies by key.** Call `GET /v1/models` with your API key to see what's available. Don't assume a model alias is available; use exact IDs from the response.

- **Proxy doesn't expose Responses API.** The Confidential Proxy only exposes Chat Completions. Anthropic Responses API is not currently supported.

- **macOS loopback limitation.** Claude for Microsoft 365 add-in cannot connect to `127.0.0.1` on macOS (browser CORS restriction). Run proxy on different machine or in container with own network interface.

## Verification checklist

Before submitting work or deploying to production:

- [ ] All four environment variables set (`PREM_API_KEY`, `CLIENT_KEK`, `PROXY_URL`, `ENCLAVE_URL`)
- [ ] `CLIENT_KEK` is exactly 64 hexadecimal characters (32 bytes)
- [ ] Endpoints fetched from `dashboard.prem.io/endpoints.json`, not hardcoded
- [ ] `reasoning_effort` set deliberately (`"none"` by default, or budgeted in `max_completion_tokens`)
- [ ] Retries use exponential backoff with jitter
- [ ] Idempotency keys on all retried writes
- [ ] Concurrent calls on same key are serialized, or spread across multiple keys
- [ ] Every response checks `finish_reason` before treating `content` as final
- [ ] `support_id` logged on every error for support escalation
- [ ] Model IDs verified with `GET /v1/models` for the key
- [ ] Rate limits confirmed for your tier
- [ ] Attestation enabled (default: `attest: true`)
- [ ] KEK backed up in secure location
- [ ] API keys rotated regularly
- [ ] No API keys or KEK in source control

## Resources

- **Full documentation navigation**: https://docs.prem.io/llms.txt
- **Quickstart guide**: https://docs.prem.io/quickstart
- **Security model and threat boundaries**: https://docs.prem.io/security-model
- **Agents & automation (unattended systems)**: https://docs.prem.io/agents
- **Confidential Proxy configuration**: https://docs.prem.io/confidential-proxy
- **Rate limits and retry patterns**: https://docs.prem.io/rate-limits
- **Production checklist**: https://docs.prem.io/production-checklist
- **API reference (chat completions)**: https://docs.prem.io/api-reference/chat-completions
- **Encryption details**: https://docs.prem.io/encryption
- **Attestation verification**: https://docs.prem.io/attestation

---

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