# How to Use the OpenWork API: A Complete Guide to REST and MCP Endpoints

> Master the OpenWork API with our complete guide. Learn to use both REST and MCP endpoints for seamless organization, user, and inference management.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-04

---

**The OpenWork API consists of two complementary HTTP interfaces: the Den API (`/api/den`) for conventional REST operations on organizations, users, and inference, and the MCP endpoint (`/mcp/agent`) for JSON-RPC style capability discovery and execution.**

OpenWork is an open-source AI workspace platform that exposes programmatic interfaces for building integrations, automating workflows, and connecting external agents. Whether you're scripting backend services or integrating with AI-driven tools like Claude Code or Cursor, understanding both API surfaces—implemented in the `different-ai/openwork` repository—is essential for effective integration.

## The Two API Surfaces: Den API vs. MCP Endpoint

OpenWork deliberately splits its public interface into two distinct layers. This design separates traditional resource management from AI-native capability execution.

| API | Base URL | Purpose | Best For |
|:---|:---|:---|:---|
| **Den API** | `https://<domain>/api/den` | RESTful resource management (orgs, users, plugins, memory, inference) | Backend services, scripts, direct data access |
| **MCP Endpoint** | `https://api.openworklabs.com/mcp/agent` | JSON-RPC capability discovery and execution | AI agents, semantic search, dynamic skill invocation |

Both APIs share the same **Better Auth** authentication system, but they differ fundamentally in interaction patterns. The Den API follows conventional REST semantics, while the MCP endpoint uses a JSON-RPC envelope designed for stateless, capability-oriented requests.

## Den API: REST Operations for Resource Management

The Den API is rooted at `/api/den`, a prefix enforced by the `DEN_WEB_PROXY_PREFIX` constant in [`ee/apps/den-api/src/mcp/resource.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/resource.ts). All routes are organized under `ee/apps/den-api/src/routes/**` with dedicated subdirectories for each resource type.

### Authentication Routes

Authentication flows through `/api/auth/*`, implemented in [`ee/apps/den-api/src/routes/auth/index.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/routes/auth/index.ts). The system supports:

- **Email/password sign-in** via `/api/auth/sign-in/*`
- **OAuth2 authorization** for third-party integrations
- **SCIM provisioning** for enterprise identity providers

Token validation occurs in [`ee/apps/den-api/src/mcp/auth.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/auth.ts), where Bearer tokens are extracted from the `Authorization` header and verified against the Better Auth session store.

### Organization and Membership Management

Organization-scoped routes live under `/api/auth/organization/*`, with core handlers in [`ee/apps/den-api/src/routes/org/core.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/routes/org/core.ts). These endpoints manage:

- Organization CRUD operations
- Member invitations and role assignments
- Billing and usage tracking

### Memory, Plugins, and Inference

Specialized routes handle OpenWork's AI-native features:

- **`/api/memory/*`** — Semantic memory storage and retrieval ([`ee/apps/den-api/src/routes/memory.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/routes/memory.ts))
- **`/api/plugins/*`** — Plugin lifecycle management and configuration
- **`/api/inference/*`** — Model inference proxying

The inference layer deserves particular attention. In [`ee/apps/den-api/src/inference.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/inference.ts), OpenWork constructs provider-specific URLs from `env.inferenceProxyBaseUrl` and forwards requests to `/api/v1` endpoints of configured providers like OpenRouter. This allows unified access to multiple model backends through a single authenticated interface.

### Policy Enforcement

Before requests reach route handlers, [`ee/apps/den-api/src/mcp/policy.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/policy.ts) enforces access controls. This middleware blocks unauthorized access to sensitive paths including `/api/auth` internals and webhook endpoints, ensuring that only properly authenticated and authorized requests proceed.

## MCP Endpoint: JSON-RPC for Capability Execution

The MCP (Model-Control-Plane) endpoint provides a different interaction model optimized for AI agents. Located at `/mcp/agent` and implemented in [`ee/apps/den-api/src/mcp/agent.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/agent.ts), this single route accepts JSON-RPC 2.0 requests with two primary methods.

### search_capabilities

This method scans OpenWork's capability registry for skills, plugins, and external MCP connections that match a semantic query. The search implementation in [`ee/apps/den-api/src/mcp/search.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/search.ts) indexes:

- User-created **skills** (documented workflows)
- Installed **plugins** (third-party extensions)
- Configured **external MCP connections** (remote capability providers)

### execute_capability

Once a capability is selected, this method runs it with provided arguments. The dispatcher in [`ee/apps/den-api/src/mcp/agent.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/agent.ts) routes execution to the appropriate handler:

- **Skills** — Executed within OpenWork's sandboxed runtime
- **Plugins** — Delegated to the plugin's configured endpoint
- **External MCP** — Proxied to the remote MCP server

### JSON-RPC Request Format

All MCP requests follow this envelope structure:

```json
{
  "jsonrpc": "2.0",
  "method": "search_capabilities|execute_capability",
  "params": { /* method-specific */ },
  "id": 1
}

