> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.agentrouter.to/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.agentrouter.to/_mcp/server.

# SDK

The TypeScript SDK is the best integration surface when you are building directly on AgentRouter from a server, worker, CLI, or agent runtime.

It stays capability-first:

1. list domains
2. inspect capabilities
3. inspect routes or contract
4. recommend a route
5. execute explicitly

Use the [API Reference](/api-reference) tab for endpoint-level HTTP detail. Use this page for SDK install guidance, integration patterns, and working examples.

## Why Start With The SDK

Use the SDK when you want:

* one explicit client object
* typed catalog discovery
* typed recommend and execute flows
* one place for API key, session token, and timeout configuration
* helper namespaces for `email`, `enrichment`, `social`, `post`, and `broadcast`
* raw response access when you need domain-specific fields without losing normalized metadata

Use [SKILL.md](/integrations/skills) when another coding agent should read instructions and make HTTP calls itself.

Use [CLI](/integrations/cli) when a human operator, support engineer, or CI job should run the same capability-first flow from a terminal.

Use [MCP](/integrations/mcp) when the runtime is MCP-compatible and you want hosted tool exposure.

## Install

```bash
npm install @agentrouter/agentrouter
```

The same package also ships the `agentrouter` CLI. See [CLI](/integrations/cli) when you want terminal-first workflows on top of the same SDK semantics.

## Create The Client

```ts
import {
  AgentRouterClient,
  DEFAULT_AGENTIC_API_BASE_URL,
} from "@agentrouter/agentrouter";

const client = new AgentRouterClient({
  apiKey: process.env.AGENTIC_API_KEY,
  baseUrl:
    process.env.AGENTIC_API_BASE_URL ?? DEFAULT_AGENTIC_API_BASE_URL,
  timeoutMs: 20_000,
});
```

Use this SDK from server-side runtimes only. Do not expose `AGENTIC_API_KEY` in browser code.

## Recommended Flow

```ts
const domains = await client.catalog.domains.list();
const capabilities = await client.catalog.capabilities.list("email");
```

```ts
const contract = await client.catalog.capabilities.contract("email", "send");
const routes = await client.catalog.capabilities.routes("email", "send");
```

```ts
const recommendation = await client.capabilities.recommend({
  domain: "email",
  capability: "send",
  input: {
    optimizationPreferences: ["cost", "quality"],
  },
});
```

```ts
const result = await client.capabilities.execute({
  domain: "email",
  capability: "send",
  input: {
    to: "maya@example.com",
    subject: "Hello from AgentRouter",
    html: "<p>Hello</p>",
  },
  provider: recommendation.recommendedProvider,
  allowFallback: true,
});
```

```ts
const wallet = await client.wallet.get();
const usage = await client.usage.list({ limit: 20 });
```

## Catalog First

```ts
const domains = await client.catalog.domains.list();
const capabilities = await client.catalog.capabilities.list("email");
const sendContract = await client.catalog.capabilities.contract("email", "send");
const sendRoutes = await client.catalog.capabilities.routes("email", "send");
```

The catalog is the source of truth for:

* canonical capability IDs
* capability contracts
* capability route metadata
* whether a domain supports intent routing

## Generic Capability Methods

```ts
const recommendation = await client.capabilities.recommend({
  domain: "email",
  capability: "send",
  input: {
    optimizationPreferences: ["cost", "quality"],
    sender: {
      mode: "platform_managed",
      replyTo: "ops@example.com",
    },
  },
});

const result = await client.capabilities.execute({
  domain: "email",
  capability: "send",
  input: {
    to: "maya@example.com",
    subject: "Hello from AgentRouter",
    html: "<p>Hello</p>",
  },
  provider: recommendation.recommendedProvider,
  allowFallback: true,
});
```

The generic capability methods are the stable contract.

## Broadcast Example: Quote First, Approve Send Separately

`broadcast.message.quote` is live. `broadcast.message.send` is mapped but intentionally gated because one live execute creates a real public post.

```ts
const quote = await client.capabilities.execute({
  domain: "broadcast",
  capability: "message-quote",
  routeKey: "broadcast.message.quote.billboard.mpp",
  input: {},
  allowFallback: false,
});

const sendRecommendation = await client.capabilities.recommend({
  domain: "broadcast",
  capability: "message-send",
  input: {
    text: "Launch update goes here.",
    optimizationPreferences: ["quality"],
  },
});
```

## Translation Example: DeepL Rephrase

`translation.text.rephrase.deepl.mpp` is live after the May 5, 2026 paid route-by-route retest. Use the generic capability methods and fetch route context before execution so your payload uses `text`, `targetLanguage`, and optional `tone`.

