# TypeScript SDK Reference

Source: https://docs.aon.pro/sdk/typescript

> Derived from the same AON Docs release as the source page.

Signature-first reference for `@agentoffernetwork/sdk`.

> Protocol default
>
> The live client sends the exact current selector `AON-Protocol-Version: 1.0`. Returned Offers follow the canonical Protocol v1.0 schema and generated SDK types.

> Package
>
> Install with `npm install @agentoffernetwork/sdk`. Current documented version:
>
> v1.0.0

> Pinned docs baseline
>
> This reference is pinned to `@agentoffernetwork/sdk@^1.0.0`. Runtime baseline: Node 20+.

Use live mode only with an issued Live Key owned by a serviceable Application. Installation, package imports, and a local mock do not establish this access condition.

## Primary Exports

```typescript
import {
  initialize,
  createContextForPlatform,
  detectContext,
  formatRecommendation,
  AON_CURRENT_PROTOCOL_VERSION,
  AON_PROTOCOL_VERSION_V10,
  type AgentOfferClient,
  type MockAgentOfferClient,
  type SDKConfig,
  type QueryOffersParams,
  type QueryConstraints,
  type QueryOffersResponse,
  type ClickEvent,
  type ConversionEvent,
  type FormatOptions,
} from '@agentoffernetwork/sdk';
```

## initialize(config)

Creates a client instance and selects the implementation by `mode`.

initialize(config)

TypeScript

```
const client = await initialize({
  apiKey: process.env.AON_API_KEY!,
  mode: 'live',
  baseUrl: 'https://api.aon.pro',
  timeout: 20000,
});
```

Parameter

Description

`apiKey`

stringRequired

Bearer token used for live API requests. Must be a non-empty string.

`mode`

"mock" | "live"Required

mock returns local sample data; live uses the HTTP API.

`baseUrl`

stringOptional

Overrides the default live API origin. Defaults to https://api.aon.pro.

`timeout`

numberOptional

Timeout in milliseconds. The live client defaults to 20000.

Validation behavior:

-   Empty `apiKey` throws `AonValidationError`.
-   Any mode other than `mock` or `live` throws `AonValidationError`.
-   `timeout <= 0` throws `AonValidationError`.

## AgentOfferClient Surface

```typescript
interface AgentOfferClient {
  queryOffers(params: QueryOffersParams): Promise<QueryOffersResponse>;
  reportClick(event: ClickEvent): Promise<ClickResult>;
  formatRecommendation(offer: Offer, options?: FormatOptions): string;
}
```

## queryOffers(params)

`queryOffers` serializes camelCase SDK fields to protocol snake\_case and sends `POST /v1/offers/query` in live mode.

```typescript
const response = await client.queryOffers({
  requestId: crypto.randomUUID(),
  context: {
    platform: { name: 'shopping-bot', channel: 'api' },
    session: { recentTopics: ['audio'] },
  },
  intent: {
    content: [
      { type: 'input_text', text: 'noise cancelling headphones under $200' },
    ],
    provenance: 'user_expressed',
    signals: { budget: { max: 200, currency: 'USD' } },
  },
  constraints: {
    categoryIds: ['computers_electronics.consumer_electronics'],
  },
  forceOffer: true,
  responseOptions: { thinkingMode: true },
});
```

Parameter

Description

`requestId`

stringOptional

Optional caller-supplied request identifier.

`timestamp`

stringOptional

Optional RFC 3339 timestamp.

`testMode`

booleanOptional

Marks the request as test traffic.

`context`

QueryContextRequired

Bounded platform, session, sessionId, and conversationId context. Long-term profiles are not sent on the Protocol v1.0 wire.

`intent.content`

ContentPart\[\]Required

At least one content part. Supported variants are input\_text and input\_image.

`intent.provenance`

user\_expressed | inferred\_contextOptional

Defaults to user\_expressed. Inferred intent requires a bounded confidence value.

`constraints`

QueryConstraintsOptional

categoryIds and excludedCategoryIds.

`forceOffer`

booleanOptional

Permits a qualified fallback Offer when an exact match is unavailable.

`responseOptions.thinkingMode`

booleanOptional

Defaults to true. Set false to omit offer matchReason values.

`QueryOffersResponse` shape:

```typescript
interface QueryOffersResponse {
  requestId: string;
  offers: Offer[];
  /** @deprecated Legacy compatibility alias for requestId. */
  queryId?: string;
  /** SDK-derived convenience, not a protocol response field. */
  total?: number;
  /** SDK-derived convenience, not a protocol response field. */
  hasMore?: boolean;
}
```

Important notes:

-   `validateContent()` runs before the HTTP request.
-   `requestId` maps to protocol `data.request_id`. `queryId` is a deprecated legacy alias when present.
-   The SDK selects Protocol `1.0` and validates returned Offers against the current contract.
-   `total` and `hasMore` are SDK-derived conveniences, not protocol/OpenAPI response fields.
-   The SDK exposes protocol `offer_id` as `offer.offerId`, `offer_instance_id` as `offer.offerInstanceId`, optional `listing_source` as `offer.listingSource`, and optional `match_reason` as `offer.matchReason`. `offer.listingSource.logo`, when present, is an explicit absolute HTTPS URI for the platform/site Logo (percent-encode non-ASCII components; not `entity.logo`, action, or material); use `offer.listingSource.name` when it is absent.
-   Advertiser destination is `offer.action.payload.url`; the AON tracking endpoint is supplied separately via `ClickEvent.trackingUrl` by your integration layer.