```

Responses mirror this structure with `result` or `error` fields.

## connect-link: Bridging to Desktop Clients

When server-side agents need to hand off users to the OpenWork desktop application, the `connect-link` package generates authenticated deep links.

The core function `buildConnectExchangeDeepLink` in [`packages/connect-link/src/index.ts`](https://github.com/different-ai/openwork/blob/main/packages/connect-link/src/index.ts) constructs URLs with this signature:

```typescript
export function buildConnectExchangeDeepLink(
  code: string,
  apiBaseUrl: string,
  scheme = "openwork"
): string

```

This produces links like `openwork://connect?code=abcd1234&apiBaseUrl=https%3A%2F%2Fapi.openworklabs.com%2Fapi%2Fden`. When clicked, the desktop client:

1. Opens automatically via the custom URL scheme
2. Validates the one-time code with the specified Den API
3. Establishes an authenticated session

## Code Examples: Calling the OpenWork API

### Example 1: MCP Search and Execute

This TypeScript example demonstrates the complete flow of discovering and running a capability:

```typescript
const MCP_URL = "https://api.openworklabs.com/mcp/agent";

async function mcpRequest(method: string, params: unknown) {
  const body = {
    jsonrpc: "2.0",
    id: Date.now(),
    method,
    params,
  };
  
  const response = await fetch(MCP_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
  
  const json = await response.json();
  if (json.error) throw new Error(json.error.message);
  return json.result;
}

// Search for document summarization capabilities
const capabilities = await mcpRequest("search_capabilities", { 
  query: "summarize document" 
});

// Execute the first matching capability
const result = await mcpRequest("execute_capability", {
  capabilityId: capabilities[0].id,
  args: { 
    text: "OpenWork is an open-source alternative to Claude Code for collaborative AI development." 
  },
});

console.log(result);

```

The `mcpRequest` helper mirrors the envelope validation performed in [`ee/apps/den-api/src/mcp/agent.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/agent.ts).

### Example 2: Den API Direct Access

For operations that don't require capability semantics, use the REST API directly:

```typescript
const DEN_BASE = "https://api.openworklabs.com/api/den";
const TOKEN = process.env.OPENWORK_API_TOKEN; // Obtain via OAuth2 flow

async function listOrganizations() {
  const response = await fetch(`${DEN_BASE}/organizations`, {
    headers: { Authorization: `Bearer ${TOKEN}` },
  });
  
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }
  
  return response.json();
}

listOrganizations()
  .then(orgs => console.log(`Found ${orgs.length} organizations`))
  .catch(console.error);

```

This accesses the organization routes referenced from [`ee/apps/den-api/src/routes/org/core.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/routes/org/core.ts).

### Example 3: Generating Desktop Connection Links

Integrate the desktop hand-off flow into your application:

