# @gpt-core/client

The official TypeScript SDK for the GPT Core Platform - document extraction, AI agents, and workspace management.

[![npm version](https://img.shields.io/npm/v/@gpt-core/client.svg)](https://www.npmjs.com/package/@gpt-core/client)
[![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue)](https://www.typescriptlang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

---

<!-- AI_CONTEXT_START
This SDK provides TypeScript bindings for the GPT Core API.
Use this for: document extraction, AI agents, workspace management, user authentication.
NOT for: admin operations (use @gpt-core/admin instead).

Quick patterns:
- Initialize: new GptClient({ baseUrl, apiKey?, token? })
- Auth: client.identity.login(email, password) -> { user, token }
- Documents: client.extraction.documents.upload(file)
- AI Search: client.ai.search(query, options?)
- Agents: client.agents.list() / .create(name, systemPrompt)
- Workspaces: client.platform.workspaces.mine()
- Threads: client.threads.create(title) / .messages.send(threadId, content)

All methods return typed responses. Errors throw typed exceptions (AuthenticationError, ValidationError, etc).
AI_CONTEXT_END -->

## For AI Coding Assistants

> **TL;DR for Claude, Cursor, Copilot, and other AI assistants:**
>
> ```typescript
> import { GptClient } from "@gpt-core/client";
> const client = new GptClient({
>   baseUrl: "https://api.example.com",
>   token: "jwt",
> });
> ```
>
> **Common operations:**
> | Task | Code |
> |------|------|
> | Login | `await client.identity.login(email, password)` |
> | List workspaces | `await client.platform.workspaces.mine()` |
> | Upload document | `await client.extraction.documents.upload(file)` |
> | AI search | `await client.ai.search(query)` |
> | Create agent | `await client.agents.create(name, systemPrompt)` |
> | Send message | `await client.threads.messages.send(threadId, content)` |
> | Verify webhook | `await new Webhooks(secret).verify(body, signature)` |
>
> **See [llms.txt](llms.txt) for complete AI-readable SDK reference.**

---

## Features

- **Fully Typed** - Complete TypeScript support with auto-generated types from OpenAPI specs
- **Class-Based API** - Stripe-style `GptClient` with namespaced methods (12 namespaces, ~135 curated methods)
- **Runtime Validation** - Zod schemas for request validation
- **Smart Error Handling** - Custom error classes with detailed context
- **Automatic Retries** - Exponential backoff with circuit breaker for transient failures
- **Idempotency Keys** - Auto-generated for POST/PATCH/DELETE requests
- **Webhook Verification** - HMAC-SHA256 signature verification with timing-safe comparison
- **Environment Fallback** - Auto-reads `GPTCORE_BASE_URL`, `GPTCORE_API_KEY`, `GPTCORE_TOKEN`
- **Browser Safety** - Throws `BrowserApiKeyError` when API keys used in browser without opt-in
- **Structured Logging** - Configurable log levels and custom logger support
- **Custom Fetch** - Bring your own fetch implementation for testing or custom network layers
- **Pagination Support** - Async iterators for easy iteration over large datasets
- **Streaming Support** - Server-Sent Events (SSE) for real-time AI responses
- **JSON:API Compliant** - Automatic envelope unwrapping

## Installation

```bash
npm install @gpt-core/client
# or
yarn add @gpt-core/client
# or
pnpm add @gpt-core/client
```

## Quick Start

```typescript
import { GptClient } from "@gpt-core/client";

// Initialize client
const client = new GptClient({
  baseUrl: "https://api.gpt-core.com",
  apiKey: "sk_app_...", // For machine-to-machine
  token: "eyJhbGc...", // For user-authenticated requests
});

// Authenticate a user
const result = await client.identity.login("user@example.com", "password");

// Update token for subsequent requests
client.setToken(result.token);

// List workspaces
const workspaces = await client.platform.workspaces.mine();
```

## API Versioning

The SDK uses Stripe-style API versioning. A default API version is sent with every request via the `Accept` header.

### Default Behavior

Every request automatically includes the SDK's built-in API version:

```http
Accept: application/vnd.api+json; version=2025-12-03
```

No configuration is needed -- the SDK sends `DEFAULT_API_VERSION` from `base-client.ts` automatically.

### Pinning a Version (Recommended for Production)

Pin a specific API version to protect your integration from breaking changes:

```typescript
const client = new GptClient({
  baseUrl: "https://api.gpt-core.com",
  apiKey: "sk_app_...",
  apiVersion: "2025-12-03", // Pin to this version
});
```

### Reading the Active Version

```typescript
// The version the SDK is configured to send
console.log(client.apiVersion);
```

### Response Header

Every API response includes the version that was used to process the request:

```
x-api-version: 2025-12-03
```

### Discovering Available Versions

List all supported API versions and their changelogs:

```bash
GET /api-versions
```

This returns the full list of versions with descriptions and deprecation status.

## Configuration

```typescript
const client = new GptClient({
  // API base URL (falls back to GPTCORE_BASE_URL env var)
  baseUrl: "https://api.gpt-core.com",

  // Authentication (provide one or both; falls back to env vars)
  apiKey: "sk_app_...", // GPTCORE_API_KEY
  token: "eyJhbGc...", // GPTCORE_TOKEN

  // API version (optional, uses SDK default if not specified)
  apiVersion: "2025-12-03",

  // Request timeout in milliseconds (default: no timeout)
  timeout: 30000,

  // Custom fetch implementation (default: globalThis.fetch)
  fetch: customFetch,

  // Default headers sent with every request (auth headers not overridden)
  defaultHeaders: { "X-Custom-Header": "value" },

  // Allow API key usage in browser (default: false, throws BrowserApiKeyError)
  dangerouslyAllowBrowser: false,

  // Log level (default: 'warn')
  logLevel: "debug", // 'debug' | 'info' | 'warn' | 'error' | 'none'

  // Custom logger (default: console)
  logger: myLogger,

  // Application info for User-Agent header (Stripe-style)
  appInfo: { name: "MyApp", version: "1.0.0", url: "https://myapp.com" },

  // Security configuration
  security: {
    requireHttps: false, // Throw InsecureConnectionError on HTTP (default: warn only)
  },

  // Retry configuration (default: 3 retries with exponential backoff)
  retry: {
    maxRetries: 3,
    initialDelay: 1000,
    maxDelay: 32000,
    retryableStatusCodes: [429, 500, 502, 503, 504],
  },

  // Disable retries
  // retry: false,
});
```

## Security

### HTTPS Enforcement

```typescript
// Development: Warns only (localhost is always allowed)
const devClient = new GptClient({
  baseUrl: "http://localhost:22222",
});

// Production: Blocks HTTP connections
const prodClient = new GptClient({
  baseUrl: "https://api.gpt-core.com",
  security: { requireHttps: true },
});
```

### Browser Safety

Using API keys in browser environments is blocked by default to prevent credential exposure:

```typescript
// This throws BrowserApiKeyError in browser:
const client = new GptClient({ apiKey: "sk_app_..." });

// Opt-in if you understand the risks:
const client = new GptClient({
  apiKey: "sk_app_...",
  dangerouslyAllowBrowser: true,
});
```

### API Key Validation

The SDK validates API key format and warns about elevated privilege keys:

```typescript
// Valid prefixes: sk_tenant_*, sk_app_*, sk_srv_*, sk_sys_*
// sk_sys_* keys trigger warnings (elevated privileges)
```

## API Reference

### Identity

Manage users, authentication, and API keys.

```typescript
// Login
const result = await client.identity.login(email, password);
client.setToken(result.token);

// Register
const user = await client.identity.register(
  email,
  password,
  passwordConfirmation,
);

// Get current user
const user = await client.identity.me();

// Get user profile
const profile = await client.identity.profile();

// API Keys
const keys = await client.identity.apiKeys.list();
const newKey = await client.identity.apiKeys.create("Production Key");
await client.identity.apiKeys.allocate("key-id", 1000, "Monthly credits");
await client.identity.apiKeys.revoke("key-id");
await client.identity.apiKeys.rotate("key-id");
```

### Platform

Manage applications, workspaces, tenants, and invitations.

```typescript
// Applications
const apps = await client.platform.applications.list();
const app = await client.platform.applications.getBySlug("my-app");

// Workspaces
const workspaces = await client.platform.workspaces.list();
const myWorkspaces = await client.platform.workspaces.mine();
const workspace = await client.platform.workspaces.create(
  "New Workspace",
  "new-workspace",
);

// Invitations
await client.platform.invitations.create(
  "colleague@example.com",
  "editor",
  "workspace",
  "workspace-id",
);
await client.platform.invitations.accept("invitation-id");
```

### Agents

Create and manage AI agents.

```typescript
// CRUD
const agents = await client.agents.list();
const agent = await client.agents.create(
  "Support Agent",
  "You are a helpful assistant",
);
const result = await client.agents.test("agent-id", "Hello!");
await client.agents.clone("agent-id");

// Versioning
const versions = await client.agents.versions.list("agent-id");
await client.agents.versions.publish("agent-id");
await client.agents.versions.restore("agent-id", "version-id");

// Training
const examples = await client.agents.training.examples("agent-id");
```

### AI

Semantic search, embeddings, and conversations.

```typescript
// Search
const results = await client.ai.search("quarterly earnings");
const advanced = await client.ai.searchAdvanced("revenue data", { limit: 20 });

// Embeddings
const embedding = await client.ai.embed("text to embed");

// Conversations
const conversations = await client.ai.conversations.list();
const conv = await client.ai.conversations.create({ title: "New Chat" });
```

### Threads

Real-time messaging threads.

```typescript
// Threads
const threads = await client.threads.list();
const thread = await client.threads.create("Bug Discussion");

// Messages
const messages = await client.threads.messages.list(thread.id);
await client.threads.messages.send(thread.id, "Hello!");

// Actions
await client.threads.archive(thread.id);
await client.threads.fork(thread.id);
await client.threads.export(thread.id);
```

### Extraction

Upload and process documents.

```typescript
// Upload
const doc = await client.extraction.documents.upload(file);
const status = await client.extraction.documents.status(doc.id);

// Results
const results = await client.extraction.results.list();
const docResults = await client.extraction.results.byDocument(doc.id);

// Batches
const batch = await client.extraction.batches.create({ name: "Q4 Reports" });
```

### Storage

Manage buckets and files.

```typescript
// Buckets
const buckets = await client.storage.buckets.list();
const bucket = await client.storage.buckets.create("uploads", "private");

// Presigned URLs
const uploadUrl = await client.storage.signUpload("image.png", "image/png");
const downloadUrl = await client.storage.signDownload("object-id");
```

### Billing

Access wallet, plans, and payment methods.

```typescript
// Wallet
const wallet = await client.billing.wallet.get();

// Plans
const plans = await client.billing.plans.list();

// Payment Methods
const methods = await client.billing.paymentMethods.list();
await client.billing.paymentMethods.setDefault("method-id");
```

### Webhooks

Manage webhook configurations and deliveries.

```typescript
// Configs
const configs = await client.webhooks.configs.list();
await client.webhooks.configs.create("https://myapp.com/webhooks", [
  "document.processed",
]);
await client.webhooks.configs.test("config-id");
await client.webhooks.configs.rotateSecret("config-id");

// Deliveries
const deliveries = await client.webhooks.deliveries.list();
await client.webhooks.deliveries.retry("delivery-id");
```

### Search

Full-text and semantic search.

```typescript
const results = await client.search.query("invoice");
const semantic = await client.search.semantic("similar to this document");
const suggestions = await client.search.suggest("inv");

// Saved searches
const saved = await client.search.saved.list();
await client.search.saved.run("saved-search-id");
```

### Communication

Notification management.

```typescript
// Logs
const logs = await client.communication.notifications.logs();

// Methods
const methods = await client.communication.notifications.methods.list();
await client.communication.notifications.methods.verify("method-id");

// Preferences
const prefs = await client.communication.notifications.preferences.list();
```

## Webhook Signature Verification

Verify incoming webhook payloads using HMAC-SHA256 signatures:

```typescript
import { Webhooks } from "@gpt-core/client";

const wh = new Webhooks("whsec_your_secret_here");

// In your webhook handler (Express example):
app.post("/webhooks", async (req, res) => {
  const signature = req.headers["x-gptcore-signature"];
  const body = req.body; // raw string body

  try {
    await wh.verify(body, signature);
    // Process the webhook...
    res.status(200).send("OK");
  } catch (err) {
    res.status(400).send("Invalid signature");
  }
});
```

The `whsec_` prefix on secrets is stripped automatically. Signatures are checked with timing-safe comparison and a default 5-minute tolerance for timestamp freshness.

## Advanced Features

### Error Handling

The SDK provides detailed error classes:

```typescript
import {
  AuthenticationError,
  AuthorizationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  ServerError,
} from "@gpt-core/client";

try {
  await client.identity.login("user@example.com", "wrong-password");
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error("Invalid credentials:", error.message);
    console.error("Request ID:", error.requestId);
  } else if (error instanceof ValidationError) {
    console.error("Validation errors:", error.errors);
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
  }
}
```

### Pagination

Easily iterate over large datasets with built-in memory protection:

```typescript
import { paginateAll } from "@gpt-core/client";

// With limit (default: 10,000)
for await (const item of paginateAll(fetcher, { pageSize: 50, limit: 1000 })) {
  // Process items
}
```

**Pagination Safety:**

- **Default Limit**: 10,000 items max (prevents memory exhaustion)
- **Warning**: Shows warning when fetching > 1,000 items
- **Configurable**: Set custom `limit` for your use case

### Streaming

Stream AI responses in real-time:

```typescript
import { streamMessage } from "@gpt-core/client";

const response = await fetch(streamingEndpoint, {
  method: "POST",
  headers: { Accept: "text/event-stream" },
  body: JSON.stringify({ content: "Hello AI" }),
});

for await (const chunk of streamMessage(response)) {
  if (chunk.type === "content") {
    process.stdout.write(chunk.content);
  }
}
```

### Retry Logic

Automatic retries with exponential backoff and circuit breaker:

```typescript
const client = new GptClient({
  baseUrl: "https://api.gpt-core.com",
  token: "token",
  retry: {
    maxRetries: 5,
    initialDelay: 1000,
    maxDelay: 32000,
  },
});

// Disable retries
const noRetryClient = new GptClient({
  retry: false,
});
```

### Raw Functions

All 403+ generated functions remain available as named exports for power users:

```typescript
import { getAgents, postUsersAuthLogin } from "@gpt-core/client";

const { data, error } = await getAgents({ client: myClientInstance });
```

## TypeScript Support

The SDK is written in TypeScript and provides full type safety:

```typescript
import type {
  BaseClientConfig,
  AppInfo,
  Logger,
  LogLevel,
  RequestOptions,
} from "@gpt-core/client";
```

## License

MIT

## Support

- Documentation: https://docs.gpt-core.com
- Issues: https://github.com/GPT-Integrators/gpt-core-sdks/issues