## reportClick(event)

`reportClick` does not call a JSON click API. It performs a `GET` on the supplied AON tracking endpoint and extracts the final tracking identifier from the URL.

```typescript
const click = await client.reportClick({
  offerId: offer.offerId,
  // In live mode, use the exact AON tracking URL supplied by your integration layer.
  // Do not replace it with the advertiser destination (`offer.action.payload.url`).
  trackingUrl: process.env.AON_TRACKING_ENDPOINT ?? 'https://tracking.example.test/click/mock-track-1',
  timestamp: new Date().toISOString(),
  agentId: 'shopping-bot',
  sessionId: 'session-123',
  context: { conversationId: 'conv-456' },
});
 
console.log(click.trackingId);
console.log(click.timestamp);
```

Parameter

Description

`offerId`

stringRequired

Offer identifier from query results.

`trackingUrl`

stringRequired

AON tracking URL supplied by your integration layer for the selected offer. Do not synthesize it from offerId.

`timestamp`

stringRequired

Client-side event timestamp.

`agentId`

stringOptional

Optional identifier for the calling agent.

`sessionId`

stringOptional

Optional session key for deduplication and analytics.

`context`

Record<string, unknown>Optional

Optional structured metadata.

## formatRecommendation(offer, options?)

Formats an `Offer` into display-ready text. The standalone export and the client method share the same implementation.

```typescript
const markdown = client.formatRecommendation(offer, {
  style: 'markdown',
  includeDisclosure: true,
  disclosureText: 'Sponsored',
  includePrice: true,
});
```

Parameter

Description

`style`

"brief" | "detailed" | "markdown"Optional

Output style. Defaults to markdown.

`includeDisclosure`

booleanOptional

Whether to append the disclosure label. Defaults to true.

`disclosureText`

stringOptional

Disclosure label text. Defaults to Sponsored.

`includePrice`

booleanOptional

Whether to include price if the offer contains one. Defaults to true.

## detectContext(overrides?)

`detectContext()` builds a `QueryContext` with platform, language, and session defaults. In TypeScript it also keeps a rolling top-10 interest history.

```typescript
const context = detectContext({
  platformName: 'custom-agent',
  channel: 'api',
  userPseudoId: 'anon-42',
  interests: ['travel', 'credit cards'],
});
```

Auto-detection behavior:

-   Non-TTY Node processes default to `mcp-skill` / `mcp`.
-   Browser environments default to `web` / `action`.
-   Other runtimes default to `sdk` / `api`.
-   `navigator.language` or process locale is used for language detection.

`web` / `action` is kept for backward compatibility in `detectContext()`. New explicit platform attribution should use `createContextForPlatform()`.

## createContextForPlatform(target, options?)

Use the explicit platform adapter when the host platform is already known.

```typescript
const mcpContext = createContextForPlatform('mcp-skill', {
  interests: ['Apple ecosystem user'],
});
 
const cozeContext = createContextForPlatform('coze', {
  nativeUserId: 'user-123',
  nativeSessionId: 'conv-1',
});
```

Built-in targets:

-   `sdk` → `platform.name = sdk`, `platform.channel = api`
-   `mcp-skill` → `platform.name = mcp-skill`, `platform.channel = mcp`
-   `chatgpt` → `platform.name = chatgpt`, `platform.channel = action`
-   `coze` → `platform.name = coze`, `platform.channel = plugin`, native user IDs normalize to `coze:<id>`
-   `dify` → `platform.name = dify`, `platform.channel = tool`, native user IDs normalize to `dify:<id>`

Notes:

-   Explicit `platformName`, `channel`, `sessionId`, and `userPseudoId` overrides always win.
-   Empty native user IDs do not produce guessed `userPseudoId` values.
-   ChatGPT Action integrations should still omit `platform` and `userPseudoId` in the request body; the F011 server path injects them automatically.

## Mock Testing

Mock mode returns a `MockAgentOfferClient`. Cast once if you want the extra inspection method.

```typescript
const mock = (await initialize({ apiKey: 'test-key', mode: 'mock' })) as MockAgentOfferClient;
 
await mock.reportClick({
  offerId: 'offer-1',
  trackingUrl: 'https://example.com/track/mock-track-1',
  timestamp: new Date().toISOString(),
});
 
console.log(mock.getRecordedEvents());
```

## Error Classes

| Class | Code | When it is raised |
| --- | --- | --- |
| `AonValidationError` | `VALIDATION_ERROR` | Invalid SDK configuration or invalid query content |
| `AonAuthError` | `AUTH_ERROR` | 401 responses or failed authentication |
| `AonRateLimitError` | `RATE_LIMIT` | 429 responses |
| `AonNetworkError` | `NETWORK_ERROR` | Timeout, transport, redirect, or non-JSON transport failures |
| `AonApiError` | server-provided | API returned a business error code instead of `SUCCESS` |

## TypeScript live completion

The TypeScript path is complete only when `queryOffers` with your issued Live Key returns a canonical v1.0 result. Empty offers or `data.empty_reason` are valid results. A local mock, authentication failure, or protocol failure is not live completion.

## Related Python reference

-   [Python SDK Reference](https://docs.aon.pro/sdk/python)

## Related Pages

-   [SDK Overview](https://docs.aon.pro/sdk)
-   [TypeScript SDK Guide](https://docs.aon.pro/guides/sdk-typescript)

[Review Production Access & API Keys](https://docs.aon.pro/quickstart/get-api-key)

[Review Authentication](https://docs.aon.pro/api/authentication)