```typescript
import { buildConnectExchangeDeepLink } from "@openwork/connect-link";

async function createConnectCode(): Promise<string> {
  const response = await fetch(`${DEN_BASE}/connect/code`, {
    method: "POST",
    headers: { Authorization: `Bearer ${TOKEN}` },
  });
  const { code } = await response.json();
  return code;
}

async function generateDesktopLink(): Promise<string> {
  const code = await createConnectCode();
  const deepLink = buildConnectExchangeDeepLink(
    code,
    DEN_BASE,
    "openwork" // URL scheme; use "openwork-beta" for test builds
  );
  return deepLink;
}

// Usage: send this link via email, Slack, or embed in a web UI
generateDesktopLink().then(link => {
  console.log("Desktop connection URL:", link);
  // openwork://connect?code=xt9k2m&apiBaseUrl=https%3A%2F%2F...
});

```

The underlying implementation in [`packages/connect-link/src/index.ts`](https://github.com/different-ai/openwork/blob/main/packages/connect-link/src/index.ts) handles URL encoding and scheme selection.

## Authentication Patterns

Both APIs accept **Bearer tokens** via the `Authorization` header. Tokens are obtained through:

1. **OAuth2 flow** — Initiate at `/api/auth/oauth2/authorize` with appropriate scopes
2. **Email/password exchange** — POST credentials to `/api/auth/sign-in/email`
3. **API key generation** — Create long-lived keys via organization settings (stored in [`ee/apps/den-api/src/routes/auth/index.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/routes/auth/index.ts) logic)

Token validation is centralized in [`ee/apps/den-api/src/mcp/auth.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/auth.ts), ensuring consistent session verification across both API surfaces.

## Summary

- **Den API** (`/api/den`) provides traditional REST access to organizations, users, memory, plugins, and inference—ideal for backend integrations and data operations.
- **MCP endpoint** (`/mcp/agent`) offers JSON-RPC capability discovery and execution—designed for AI agents and semantic workflows.
- **connect-link package** generates `openwork://` deep links for seamless desktop hand-offs, implemented in [`packages/connect-link/src/index.ts`](https://github.com/different-ai/openwork/blob/main/packages/connect-link/src/index.ts).
- Both APIs share **Better Auth** authentication with Bearer tokens validated in [`ee/apps/den-api/src/mcp/auth.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/auth.ts).
- Policy enforcement in [`ee/apps/den-api/src/mcp/policy.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/policy.ts) guards sensitive routes before request handling.

## Frequently Asked Questions

### What authentication does the OpenWork API require?

The OpenWork API uses **Better Auth** for all authentication. Obtain a Bearer token through OAuth2, email/password sign-in, or organization-scoped API keys. Include the token in the `Authorization: Bearer <token>` header for all requests. Token validation is implemented in [`ee/apps/den-api/src/mcp/auth.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/auth.ts).

### When should I use the MCP endpoint instead of the Den API?

Use the **MCP endpoint** when building AI agent integrations that need to **discover and execute capabilities dynamically**. Use the **Den API** for direct resource manipulation—creating organizations, managing users, or running inference with explicit parameters. The MCP endpoint abstracts provider details; the Den API exposes them.

### How do I connect a user from my web app to the OpenWork desktop client?

Generate a one-time code via your backend's Den API, then use `buildConnectExchangeDeepLink` from the `connect-link` package to create an `openwork://connect?code=...&apiBaseUrl=...` URL. When the user clicks this link, the desktop app opens and authenticates automatically. The implementation lives in [`packages/connect-link/src/index.ts`](https://github.com/different-ai/openwork/blob/main/packages/connect-link/src/index.ts).

### Can I self-host the OpenWork API?

Yes. The `ee/apps/den-api` directory contains the complete API implementation. Set the `DEN_WEB_PROXY_PREFIX` environment variable (defaults to `/api/den` per [`ee/apps/den-api/src/mcp/resource.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/mcp/resource.ts)) and configure `env.inferenceProxyBaseUrl` for your model provider. The MCP endpoint and all REST routes deploy as a single service.