> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adrelay.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript SDK

> Official TypeScript/JavaScript SDK for the AdRelay API.

## Installation

```bash theme={null}
npm install @adrelay/sdk
```

Or with yarn:

```bash theme={null}
yarn add @adrelay/sdk
```

## Quick Start

```typescript theme={null}
import { AdRelay } from "@adrelay/sdk";

const client = new AdRelay({
  apiKey: process.env.ADRELAY_API_KEY!,
});

// List all campaigns
const { data, pagination } = await client.campaigns.list();
console.log(data); // AdsCampaign[]

// Filter by platform and status
const google = await client.campaigns.list({
  platform: "google_ads",
  status: "ACTIVE",
  limit: 10,
});
```

## Configuration

```typescript theme={null}
const client = new AdRelay({
  apiKey: process.env.ADRELAY_API_KEY!,
  baseUrl: "https://api.adrelay.dev/v1", // default
  maxRetries: 3, // retry on 429 and 5xx, default 3
});
```

## Campaigns

```typescript theme={null}
// List with cursor pagination
const page1 = await client.campaigns.list({ limit: 20 });
if (page1.pagination.hasMore) {
  const page2 = await client.campaigns.list({
    cursor: page1.pagination.cursor!,
  });
}

// Create
const { data: campaign } = await client.campaigns.create({
  platform: "google_ads",
  organization_id: "org_123",
  name: "Summer Sale 2026",
  budget_amount: 50.0,
  budget_period: "DAILY",
  goal: "SALES",
});

// Update
const { data: updated } = await client.campaigns.update("google_abc123", {
  organization_id: "org_123",
  status: "ACTIVE",
  budget_amount: 75.0,
});

// Delete
await client.campaigns.delete("google_abc123", "org_123");
```

## Ad Groups

```typescript theme={null}
// List ad groups (optionally filter by campaign)
const groups = await client.adGroups.list({
  campaign_id: "google_abc123",
  platform: "google_ads",
});

// Create
const { data: group } = await client.adGroups.create({
  platform: "google_ads",
  organization_id: "org_123",
  campaign_id: "google_abc123",
  name: "US Audience",
  bid_amount: 2.5,
});

// Update
const { data: updatedGroup } = await client.adGroups.update("google_ag456", {
  organization_id: "org_123",
  status: "PAUSED",
});

// Delete
await client.adGroups.delete("google_ag456", "org_123");
```

## Reports

```typescript theme={null}
const { data: reports } = await client.reports.list({
  platform: "google_ads",
  organization_id: "org_123",
  start_date: "2026-01-01",
  end_date: "2026-01-31",
  campaign_id: "google_abc123", // optional
});
```

## Connections

```typescript theme={null}
// List connected ad accounts
const { data: connections } = await client.connections.list();

// Get OAuth URL for a platform
const { data: { url } } = await client.connections.getAuthUrl("google");

// With custom redirect URI (user lands on your app after OAuth)
const { data: { url: customUrl } } = await client.connections.getAuthUrl("google", {
  redirectUri: "https://myapp.com/callback",
});

// Sync connection data
const { data: synced } = await client.connections.sync();

// Remove a connection
await client.connections.delete("conn_123");
```

## Redirect URIs

```typescript theme={null}
// List all redirect URIs (defaults + custom)
const { data } = await client.redirectUris.list();
console.log(data.defaults); // Pre-registered localhost URIs
console.log(data.custom);   // Your registered URIs

// Register a new redirect URI
const { data: newUri } = await client.redirectUris.create("https://myapp.com/callback");

// Delete a redirect URI
await client.redirectUris.delete(newUri.id);
```

## Error Handling

The SDK provides typed error classes for different failure modes:

```typescript theme={null}
import {
  AdRelay,
  AdRelayError,
  AdRelayAuthError,
  AdRelayRateLimitError,
  AdRelayPlatformError,
} from "@adrelay/sdk";

try {
  await client.campaigns.create({ /* ... */ });
} catch (error) {
  if (error instanceof AdRelayAuthError) {
    // 401 — invalid or missing API key
    console.error("Auth failed:", error.message);
  } else if (error instanceof AdRelayRateLimitError) {
    // 429 — exhausted after maxRetries
    console.error("Rate limited, retry after:", error.retryAfter);
  } else if (error instanceof AdRelayPlatformError) {
    // Upstream platform (Google/Meta/TikTok) returned an error
    console.error("Platform:", error.platform);
    console.error("Detail:", error.platformError);
  } else if (error instanceof AdRelayError) {
    // Any other API error
    console.error(`${error.code} (${error.status}): ${error.message}`);
    console.error("Retryable:", error.retryable);
    console.error("Request ID:", error.requestId);
  }
}
```

## Automatic Retries

The SDK automatically retries on `429` (rate limited) and `5xx` (server error) responses with exponential backoff (1s, 2s, 4s, up to 8s max). Authentication errors (`401`) and client errors (`4xx`) are never retried.

## TypeScript Support

All API types are re-exported from `@adrelay/types`:

```typescript theme={null}
import type {
  AdsCampaign,
  AdsGroup,
  AdsReport,
  AdsStatus,
  Platform,
} from "@adrelay/types";
```
