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

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

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

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

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

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

ClassCodeWhen it is raised
AonValidationErrorVALIDATION_ERRORInvalid SDK configuration or invalid query content
AonAuthErrorAUTH_ERROR401 responses or failed authentication
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 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.

Review Production Access & API Keys

Review Authentication