```ts
const routeContext = await client.catalog.routes.context(
  "translation.text.rephrase.deepl.mpp",
);

const rewrite = await client.capabilities.execute({
  domain: "translation",
  capability: "text-rephrase",
  routeKey: "translation.text.rephrase.deepl.mpp",
  input: {
    text: "Please make this product update friendlier.",
    targetLanguage: "EN-US",
    tone: "prefer_friendly",
  },
  allowFallback: false,
});

console.log(rewrite.rewrittenText);
```

## Geo Example: Abstract Timezone Conversion

`geo.time.current.abstract-timezone.mpp` and `geo.time.convert.abstract-timezone.mpp` are live after the May 9, 2026 paid route-by-route smoke. Use generic capability methods and fetch route context before execution so your payload uses `location` for current time or `fromLocation`, `toLocation`, and optional `datetime` for conversion.

```ts
const routeContext = await client.catalog.routes.context(
  "geo.time.convert.abstract-timezone.mpp",
);

const converted = await client.capabilities.execute({
  domain: "geo",
  capability: "time-convert",
  routeKey: "geo.time.convert.abstract-timezone.mpp",
  input: {
    fromLocation: "Los Angeles, CA",
    toLocation: "Tokyo, Japan",
    datetime: "2026-05-08 09:30:00",
  },
  allowFallback: false,
});

console.log(converted.convertedTime);
```

## Models Example: DeepSeek Chat Completion

`models.chat.complete.deepseek.mpp`, `models.code.complete.deepseek.mpp`, and `models.list.deepseek.mpp` are live through the generic capability surface after the May 5, 2026 production-mode smoke. Fetch route context before execution so your payload uses a supported model id such as `deepseek-v4-flash`.

```ts
const routeContext = await client.catalog.routes.context(
  "models.chat.complete.deepseek.mpp",
);

const modelChat = await client.capabilities.execute({
  domain: "models",
  capability: "chat-complete",
  routeKey: "models.chat.complete.deepseek.mpp",
  input: {
    model: "deepseek-v4-flash",
    messages: [
      {
        role: "user",
        content: "Say AgentRouter DeepSeek smoke OK.",
      },
    ],
  },
  allowFallback: false,
});

console.log(modelChat.completionText);
```

## Text Analysis Example: Recommend And Context Only

`text.analyze.diffbot-nl.mpp` is mapped and recommendable through Diffbot NL, but it is not live for execution yet. Direct Diffbot NL MPP wrapper checks on May 5, 2026 returned HTTP 429 before payment, so no AgentRouter credits were charged. Use recommend and route context until `canExecuteNow` is true and a paid route smoke succeeds.

```ts
const textRecommendation = await client.capabilities.recommend({
  domain: "text",
  capability: "analyze",
  input: {
    provider: "diffbot-nl",
    content: "AgentRouter routes text analysis through Diffbot NL.",
    fields: "entities,sentiment,language",
    optimizationPreferences: ["quality"],
  },
});

const textContext = await client.catalog.routes.context(
  "text.analyze.diffbot-nl.mpp",
);

console.log(textRecommendation.recommendedRouteKey);
console.log(textRecommendation.canExecuteNow);
console.log(textContext.routeKey);
```

## Media Example: fal Image Routes

fal image generation and image edit are live on MPP image routes. `media.video.generate.fal.mpp` remains gated after upstream paymentauth 524 timeouts reproduced outside AgentRouter, so use recommend and route context for video generation until paid smoke evidence exists.

```ts
const imageContext = await client.catalog.routes.context(
  "media.image.generate.fal.mpp",
);

const heroImage = await client.capabilities.execute({
  domain: "media",
  capability: "image-generate",
  routeKey: "media.image.generate.fal.mpp",
  input: {
    prompt: "Create a clean launch hero image for an AI developer tool",
    aspectRatio: "16:9",
  },
  provider: "fal",
  allowFallback: false,
});

console.log(imageContext.routeKey);
console.log(heroImage.primaryImageUrl);
```

## Web And Enrichment Example: Diffbot Routes

`web.extract.diffbot.mpp`, `enrichment.people.enrich.diffbot.mpp`, and `enrichment.company.enrich.diffbot.mpp` are live after the May 5, 2026 route-by-route retest. Fetch route context before execution so the SDK payload matches the selected Diffbot route.

