Skip to content
 

TypeScript SDK Reference

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.1.0

Pinned docs baseline

This reference is pinned to @agentoffernetwork/sdk@^1.1.0. Runtime baseline: Node 20+.

Use live mode with the placement id of a placement in a serviceable Application. Installation, package imports, and a local mock do not establish this access condition.

Primary Exports

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({
  placementId: 'plc_YOUR_PLACEMENT_ID',
  mode: 'live',
  baseUrl: 'https://api.aon.pro',
  timeout: 20000,
});
Parameter
placementId
stringRequired

Placement id (plc_…) sent as the X-AON-Placement-Id header. 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 placementId throws AonValidationError.
  • Any mode other than mock or live throws AonValidationError.
  • timeout <= 0 throws AonValidationError.

AgentOfferClient Surface

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.

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
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:

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.
  • offer.action.payload.url is the AON-tracked click link (an aon.link short link), not the advertiser destination. Open it unchanged: opening it records the click and redirects to the advertiser.

reportClick(event)

reportClick does not call a JSON click API. It performs a GET on the supplied AON tracking link and extracts the final tracking identifier from the URL. That GET records a click, so use reportClick only when you record the click without sending the user to offer.action.payload.url; opening the link already records it.

const click = await client.reportClick({
  offerId: offer.offerId,
  // The offer's tracked click link, unchanged.
  trackingUrl: offer.action.payload.url,
  timestamp: new Date().toISOString(),
  agentId: 'shopping-bot',
  sessionId: 'session-123',
  context: { conversationId: 'conv-456' },
});
 
console.log(click.trackingId);
console.log(click.timestamp);
Parameter
offerId
stringRequired

Offer identifier from query results.

trackingUrl
stringRequired

The selected offer's tracked click link (`offer.action.payload.url`), unchanged. 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.

const markdown = client.formatRecommendation(offer, {
  style: 'markdown',
  includeDisclosure: true,
  disclosureText: 'Sponsored',
  includePrice: true,
});
Parameter
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.

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.

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.

Mock Testing

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

const mock = (await initialize({ placementId: 'plc_A1b2C3d4E5f6G7h8', 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

ClassCodeWhen it is raised
AonValidationErrorVALIDATION_ERRORInvalid SDK configuration or invalid query content
AonAuthErrorAUTH_ERROR401 responses: the request did not identify a placement and anonymous mode was unavailable
AonRateLimitErrorRATE_LIMIT429 responses
AonNetworkErrorNETWORK_ERRORTimeout, transport, redirect, or non-JSON transport failures
AonApiErrorserver-providedAPI returned a business error code instead of SUCCESS

TypeScript live completion

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

Get your Placement ID

Review Authentication