@gravity-ai/api 0.1.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,14 +17,18 @@ import { Client } from '@gravity-ai/api';
17
17
 
18
18
  const client = new Client('your-api-key');
19
19
 
20
- const ad = await client.getAd({
20
+ // Contextual ads (v1 API)
21
+ const response = await client.contextualAd({
21
22
  messages: [
22
23
  { role: 'user', content: 'What are some good hiking trails?' },
23
24
  { role: 'assistant', content: 'Here are some popular trails...' }
24
- ]
25
+ ],
26
+ sessionId: 'session-123', // Recommended
27
+ userId: 'user-456', // Recommended
25
28
  });
26
29
 
27
- if (ad) {
30
+ if (response) {
31
+ const ad = response.ads[0];
28
32
  console.log(ad.adText);
29
33
  }
30
34
  ```
@@ -61,29 +65,47 @@ const client = new Client('your-api-key', {
61
65
  | `excludedTopics` | `string[]` | `[]` | Topics to exclude from ad matching |
62
66
  | `relevancy` | `number \| null` | `null` | Minimum relevancy score (0-1) |
63
67
 
64
- ## Fetching Ads
68
+ ---
65
69
 
66
- ### Basic Request
70
+ ## v1 API Methods
71
+
72
+ The v1 API provides explicit endpoints for different ad types with multi-ad support.
73
+
74
+ ### `contextualAd()` — Contextual Ads
75
+
76
+ Fetch ads based on conversation context. Requires `messages` array.
67
77
 
68
78
  ```typescript
69
- const ad = await client.getAd({
79
+ const response = await client.contextualAd({
70
80
  messages: [
71
81
  { role: 'user', content: 'I need help finding a new laptop.' },
72
82
  { role: 'assistant', content: 'What is your budget?' }
73
- ]
83
+ ],
84
+ sessionId: 'session-123', // Recommended
85
+ userId: 'user-456', // Recommended
86
+ numAds: 1, // 1-3, default 1
74
87
  });
88
+
89
+ if (response) {
90
+ const ad = response.ads[0];
91
+ console.log(ad.adText);
92
+ }
75
93
  ```
76
94
 
77
- ### Full Request with All Options
95
+ #### Full Request with All Options
78
96
 
79
97
  ```typescript
80
- const ad = await client.getAd({
98
+ const response = await client.contextualAd({
81
99
  // Required: conversation messages
82
100
  messages: [
83
101
  { role: 'user', content: 'I need help finding a new laptop.' },
84
102
  { role: 'assistant', content: 'What is your budget?' }
85
103
  ],
86
104
 
105
+ // Recommended: session/user tracking (improves ad relevance & revenue)
106
+ sessionId: 'session-123',
107
+ userId: 'user-456',
108
+
87
109
  // Optional: user information for targeting
88
110
  user: {
89
111
  uid: 'user-123', // Unique user identifier
@@ -101,27 +123,158 @@ const ad = await client.getAd({
101
123
  ifa: 'device-ad-id', // Advertising identifier
102
124
  },
103
125
 
104
- // Optional: additional targeting context
105
- excludedTopics: ['politics'], // Override client-level exclusions
106
- relevancy: 0.8, // Override client-level relevancy
126
+ // Optional: ad request settings
127
+ excludedTopics: ['politics'], // Topics to exclude
128
+ relevancy: 0.8, // Min relevancy threshold (0-1)
129
+ numAds: 1, // Number of ads (1-3)
130
+ testAd: false, // Return test ad when true
107
131
 
108
- // Optional: custom fields (open-ended)
132
+ // Optional: custom fields (open-ended, passed to matching)
109
133
  interests: ['coding', 'apple', 'software development'],
110
134
  summary: 'User wants a laptop for software development',
111
135
  });
112
136
  ```
113
137
 
114
- ### Request Parameters
138
+ ### `summaryAd()` — Summary-Based Ads
139
+
140
+ Fetch ads based on a search query or summary string. Requires `queryString`.
141
+
142
+ ```typescript
143
+ const response = await client.summaryAd({
144
+ queryString: 'User wants a laptop for software development',
145
+ sessionId: 'session-123',
146
+ userId: 'user-456',
147
+ });
148
+
149
+ if (response) {
150
+ const ad = response.ads[0];
151
+ console.log(ad.adText);
152
+ }
153
+ ```
154
+
155
+ ### `nonContextualAd()` — Non-Contextual Ads
156
+
157
+ Fetch ads without context matching. Ideal for:
158
+ - **Integration testing** — Test your ad implementation on a subset of users before rolling out contextual ads
159
+ - **Brand awareness** — Show ads without requiring conversation context
160
+ - **Fallback placements** — Ad slots where context isn't available
161
+
162
+ ```typescript
163
+ const response = await client.nonContextualAd({
164
+ sessionId: 'session-123',
165
+ userId: 'user-456',
166
+ numAds: 2, // Request multiple ads
167
+ });
168
+
169
+ if (response) {
170
+ response.ads.forEach(ad => console.log(ad.adText));
171
+ }
172
+ ```
173
+
174
+ ### `bid()` + `render()` — Two-Phase Flow
175
+
176
+ For publishers who need to know the clearing price before rendering the ad.
177
+
178
+ ```typescript
179
+ // Phase 1: Get bid price
180
+ const bidResult = await client.bid({
181
+ messages: [
182
+ { role: 'user', content: 'I need help with my code' }
183
+ ],
184
+ sessionId: 'session-123',
185
+ });
186
+
187
+ if (bidResult) {
188
+ console.log(`Clearing price: $${bidResult.bid} CPM`);
189
+ console.log(`Bid ID: ${bidResult.bidId}`);
190
+
191
+ // Decide whether to show ad based on price...
192
+
193
+ // Phase 2: Render the ad
194
+ const response = await client.render({
195
+ bidId: bidResult.bidId,
196
+ realizedPrice: bidResult.bid,
197
+ });
198
+
199
+ if (response) {
200
+ const ad = response.ads[0];
201
+ console.log(ad.adText);
202
+ }
203
+ }
204
+ ```
205
+
206
+ > **Note:** Bids expire after 60 seconds. Call `render()` promptly after `bid()`.
207
+
208
+ ---
209
+
210
+ ## v1 Request Parameters
211
+
212
+ ### Base Parameters (All v1 Methods)
115
213
 
116
214
  | Parameter | Type | Required | Description |
117
215
  |-----------|------|----------|-------------|
118
- | `messages` | `MessageObject[]` | | Conversation history |
119
- | `user` | `UserObject` | - | User targeting info |
216
+ | `sessionId` | `string` | Recommended | Session identifier for tracking |
217
+ | `userId` | `string` | Recommended | User identifier for frequency capping |
120
218
  | `device` | `DeviceObject` | - | Device/location info |
219
+ | `user` | `UserObject` | - | User targeting info |
121
220
  | `excludedTopics` | `string[]` | - | Topics to exclude |
122
221
  | `relevancy` | `number` | - | Min relevancy (0-1) |
123
- | `apiKey` | `string` | - | Override client API key |
124
- | `[key: string]` | `any` | - | Custom fields allowed |
222
+ | `numAds` | `number` | - | Number of ads (1-3, default 1) |
223
+ | `testAd` | `boolean` | - | Return test ad when true |
224
+
225
+ ### Method-Specific Parameters
226
+
227
+ | Method | Required Parameter | Description |
228
+ |--------|-------------------|-------------|
229
+ | `contextualAd()` | `messages: MessageObject[]` | Conversation history |
230
+ | `summaryAd()` | `queryString: string` | Search/summary query |
231
+ | `nonContextualAd()` | None | No context required |
232
+ | `bid()` | `messages: MessageObject[]` | Conversation for bid |
233
+ | `render()` | `bidId: string`, `realizedPrice: number` | From bid response |
234
+
235
+ ---
236
+
237
+ ## v1 Response Types
238
+
239
+ ### AdResponseV1
240
+
241
+ Returned by `contextualAd()`, `summaryAd()`, `nonContextualAd()`, and `render()`.
242
+
243
+ ```typescript
244
+ interface AdResponseV1 {
245
+ ads: AdV1[]; // Array of ads
246
+ numAds: number; // Number of ads returned
247
+ totalPayout?: number; // Total payout across all ads
248
+ }
249
+
250
+ interface AdV1 {
251
+ adText: string; // Ad copy text
252
+ adId: string; // Unique ad identifier
253
+ title?: string; // Ad title
254
+ brandName?: string; // Brand name
255
+ brandImage?: string; // Brand logo URL
256
+ url?: string; // Landing page URL
257
+ favicon?: string; // Favicon URL
258
+ impUrl?: string; // Impression tracking URL
259
+ clickUrl?: string; // Click-through URL
260
+ payout?: number; // Payout amount
261
+ }
262
+ ```
263
+
264
+ ### BidResponse
265
+
266
+ Returned by `bid()`.
267
+
268
+ ```typescript
269
+ interface BidResponse {
270
+ bid: number; // Clearing price (CPM)
271
+ bidId: string; // Use this in render()
272
+ }
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Common Types
125
278
 
126
279
  ### Message Object
127
280
 
@@ -155,39 +308,59 @@ interface DeviceObject {
155
308
  }
156
309
  ```
157
310
 
158
- ## Ad Response
311
+ ---
312
+
313
+ ## Legacy API (v0)
159
314
 
160
- The `getAd` method returns an `AdResponse` object or `null` if no relevant ad is found.
315
+ The original `getAd()` method is still available for backward compatibility.
316
+
317
+ ### Basic Request
318
+
319
+ ```typescript
320
+ const ad = await client.getAd({
321
+ messages: [
322
+ { role: 'user', content: 'I need help finding a new laptop.' },
323
+ { role: 'assistant', content: 'What is your budget?' }
324
+ ]
325
+ });
326
+ ```
327
+
328
+ ### Full Request with All Options
329
+
330
+ ```typescript
331
+ const ad = await client.getAd({
332
+ messages: [...],
333
+ user: { uid: 'user-123', gender: 'male', age: '25-34' },
334
+ device: { ip: '1.2.3.4', country: 'US', ua: 'Mozilla/5.0...' },
335
+ excludedTopics: ['politics'],
336
+ relevancy: 0.8,
337
+ });
338
+ ```
339
+
340
+ ### Legacy Response
161
341
 
162
342
  ```typescript
163
343
  interface AdResponse {
164
344
  adText: string; // The ad copy to display
165
- impUrl?: string; // Impression tracking URL (fire on view)
345
+ impUrl?: string; // Impression tracking URL
166
346
  clickUrl?: string; // Click-through URL
167
347
  payout?: number; // Payout amount
168
348
  }
169
349
  ```
170
350
 
171
- ### Handling the Response
351
+ ### Handling the Legacy Response
172
352
 
173
353
  ```typescript
174
354
  const ad = await client.getAd({ messages });
175
355
 
176
356
  if (ad) {
177
- // Display the ad
178
357
  console.log('Ad:', ad.adText);
179
358
 
180
- // Track impression (fire pixel)
359
+ // Track impression
181
360
  if (ad.impUrl) {
182
- fetch(ad.impUrl); // or use an image beacon
183
- }
184
-
185
- // Handle clicks
186
- if (ad.clickUrl) {
187
- // Navigate user to ad.clickUrl on click
361
+ fetch(ad.impUrl);
188
362
  }
189
363
  } else {
190
- // No relevant ad found - show fallback or nothing
191
364
  console.log('No ad available');
192
365
  }
193
366
  ```
@@ -197,15 +370,16 @@ if (ad) {
197
370
  The client handles errors gracefully and returns `null` on failure. Errors are logged to the console.
198
371
 
199
372
  ```typescript
200
- const ad = await client.getAd({ messages });
373
+ const response = await client.contextualAd({ messages, sessionId: '...' });
201
374
 
202
375
  // Returns null on:
203
376
  // - Network errors
204
377
  // - API errors (4xx, 5xx)
205
378
  // - No relevant ad (204)
206
379
  // - Invalid response data
380
+ // - Expired bid (404 for render())
207
381
 
208
- if (!ad) {
382
+ if (!response) {
209
383
  // Handle gracefully - don't break the user experience
210
384
  }
211
385
  ```
@@ -216,7 +390,24 @@ Full TypeScript support with exported types:
216
390
 
217
391
  ```typescript
218
392
  import { Client, ClientParams } from '@gravity-ai/api';
219
- import type { AdParams, AdResponse, MessageObject, DeviceObject, UserObject } from '@gravity-ai/api';
393
+ import type {
394
+ // v1 types
395
+ ContextualAdParams,
396
+ SummaryAdParams,
397
+ NonContextualAdParams,
398
+ BidParams,
399
+ RenderParams,
400
+ AdV1,
401
+ AdResponseV1,
402
+ BidResponse,
403
+ // Common types
404
+ MessageObject,
405
+ DeviceObject,
406
+ UserObject,
407
+ // Legacy types
408
+ AdParams,
409
+ AdResponse,
410
+ } from '@gravity-ai/api';
220
411
  ```
221
412
 
222
413
  ## Using with React
@@ -237,13 +428,31 @@ function ChatApp() {
237
428
  const [ad, setAd] = useState(null);
238
429
 
239
430
  useEffect(() => {
240
- client.getAd({ messages }).then(setAd);
431
+ client.contextualAd({
432
+ messages,
433
+ sessionId: 'session-123',
434
+ userId: 'user-456',
435
+ }).then(res => setAd(res?.ads[0] || null));
241
436
  }, [messages]);
242
437
 
243
438
  return <AdBanner ad={ad} theme="dark" />;
244
439
  }
245
440
  ```
246
441
 
442
+ ## Best Practices
443
+
444
+ 1. **Always include `sessionId` and `userId`** — These directly impact publisher revenue through better frequency capping and ad relevance.
445
+
446
+ 2. **Choose the right method**:
447
+ - Chat/conversation → `contextualAd()`
448
+ - Chat summary → `summaryAd()`
449
+ - Brand awareness → `nonContextualAd()`
450
+ - Custom auction → `bid()` + `render()`
451
+
452
+ 3. **Handle null responses gracefully** — Don't break the user experience when no ad is available.
453
+
454
+ 4. **Fire impression url** — Use the `impUrl` when the ad becomes visible to properly track impressions.
455
+
247
456
  ## License
248
457
 
249
458
  MIT
package/dist/index.d.mts CHANGED
@@ -153,6 +153,127 @@ interface ApiErrorResponse {
153
153
  /** HTTP status code */
154
154
  statusCode?: number;
155
155
  }
156
+ /**
157
+ * Base fields shared across all v1 ad requests.
158
+ * @description Mirrors engine's AdRequestBaseV1. All fields are optional.
159
+ */
160
+ interface AdRequestBaseV1 {
161
+ /** Session identifier for tracking user sessions */
162
+ sessionId?: string;
163
+ /** Unique user identifier */
164
+ userId?: string;
165
+ /** Device and location information */
166
+ device?: DeviceObject;
167
+ /** User demographic and interest data */
168
+ user?: UserObject;
169
+ /** Topics to exclude from ad matching */
170
+ excludedTopics?: string[];
171
+ /** Minimum relevancy score threshold (0-1) */
172
+ relevancy?: number | null;
173
+ /** Number of ads to return (1-3, default 1) */
174
+ numAds?: number;
175
+ /** Returns a test ad when true */
176
+ testAd?: boolean;
177
+ /** Additional custom fields */
178
+ [key: string]: unknown;
179
+ }
180
+ /**
181
+ * POST /api/v1/ad/contextual
182
+ * @description Requires messages array for contextual targeting.
183
+ */
184
+ interface ContextualAdParams extends AdRequestBaseV1 {
185
+ /** Array of conversation messages (required) */
186
+ messages: MessageObject[];
187
+ }
188
+ /**
189
+ * POST /api/v1/ad/summary
190
+ * @description Requires queryString for summary-based targeting.
191
+ */
192
+ interface SummaryAdParams extends AdRequestBaseV1 {
193
+ /** Search/summary query string (required) */
194
+ queryString: string;
195
+ }
196
+ /**
197
+ * POST /api/v1/ad/non-contextual
198
+ * @description No context required - returns ads without context matching.
199
+ */
200
+ interface NonContextualAdParams extends AdRequestBaseV1 {
201
+ }
202
+ /**
203
+ * POST /api/v1/bid
204
+ * @description Two-phase bid request. Returns bid price and bidId.
205
+ * @note Does NOT extend AdRequestBaseV1 - has its own field set.
206
+ */
207
+ interface BidParams {
208
+ /** Array of conversation messages (required) */
209
+ messages: MessageObject[];
210
+ /** Session identifier */
211
+ sessionId?: string;
212
+ /** Unique user identifier */
213
+ userId?: string;
214
+ /** Chat/conversation identifier */
215
+ chatId?: string;
216
+ /** Device and location information */
217
+ device?: DeviceObject;
218
+ }
219
+ /**
220
+ * POST /api/v1/render
221
+ * @description Two-phase render request using cached bid context.
222
+ */
223
+ interface RenderParams {
224
+ /** Bid identifier from the bid phase (required) */
225
+ bidId: string;
226
+ /** Realized price to charge (required) */
227
+ realizedPrice: number;
228
+ }
229
+ /**
230
+ * Single ad object in v1 responses.
231
+ * @description Contains all ad creative and tracking data.
232
+ */
233
+ interface AdV1 {
234
+ /** The advertisement copy text */
235
+ adText: string;
236
+ /** Unique ad identifier */
237
+ adId: string;
238
+ /** Ad title */
239
+ title?: string;
240
+ /** Brand/advertiser name */
241
+ brandName?: string;
242
+ /** Brand logo image URL */
243
+ brandImage?: string;
244
+ /** Landing page URL */
245
+ url?: string;
246
+ /** Favicon URL */
247
+ favicon?: string;
248
+ /** Impression tracking URL */
249
+ impUrl?: string;
250
+ /** Click-through tracking URL */
251
+ clickUrl?: string;
252
+ /** Payout amount in USD */
253
+ payout?: number;
254
+ }
255
+ /**
256
+ * v1 ad response (multi-ad support).
257
+ * @description Returned by contextual, summary, non-contextual, and render endpoints.
258
+ */
259
+ interface AdResponseV1 {
260
+ /** Array of ad objects */
261
+ ads: AdV1[];
262
+ /** Number of ads returned */
263
+ numAds: number;
264
+ /** Total payout across all ads */
265
+ totalPayout?: number;
266
+ }
267
+ /**
268
+ * v1 bid response.
269
+ * @description Returned by the bid endpoint.
270
+ */
271
+ interface BidResponse {
272
+ /** Clearing price (CPM) */
273
+ bid: number;
274
+ /** Bid identifier for the render phase */
275
+ bidId: string;
276
+ }
156
277
 
157
278
  /**
158
279
  * Configuration options for the Gravity API Client
@@ -303,6 +424,131 @@ declare class Client {
303
424
  * ```
304
425
  */
305
426
  getAd(params: AdParams): Promise<AdResponse | null>;
427
+ /**
428
+ * Request contextual advertisements (v1 API)
429
+ *
430
+ * @description Fetches ads based on conversation context. Requires messages array.
431
+ * Returns null if no relevant ad is available or on error.
432
+ *
433
+ * @param params - Request parameters including messages array
434
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
435
+ *
436
+ * @example
437
+ * ```typescript
438
+ * const response = await client.contextualAd({
439
+ * messages: [
440
+ * { role: 'user', content: 'What laptop should I buy?' }
441
+ * ],
442
+ * sessionId: 'session-123',
443
+ * userId: 'user-456',
444
+ * });
445
+ *
446
+ * if (response) {
447
+ * const ad = response.ads[0];
448
+ * console.log(ad.adText);
449
+ * }
450
+ * ```
451
+ */
452
+ contextualAd(params: ContextualAdParams): Promise<AdResponseV1 | null>;
453
+ /**
454
+ * Request summary-based advertisements (v1 API)
455
+ *
456
+ * @description Fetches ads based on a search/summary query string.
457
+ * Returns null if no relevant ad is available or on error.
458
+ *
459
+ * @param params - Request parameters including queryString
460
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
461
+ *
462
+ * @example
463
+ * ```typescript
464
+ * const response = await client.summaryAd({
465
+ * queryString: 'best laptops for programming 2025',
466
+ * sessionId: 'session-123',
467
+ * });
468
+ *
469
+ * if (response) {
470
+ * const ad = response.ads[0];
471
+ * console.log(ad.adText);
472
+ * }
473
+ * ```
474
+ */
475
+ summaryAd(params: SummaryAdParams): Promise<AdResponseV1 | null>;
476
+ /**
477
+ * Request non-contextual advertisements (v1 API)
478
+ *
479
+ * @description Fetches ads without context matching. Useful for brand awareness placements.
480
+ * Returns null if no ad is available or on error.
481
+ *
482
+ * @param params - Optional request parameters
483
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
484
+ *
485
+ * @example
486
+ * ```typescript
487
+ * const response = await client.nonContextualAd({
488
+ * sessionId: 'session-123',
489
+ * numAds: 2,
490
+ * });
491
+ *
492
+ * if (response) {
493
+ * response.ads.forEach(ad => console.log(ad.adText));
494
+ * }
495
+ * ```
496
+ */
497
+ nonContextualAd(params?: NonContextualAdParams): Promise<AdResponseV1 | null>;
498
+ /**
499
+ * Request a bid price for contextual ad placement (v1 API)
500
+ *
501
+ * @description First phase of two-phase ad flow. Returns bid price and bidId.
502
+ * Use the bidId with render() to generate the actual ad creative.
503
+ * Returns null if no bid is available or on error.
504
+ *
505
+ * @param params - Request parameters including messages array
506
+ * @returns Promise resolving to BidResponse or null if no bid available
507
+ *
508
+ * @example
509
+ * ```typescript
510
+ * const bidResult = await client.bid({
511
+ * messages: [
512
+ * { role: 'user', content: 'I need help with my code' }
513
+ * ],
514
+ * sessionId: 'session-123',
515
+ * });
516
+ *
517
+ * if (bidResult) {
518
+ * console.log(`Bid price: $${bidResult.bid} CPM`);
519
+ * // Decide whether to show ad based on price...
520
+ * const ad = await client.render({
521
+ * bidId: bidResult.bidId,
522
+ * realizedPrice: bidResult.bid,
523
+ * });
524
+ * }
525
+ * ```
526
+ */
527
+ bid(params: BidParams): Promise<BidResponse | null>;
528
+ /**
529
+ * Render an ad from a cached bid (v1 API)
530
+ *
531
+ * @description Second phase of two-phase ad flow. Generates ad creative using cached bid context.
532
+ * Returns null if bid expired (404) or on error. Bid expires after 60 seconds.
533
+ *
534
+ * @param params - Request parameters including bidId and realizedPrice
535
+ * @returns Promise resolving to AdResponseV1 or null if bid expired/error
536
+ *
537
+ * @example
538
+ * ```typescript
539
+ * // After getting a bid...
540
+ * const ad = await client.render({
541
+ * bidId: bidResult.bidId,
542
+ * realizedPrice: bidResult.bid,
543
+ * });
544
+ *
545
+ * if (ad) {
546
+ * const firstAd = ad.ads[0];
547
+ * displayAd(firstAd);
548
+ * }
549
+ * ```
550
+ */
551
+ render(params: RenderParams): Promise<AdResponseV1 | null>;
306
552
  /**
307
553
  * Handle and log API errors
308
554
  *
@@ -317,4 +563,4 @@ declare class Client {
317
563
  private handleError;
318
564
  }
319
565
 
320
- export { type AdParams, type AdResponse, type ApiErrorResponse, Client, type ClientParams };
566
+ export { type AdParams, type AdRequestBaseV1, type AdResponse, type AdResponseV1, type AdV1, type ApiErrorResponse, type BidParams, type BidResponse, Client, type ClientParams, type ContextualAdParams, type DeviceObject, type Gender, type MessageObject, type NonContextualAdParams, type RenderParams, type Role, type SummaryAdParams, type UserObject };
package/dist/index.d.ts CHANGED
@@ -153,6 +153,127 @@ interface ApiErrorResponse {
153
153
  /** HTTP status code */
154
154
  statusCode?: number;
155
155
  }
156
+ /**
157
+ * Base fields shared across all v1 ad requests.
158
+ * @description Mirrors engine's AdRequestBaseV1. All fields are optional.
159
+ */
160
+ interface AdRequestBaseV1 {
161
+ /** Session identifier for tracking user sessions */
162
+ sessionId?: string;
163
+ /** Unique user identifier */
164
+ userId?: string;
165
+ /** Device and location information */
166
+ device?: DeviceObject;
167
+ /** User demographic and interest data */
168
+ user?: UserObject;
169
+ /** Topics to exclude from ad matching */
170
+ excludedTopics?: string[];
171
+ /** Minimum relevancy score threshold (0-1) */
172
+ relevancy?: number | null;
173
+ /** Number of ads to return (1-3, default 1) */
174
+ numAds?: number;
175
+ /** Returns a test ad when true */
176
+ testAd?: boolean;
177
+ /** Additional custom fields */
178
+ [key: string]: unknown;
179
+ }
180
+ /**
181
+ * POST /api/v1/ad/contextual
182
+ * @description Requires messages array for contextual targeting.
183
+ */
184
+ interface ContextualAdParams extends AdRequestBaseV1 {
185
+ /** Array of conversation messages (required) */
186
+ messages: MessageObject[];
187
+ }
188
+ /**
189
+ * POST /api/v1/ad/summary
190
+ * @description Requires queryString for summary-based targeting.
191
+ */
192
+ interface SummaryAdParams extends AdRequestBaseV1 {
193
+ /** Search/summary query string (required) */
194
+ queryString: string;
195
+ }
196
+ /**
197
+ * POST /api/v1/ad/non-contextual
198
+ * @description No context required - returns ads without context matching.
199
+ */
200
+ interface NonContextualAdParams extends AdRequestBaseV1 {
201
+ }
202
+ /**
203
+ * POST /api/v1/bid
204
+ * @description Two-phase bid request. Returns bid price and bidId.
205
+ * @note Does NOT extend AdRequestBaseV1 - has its own field set.
206
+ */
207
+ interface BidParams {
208
+ /** Array of conversation messages (required) */
209
+ messages: MessageObject[];
210
+ /** Session identifier */
211
+ sessionId?: string;
212
+ /** Unique user identifier */
213
+ userId?: string;
214
+ /** Chat/conversation identifier */
215
+ chatId?: string;
216
+ /** Device and location information */
217
+ device?: DeviceObject;
218
+ }
219
+ /**
220
+ * POST /api/v1/render
221
+ * @description Two-phase render request using cached bid context.
222
+ */
223
+ interface RenderParams {
224
+ /** Bid identifier from the bid phase (required) */
225
+ bidId: string;
226
+ /** Realized price to charge (required) */
227
+ realizedPrice: number;
228
+ }
229
+ /**
230
+ * Single ad object in v1 responses.
231
+ * @description Contains all ad creative and tracking data.
232
+ */
233
+ interface AdV1 {
234
+ /** The advertisement copy text */
235
+ adText: string;
236
+ /** Unique ad identifier */
237
+ adId: string;
238
+ /** Ad title */
239
+ title?: string;
240
+ /** Brand/advertiser name */
241
+ brandName?: string;
242
+ /** Brand logo image URL */
243
+ brandImage?: string;
244
+ /** Landing page URL */
245
+ url?: string;
246
+ /** Favicon URL */
247
+ favicon?: string;
248
+ /** Impression tracking URL */
249
+ impUrl?: string;
250
+ /** Click-through tracking URL */
251
+ clickUrl?: string;
252
+ /** Payout amount in USD */
253
+ payout?: number;
254
+ }
255
+ /**
256
+ * v1 ad response (multi-ad support).
257
+ * @description Returned by contextual, summary, non-contextual, and render endpoints.
258
+ */
259
+ interface AdResponseV1 {
260
+ /** Array of ad objects */
261
+ ads: AdV1[];
262
+ /** Number of ads returned */
263
+ numAds: number;
264
+ /** Total payout across all ads */
265
+ totalPayout?: number;
266
+ }
267
+ /**
268
+ * v1 bid response.
269
+ * @description Returned by the bid endpoint.
270
+ */
271
+ interface BidResponse {
272
+ /** Clearing price (CPM) */
273
+ bid: number;
274
+ /** Bid identifier for the render phase */
275
+ bidId: string;
276
+ }
156
277
 
157
278
  /**
158
279
  * Configuration options for the Gravity API Client
@@ -303,6 +424,131 @@ declare class Client {
303
424
  * ```
304
425
  */
305
426
  getAd(params: AdParams): Promise<AdResponse | null>;
427
+ /**
428
+ * Request contextual advertisements (v1 API)
429
+ *
430
+ * @description Fetches ads based on conversation context. Requires messages array.
431
+ * Returns null if no relevant ad is available or on error.
432
+ *
433
+ * @param params - Request parameters including messages array
434
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
435
+ *
436
+ * @example
437
+ * ```typescript
438
+ * const response = await client.contextualAd({
439
+ * messages: [
440
+ * { role: 'user', content: 'What laptop should I buy?' }
441
+ * ],
442
+ * sessionId: 'session-123',
443
+ * userId: 'user-456',
444
+ * });
445
+ *
446
+ * if (response) {
447
+ * const ad = response.ads[0];
448
+ * console.log(ad.adText);
449
+ * }
450
+ * ```
451
+ */
452
+ contextualAd(params: ContextualAdParams): Promise<AdResponseV1 | null>;
453
+ /**
454
+ * Request summary-based advertisements (v1 API)
455
+ *
456
+ * @description Fetches ads based on a search/summary query string.
457
+ * Returns null if no relevant ad is available or on error.
458
+ *
459
+ * @param params - Request parameters including queryString
460
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
461
+ *
462
+ * @example
463
+ * ```typescript
464
+ * const response = await client.summaryAd({
465
+ * queryString: 'best laptops for programming 2025',
466
+ * sessionId: 'session-123',
467
+ * });
468
+ *
469
+ * if (response) {
470
+ * const ad = response.ads[0];
471
+ * console.log(ad.adText);
472
+ * }
473
+ * ```
474
+ */
475
+ summaryAd(params: SummaryAdParams): Promise<AdResponseV1 | null>;
476
+ /**
477
+ * Request non-contextual advertisements (v1 API)
478
+ *
479
+ * @description Fetches ads without context matching. Useful for brand awareness placements.
480
+ * Returns null if no ad is available or on error.
481
+ *
482
+ * @param params - Optional request parameters
483
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
484
+ *
485
+ * @example
486
+ * ```typescript
487
+ * const response = await client.nonContextualAd({
488
+ * sessionId: 'session-123',
489
+ * numAds: 2,
490
+ * });
491
+ *
492
+ * if (response) {
493
+ * response.ads.forEach(ad => console.log(ad.adText));
494
+ * }
495
+ * ```
496
+ */
497
+ nonContextualAd(params?: NonContextualAdParams): Promise<AdResponseV1 | null>;
498
+ /**
499
+ * Request a bid price for contextual ad placement (v1 API)
500
+ *
501
+ * @description First phase of two-phase ad flow. Returns bid price and bidId.
502
+ * Use the bidId with render() to generate the actual ad creative.
503
+ * Returns null if no bid is available or on error.
504
+ *
505
+ * @param params - Request parameters including messages array
506
+ * @returns Promise resolving to BidResponse or null if no bid available
507
+ *
508
+ * @example
509
+ * ```typescript
510
+ * const bidResult = await client.bid({
511
+ * messages: [
512
+ * { role: 'user', content: 'I need help with my code' }
513
+ * ],
514
+ * sessionId: 'session-123',
515
+ * });
516
+ *
517
+ * if (bidResult) {
518
+ * console.log(`Bid price: $${bidResult.bid} CPM`);
519
+ * // Decide whether to show ad based on price...
520
+ * const ad = await client.render({
521
+ * bidId: bidResult.bidId,
522
+ * realizedPrice: bidResult.bid,
523
+ * });
524
+ * }
525
+ * ```
526
+ */
527
+ bid(params: BidParams): Promise<BidResponse | null>;
528
+ /**
529
+ * Render an ad from a cached bid (v1 API)
530
+ *
531
+ * @description Second phase of two-phase ad flow. Generates ad creative using cached bid context.
532
+ * Returns null if bid expired (404) or on error. Bid expires after 60 seconds.
533
+ *
534
+ * @param params - Request parameters including bidId and realizedPrice
535
+ * @returns Promise resolving to AdResponseV1 or null if bid expired/error
536
+ *
537
+ * @example
538
+ * ```typescript
539
+ * // After getting a bid...
540
+ * const ad = await client.render({
541
+ * bidId: bidResult.bidId,
542
+ * realizedPrice: bidResult.bid,
543
+ * });
544
+ *
545
+ * if (ad) {
546
+ * const firstAd = ad.ads[0];
547
+ * displayAd(firstAd);
548
+ * }
549
+ * ```
550
+ */
551
+ render(params: RenderParams): Promise<AdResponseV1 | null>;
306
552
  /**
307
553
  * Handle and log API errors
308
554
  *
@@ -317,4 +563,4 @@ declare class Client {
317
563
  private handleError;
318
564
  }
319
565
 
320
- export { type AdParams, type AdResponse, type ApiErrorResponse, Client, type ClientParams };
566
+ export { type AdParams, type AdRequestBaseV1, type AdResponse, type AdResponseV1, type AdV1, type ApiErrorResponse, type BidParams, type BidResponse, Client, type ClientParams, type ContextualAdParams, type DeviceObject, type Gender, type MessageObject, type NonContextualAdParams, type RenderParams, type Role, type SummaryAdParams, type UserObject };
package/dist/index.js CHANGED
@@ -130,8 +130,6 @@ var Client = class {
130
130
  try {
131
131
  const body = {
132
132
  ...params,
133
- // Prefer explicit apiKey in params, else use client's apiKey
134
- apiKey: params.apiKey ?? this.apiKey,
135
133
  // Use request-level excludedTopics, or fall back to client-level
136
134
  excludedTopics: params.excludedTopics ?? this.excludedTopics,
137
135
  // Use request-level relevancy, or fall back to client-level
@@ -155,6 +153,224 @@ var Client = class {
155
153
  return null;
156
154
  }
157
155
  }
156
+ // ===========================================================================
157
+ // v1 API Methods
158
+ // ===========================================================================
159
+ /**
160
+ * Request contextual advertisements (v1 API)
161
+ *
162
+ * @description Fetches ads based on conversation context. Requires messages array.
163
+ * Returns null if no relevant ad is available or on error.
164
+ *
165
+ * @param params - Request parameters including messages array
166
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
167
+ *
168
+ * @example
169
+ * ```typescript
170
+ * const response = await client.contextualAd({
171
+ * messages: [
172
+ * { role: 'user', content: 'What laptop should I buy?' }
173
+ * ],
174
+ * sessionId: 'session-123',
175
+ * userId: 'user-456',
176
+ * });
177
+ *
178
+ * if (response) {
179
+ * const ad = response.ads[0];
180
+ * console.log(ad.adText);
181
+ * }
182
+ * ```
183
+ */
184
+ async contextualAd(params) {
185
+ try {
186
+ const body = {
187
+ ...params,
188
+ excludedTopics: params.excludedTopics ?? this.excludedTopics,
189
+ relevancy: params.relevancy ?? this.relevancy
190
+ };
191
+ const response = await this.axios.post("/api/v1/ad/contextual", body);
192
+ if (response.status === 204) {
193
+ return null;
194
+ }
195
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
196
+ return response.data;
197
+ }
198
+ return null;
199
+ } catch (error) {
200
+ this.handleError(error, "contextualAd");
201
+ return null;
202
+ }
203
+ }
204
+ /**
205
+ * Request summary-based advertisements (v1 API)
206
+ *
207
+ * @description Fetches ads based on a search/summary query string.
208
+ * Returns null if no relevant ad is available or on error.
209
+ *
210
+ * @param params - Request parameters including queryString
211
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
212
+ *
213
+ * @example
214
+ * ```typescript
215
+ * const response = await client.summaryAd({
216
+ * queryString: 'best laptops for programming 2025',
217
+ * sessionId: 'session-123',
218
+ * });
219
+ *
220
+ * if (response) {
221
+ * const ad = response.ads[0];
222
+ * console.log(ad.adText);
223
+ * }
224
+ * ```
225
+ */
226
+ async summaryAd(params) {
227
+ try {
228
+ const body = {
229
+ ...params,
230
+ excludedTopics: params.excludedTopics ?? this.excludedTopics,
231
+ relevancy: params.relevancy ?? this.relevancy
232
+ };
233
+ const response = await this.axios.post("/api/v1/ad/summary", body);
234
+ if (response.status === 204) {
235
+ return null;
236
+ }
237
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
238
+ return response.data;
239
+ }
240
+ return null;
241
+ } catch (error) {
242
+ this.handleError(error, "summaryAd");
243
+ return null;
244
+ }
245
+ }
246
+ /**
247
+ * Request non-contextual advertisements (v1 API)
248
+ *
249
+ * @description Fetches ads without context matching. Useful for brand awareness placements.
250
+ * Returns null if no ad is available or on error.
251
+ *
252
+ * @param params - Optional request parameters
253
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * const response = await client.nonContextualAd({
258
+ * sessionId: 'session-123',
259
+ * numAds: 2,
260
+ * });
261
+ *
262
+ * if (response) {
263
+ * response.ads.forEach(ad => console.log(ad.adText));
264
+ * }
265
+ * ```
266
+ */
267
+ async nonContextualAd(params = {}) {
268
+ try {
269
+ const body = {
270
+ ...params,
271
+ excludedTopics: params.excludedTopics ?? this.excludedTopics
272
+ };
273
+ const response = await this.axios.post("/api/v1/ad/non-contextual", body);
274
+ if (response.status === 204) {
275
+ return null;
276
+ }
277
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
278
+ return response.data;
279
+ }
280
+ return null;
281
+ } catch (error) {
282
+ this.handleError(error, "nonContextualAd");
283
+ return null;
284
+ }
285
+ }
286
+ /**
287
+ * Request a bid price for contextual ad placement (v1 API)
288
+ *
289
+ * @description First phase of two-phase ad flow. Returns bid price and bidId.
290
+ * Use the bidId with render() to generate the actual ad creative.
291
+ * Returns null if no bid is available or on error.
292
+ *
293
+ * @param params - Request parameters including messages array
294
+ * @returns Promise resolving to BidResponse or null if no bid available
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * const bidResult = await client.bid({
299
+ * messages: [
300
+ * { role: 'user', content: 'I need help with my code' }
301
+ * ],
302
+ * sessionId: 'session-123',
303
+ * });
304
+ *
305
+ * if (bidResult) {
306
+ * console.log(`Bid price: $${bidResult.bid} CPM`);
307
+ * // Decide whether to show ad based on price...
308
+ * const ad = await client.render({
309
+ * bidId: bidResult.bidId,
310
+ * realizedPrice: bidResult.bid,
311
+ * });
312
+ * }
313
+ * ```
314
+ */
315
+ async bid(params) {
316
+ try {
317
+ const response = await this.axios.post("/api/v1/bid", params);
318
+ if (response.status === 204) {
319
+ return null;
320
+ }
321
+ if (response.data && response.data.data) {
322
+ return {
323
+ bid: response.data.data.bid,
324
+ bidId: response.data.data.bidId
325
+ };
326
+ }
327
+ return null;
328
+ } catch (error) {
329
+ this.handleError(error, "bid");
330
+ return null;
331
+ }
332
+ }
333
+ /**
334
+ * Render an ad from a cached bid (v1 API)
335
+ *
336
+ * @description Second phase of two-phase ad flow. Generates ad creative using cached bid context.
337
+ * Returns null if bid expired (404) or on error. Bid expires after 60 seconds.
338
+ *
339
+ * @param params - Request parameters including bidId and realizedPrice
340
+ * @returns Promise resolving to AdResponseV1 or null if bid expired/error
341
+ *
342
+ * @example
343
+ * ```typescript
344
+ * // After getting a bid...
345
+ * const ad = await client.render({
346
+ * bidId: bidResult.bidId,
347
+ * realizedPrice: bidResult.bid,
348
+ * });
349
+ *
350
+ * if (ad) {
351
+ * const firstAd = ad.ads[0];
352
+ * displayAd(firstAd);
353
+ * }
354
+ * ```
355
+ */
356
+ async render(params) {
357
+ try {
358
+ const response = await this.axios.post("/api/v1/render", params);
359
+ if (response.status === 204) {
360
+ return null;
361
+ }
362
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
363
+ return response.data;
364
+ }
365
+ return null;
366
+ } catch (error) {
367
+ if (import_axios.default.isAxiosError(error) && error.response?.status === 404) {
368
+ return null;
369
+ }
370
+ this.handleError(error, "render");
371
+ return null;
372
+ }
373
+ }
158
374
  /**
159
375
  * Handle and log API errors
160
376
  *
package/dist/index.mjs CHANGED
@@ -94,8 +94,6 @@ var Client = class {
94
94
  try {
95
95
  const body = {
96
96
  ...params,
97
- // Prefer explicit apiKey in params, else use client's apiKey
98
- apiKey: params.apiKey ?? this.apiKey,
99
97
  // Use request-level excludedTopics, or fall back to client-level
100
98
  excludedTopics: params.excludedTopics ?? this.excludedTopics,
101
99
  // Use request-level relevancy, or fall back to client-level
@@ -119,6 +117,224 @@ var Client = class {
119
117
  return null;
120
118
  }
121
119
  }
120
+ // ===========================================================================
121
+ // v1 API Methods
122
+ // ===========================================================================
123
+ /**
124
+ * Request contextual advertisements (v1 API)
125
+ *
126
+ * @description Fetches ads based on conversation context. Requires messages array.
127
+ * Returns null if no relevant ad is available or on error.
128
+ *
129
+ * @param params - Request parameters including messages array
130
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * const response = await client.contextualAd({
135
+ * messages: [
136
+ * { role: 'user', content: 'What laptop should I buy?' }
137
+ * ],
138
+ * sessionId: 'session-123',
139
+ * userId: 'user-456',
140
+ * });
141
+ *
142
+ * if (response) {
143
+ * const ad = response.ads[0];
144
+ * console.log(ad.adText);
145
+ * }
146
+ * ```
147
+ */
148
+ async contextualAd(params) {
149
+ try {
150
+ const body = {
151
+ ...params,
152
+ excludedTopics: params.excludedTopics ?? this.excludedTopics,
153
+ relevancy: params.relevancy ?? this.relevancy
154
+ };
155
+ const response = await this.axios.post("/api/v1/ad/contextual", body);
156
+ if (response.status === 204) {
157
+ return null;
158
+ }
159
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
160
+ return response.data;
161
+ }
162
+ return null;
163
+ } catch (error) {
164
+ this.handleError(error, "contextualAd");
165
+ return null;
166
+ }
167
+ }
168
+ /**
169
+ * Request summary-based advertisements (v1 API)
170
+ *
171
+ * @description Fetches ads based on a search/summary query string.
172
+ * Returns null if no relevant ad is available or on error.
173
+ *
174
+ * @param params - Request parameters including queryString
175
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const response = await client.summaryAd({
180
+ * queryString: 'best laptops for programming 2025',
181
+ * sessionId: 'session-123',
182
+ * });
183
+ *
184
+ * if (response) {
185
+ * const ad = response.ads[0];
186
+ * console.log(ad.adText);
187
+ * }
188
+ * ```
189
+ */
190
+ async summaryAd(params) {
191
+ try {
192
+ const body = {
193
+ ...params,
194
+ excludedTopics: params.excludedTopics ?? this.excludedTopics,
195
+ relevancy: params.relevancy ?? this.relevancy
196
+ };
197
+ const response = await this.axios.post("/api/v1/ad/summary", body);
198
+ if (response.status === 204) {
199
+ return null;
200
+ }
201
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
202
+ return response.data;
203
+ }
204
+ return null;
205
+ } catch (error) {
206
+ this.handleError(error, "summaryAd");
207
+ return null;
208
+ }
209
+ }
210
+ /**
211
+ * Request non-contextual advertisements (v1 API)
212
+ *
213
+ * @description Fetches ads without context matching. Useful for brand awareness placements.
214
+ * Returns null if no ad is available or on error.
215
+ *
216
+ * @param params - Optional request parameters
217
+ * @returns Promise resolving to AdResponseV1 or null if no ad available
218
+ *
219
+ * @example
220
+ * ```typescript
221
+ * const response = await client.nonContextualAd({
222
+ * sessionId: 'session-123',
223
+ * numAds: 2,
224
+ * });
225
+ *
226
+ * if (response) {
227
+ * response.ads.forEach(ad => console.log(ad.adText));
228
+ * }
229
+ * ```
230
+ */
231
+ async nonContextualAd(params = {}) {
232
+ try {
233
+ const body = {
234
+ ...params,
235
+ excludedTopics: params.excludedTopics ?? this.excludedTopics
236
+ };
237
+ const response = await this.axios.post("/api/v1/ad/non-contextual", body);
238
+ if (response.status === 204) {
239
+ return null;
240
+ }
241
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
242
+ return response.data;
243
+ }
244
+ return null;
245
+ } catch (error) {
246
+ this.handleError(error, "nonContextualAd");
247
+ return null;
248
+ }
249
+ }
250
+ /**
251
+ * Request a bid price for contextual ad placement (v1 API)
252
+ *
253
+ * @description First phase of two-phase ad flow. Returns bid price and bidId.
254
+ * Use the bidId with render() to generate the actual ad creative.
255
+ * Returns null if no bid is available or on error.
256
+ *
257
+ * @param params - Request parameters including messages array
258
+ * @returns Promise resolving to BidResponse or null if no bid available
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * const bidResult = await client.bid({
263
+ * messages: [
264
+ * { role: 'user', content: 'I need help with my code' }
265
+ * ],
266
+ * sessionId: 'session-123',
267
+ * });
268
+ *
269
+ * if (bidResult) {
270
+ * console.log(`Bid price: $${bidResult.bid} CPM`);
271
+ * // Decide whether to show ad based on price...
272
+ * const ad = await client.render({
273
+ * bidId: bidResult.bidId,
274
+ * realizedPrice: bidResult.bid,
275
+ * });
276
+ * }
277
+ * ```
278
+ */
279
+ async bid(params) {
280
+ try {
281
+ const response = await this.axios.post("/api/v1/bid", params);
282
+ if (response.status === 204) {
283
+ return null;
284
+ }
285
+ if (response.data && response.data.data) {
286
+ return {
287
+ bid: response.data.data.bid,
288
+ bidId: response.data.data.bidId
289
+ };
290
+ }
291
+ return null;
292
+ } catch (error) {
293
+ this.handleError(error, "bid");
294
+ return null;
295
+ }
296
+ }
297
+ /**
298
+ * Render an ad from a cached bid (v1 API)
299
+ *
300
+ * @description Second phase of two-phase ad flow. Generates ad creative using cached bid context.
301
+ * Returns null if bid expired (404) or on error. Bid expires after 60 seconds.
302
+ *
303
+ * @param params - Request parameters including bidId and realizedPrice
304
+ * @returns Promise resolving to AdResponseV1 or null if bid expired/error
305
+ *
306
+ * @example
307
+ * ```typescript
308
+ * // After getting a bid...
309
+ * const ad = await client.render({
310
+ * bidId: bidResult.bidId,
311
+ * realizedPrice: bidResult.bid,
312
+ * });
313
+ *
314
+ * if (ad) {
315
+ * const firstAd = ad.ads[0];
316
+ * displayAd(firstAd);
317
+ * }
318
+ * ```
319
+ */
320
+ async render(params) {
321
+ try {
322
+ const response = await this.axios.post("/api/v1/render", params);
323
+ if (response.status === 204) {
324
+ return null;
325
+ }
326
+ if (response.data && response.data.ads && response.data.ads.length > 0) {
327
+ return response.data;
328
+ }
329
+ return null;
330
+ } catch (error) {
331
+ if (axios.isAxiosError(error) && error.response?.status === 404) {
332
+ return null;
333
+ }
334
+ this.handleError(error, "render");
335
+ return null;
336
+ }
337
+ }
122
338
  /**
123
339
  * Handle and log API errors
124
340
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ai/api",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "description": "Gravity JS SDK for retrieving targeted advertisements",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",