```ts
const extractContext = await client.catalog.routes.context(
  "web.extract.diffbot.mpp",
);
const personContext = await client.catalog.routes.context(
  "enrichment.people.enrich.diffbot.mpp",
);
const companyContext = await client.catalog.routes.context(
  "enrichment.company.enrich.diffbot.mpp",
);

const article = await client.capabilities.execute({
  domain: "web",
  capability: "extract",
  routeKey: "web.extract.diffbot.mpp",
  input: {
    url: "https://www.example.com/article",
  },
  allowFallback: false,
});

const person = await client.capabilities.execute({
  domain: "enrichment",
  capability: "people-enrich",
  routeKey: "enrichment.people.enrich.diffbot.mpp",
  input: {
    fullName: "Sam Altman",
    companyName: "OpenAI",
  },
  allowFallback: false,
});

const company = await client.capabilities.execute({
  domain: "enrichment",
  capability: "company-enrich",
  routeKey: "enrichment.company.enrich.diffbot.mpp",
  input: {
    companyName: "OpenAI",
    domain: "openai.com",
  },
  allowFallback: false,
});

console.log(article.routeKey);
console.log(person.person);
console.log(company.company);
```

## Travel Example: Pin FlightAPI Airport Operations

When you need one concrete travel provider, fetch route context first and then pin the `routeKey` during execute:

```ts
const routeContext = await client.catalog.routes.context(
  "travel.airport.operations.flightapi.mpp",
);

const airportOperations = await client.capabilities.execute({
  domain: "travel",
  capability: "airport-operations",
  routeKey: "travel.airport.operations.flightapi.mpp",
  input: {
    iataCode: "JFK",
    mode: "departures",
    limit: 1,
  },
  provider: "flightapi",
  allowFallback: false,
});
```

Use the route context to confirm route-specific fields before execution. FlightAPI airport operations passed a May 8, 2026 production smoke through `travel.airport.operations.flightapi.mpp`.

## Domain Helpers And Examples

The SDK also exposes high-value helper namespaces:

```ts
client.email;
client.enrichment;
client.social;
client.post;
client.broadcast;
```

```ts
const recommendation = await client.email.send.recommend({
  optimizationPreferences: ["cost"],
});

const sent = await client.email.send.execute(
  {
    to: "maya@example.com",
    subject: "Hello from AgentRouter",
    html: "<p>Hello</p>",
  },
  {
    provider: recommendation.recommendedProvider,
    allowFallback: true,
  },
);
```

```ts
const routed = await client.enrichment.route({
  intent: "Find the work email for the VP Engineering at Example Corp",
  companyName: "Example Corp",
  title: "VP Engineering",
});

const contact = await client.enrichment.contactEnrich.execute(
  {
    linkedinUrl: "https://www.linkedin.com/in/example",
  },
  {
    allowFallback: true,
  },
);

const graphCompany = await client.capabilities.execute({
  domain: "enrichment",
  capability: "company-enrich",
  routeKey: "enrichment.company.enrich.diffbot.mpp",
  input: {
    companyName: "OpenAI",
    domain: "openai.com",
  },
  allowFallback: false,
});
```

```ts
const profile = await client.social.profileLookup.execute(
  {
    platform: "instagram",
    handle: "nike",
  },
  {
    allowFallback: true,
  },
);
```

## Response Model

Recommend, route, and execute responses preserve normalized fields and the raw backend payload:

```ts
const recommendation = await client.capabilities.recommend({
  domain: "email",
  capability: "send",
  input: {
    optimizationPreferences: ["cost", "quality"],
  },
});

console.log(recommendation.recommendedProvider);
console.log(recommendation.domainKey);
console.log(recommendation.capabilityId);
console.log(recommendation.raw);
```

That lets you keep a stable integration while still inspecting domain-specific fields when needed.

## Raw Requests And Auth

For endpoints that are not wrapped yet, you can fall back to the raw client:

```ts
const wallet = await client.raw.request<{
  userId: string;
  balanceCredits: number;
}>({
  path: "/wallet",
  authMode: "apiKey",
});
```

The SDK supports:

* API key auth for normal server-side usage
* session token auth for session-backed flows
* `userId` passthrough for local development helpers
* per-call `timeoutMs` overrides

## Observe Wallet And Usage

```ts
const wallet = await client.wallet.get();
const usage = await client.usage.list({ limit: 20 });
```

The SDK keeps wallet and usage close to execution so developers can audit spend and route behavior without switching abstractions.

## Compatibility Notes

* Canonical capability IDs come from the catalog.
* The canonical email inbox acquisition capability ID is `inbox-acquire`.
* The backend still accepts the legacy alias `inbox-buy`.
* The SDK exposes both `client.email.inbox.acquire` and `client.email.inbox.buy`, but both target the canonical capability under the hood.