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:
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.
const client = await initialize({
apiKey: process.env.AON_API_KEY!,
mode: 'live',
baseUrl: 'https://api.aon.pro',
timeout: 20000,
});apiKeyBearer token used for live API requests. Must be a non-empty string.
modemock returns local sample data; live uses the HTTP API.
baseUrlOverrides the default live API origin. Defaults to https://api.aon.pro.
timeoutTimeout in milliseconds. The live client defaults to 20000.
Validation behavior:
- Empty
apiKeythrowsAonValidationError. - Any mode other than
mockorlivethrowsAonValidationError. timeout <= 0throwsAonValidationError.
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 },
});requestIdOptional caller-supplied request identifier.
timestampOptional RFC 3339 timestamp.
testModeMarks the request as test traffic.
contextBounded platform, session, sessionId, and conversationId context. Long-term profiles are not sent on the Protocol v1.0 wire.
intent.contentAt least one content part. Supported variants are input_text and input_image.
intent.provenanceDefaults to user_expressed. Inferred intent requires a bounded confidence value.
constraintscategoryIds and excludedCategoryIds.
forceOfferPermits a qualified fallback Offer when an exact match is unavailable.
responseOptions.thinkingModeDefaults 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.requestIdmaps to protocoldata.request_id.queryIdis a deprecated legacy alias when present.- The SDK selects Protocol
1.0and validates returned Offers against the current contract. totalandhasMoreare SDK-derived conveniences, not protocol/OpenAPI response fields.- The SDK exposes protocol
offer_idasoffer.offerId,offer_instance_idasoffer.offerInstanceId, optionallisting_sourceasoffer.listingSource, and optionalmatch_reasonasoffer.matchReason.offer.listingSource.logo, when present, is an explicit absolute HTTPS URI for the platform/site Logo (percent-encode non-ASCII components; notentity.logo, action, or material); useoffer.listingSource.namewhen it is absent. - Advertiser destination is
offer.action.payload.url; the AON tracking endpoint is supplied separately viaClickEvent.trackingUrlby 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);offerIdOffer identifier from query results.
trackingUrlAON tracking URL supplied by your integration layer for the selected offer. Do not synthesize it from offerId.
timestampClient-side event timestamp.
agentIdOptional identifier for the calling agent.
sessionIdOptional session key for deduplication and analytics.
contextOptional 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,
});styleOutput style. Defaults to markdown.
includeDisclosureWhether to append the disclosure label. Defaults to true.
disclosureTextDisclosure label text. Defaults to Sponsored.
includePriceWhether 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.languageor 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 = apimcp-skill→platform.name = mcp-skill,platform.channel = mcpchatgpt→platform.name = chatgpt,platform.channel = actioncoze→platform.name = coze,platform.channel = plugin, native user IDs normalize tocoze:<id>dify→platform.name = dify,platform.channel = tool, native user IDs normalize todify:<id>
Notes:
- Explicit
platformName,channel,sessionId, anduserPseudoIdoverrides always win. - Empty native user IDs do not produce guessed
userPseudoIdvalues. - ChatGPT Action integrations should still omit
platformanduserPseudoIdin 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
| 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.