@gravity-ai/api 0.1.0 → 0.1.1

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
@@ -1,6 +1,6 @@
1
1
  # @gravity-ai/api
2
2
 
3
- The official Node.js/TypeScript SDK for the Gravity API.
3
+ The official Node.js/TypeScript SDK for the Gravity AI advertising API. Fetch contextually relevant ads based on conversation content.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,61 +8,240 @@ The official Node.js/TypeScript SDK for the Gravity API.
8
8
  npm install @gravity-ai/api
9
9
  ```
10
10
 
11
- ## Usage
11
+ > **Note:** Requires Node.js 18+
12
12
 
13
- First, import and initialize the client with your API key.
13
+ ## Quick Start
14
14
 
15
15
  ```typescript
16
16
  import { Client } from '@gravity-ai/api';
17
17
 
18
- const client = new Client('YOUR_API_KEY');
18
+ const client = new Client('your-api-key');
19
+
20
+ const ad = await client.getAd({
21
+ messages: [
22
+ { role: 'user', content: 'What are some good hiking trails?' },
23
+ { role: 'assistant', content: 'Here are some popular trails...' }
24
+ ]
25
+ });
26
+
27
+ if (ad) {
28
+ console.log(ad.adText);
29
+ }
19
30
  ```
20
31
 
21
- ### Fetching an Ad
32
+ ## Client Configuration
22
33
 
23
- To request an ad, you need to pass the conversation context (messages). You can also provide optional user or device information to improve targeting.
34
+ ### Basic Initialization
35
+
36
+ ```typescript
37
+ import { Client } from '@gravity-ai/api';
38
+
39
+ const client = new Client('your-api-key');
40
+ ```
41
+
42
+ ### Advanced Configuration
43
+
44
+ ```typescript
45
+ import { Client } from '@gravity-ai/api';
46
+
47
+ const client = new Client('your-api-key', {
48
+ // Topics to exclude globally (optional)
49
+ excludedTopics: ['politics', 'religion'],
50
+
51
+ // Minimum relevancy threshold 0-1 (optional)
52
+ relevancy: 0.8,
53
+ });
54
+ ```
55
+
56
+ #### Configuration Options
57
+
58
+ | Option | Type | Default | Description |
59
+ |--------|------|---------|-------------|
60
+ | `endpoint` | `string` | `'https://server.trygravity.ai'` | API endpoint URL |
61
+ | `excludedTopics` | `string[]` | `[]` | Topics to exclude from ad matching |
62
+ | `relevancy` | `number \| null` | `null` | Minimum relevancy score (0-1) |
63
+
64
+ ## Fetching Ads
65
+
66
+ ### Basic Request
67
+
68
+ ```typescript
69
+ const ad = await client.getAd({
70
+ messages: [
71
+ { role: 'user', content: 'I need help finding a new laptop.' },
72
+ { role: 'assistant', content: 'What is your budget?' }
73
+ ]
74
+ });
75
+ ```
76
+
77
+ ### Full Request with All Options
24
78
 
25
79
  ```typescript
26
80
  const ad = await client.getAd({
81
+ // Required: conversation messages
27
82
  messages: [
28
83
  { role: 'user', content: 'I need help finding a new laptop.' },
29
84
  { role: 'assistant', content: 'What is your budget?' }
30
85
  ],
31
- // User context
86
+
87
+ // Optional: user information for targeting
32
88
  user: {
33
- gender: 'male',
34
- age: '25-34'
89
+ uid: 'user-123', // Unique user identifier
90
+ gender: 'male', // 'male' | 'female' | 'other'
91
+ age: '25-34', // Age range string
92
+ keywords: 'tech,gadgets', // User interest keywords
35
93
  },
36
- // Device info
37
- device: {
38
- ip: '1.2.3.4',
39
- country: 'US',
40
- ua: 'UA'
94
+
95
+ // Optional: device information
96
+ device: {
97
+ ip: '1.2.3.4', // User IP address
98
+ country: 'US', // ISO country code
99
+ ua: 'Mozilla/5.0...', // User agent string
100
+ os: 'macOS', // Operating system
101
+ ifa: 'device-ad-id', // Advertising identifier
41
102
  },
42
- // Optional additional context
43
- interests: ["coding", "apple", "software development"],
44
- summary: "User is building software on his windows laptop but wants an apple laptop"
103
+
104
+ // Optional: additional targeting context
105
+ excludedTopics: ['politics'], // Override client-level exclusions
106
+ relevancy: 0.8, // Override client-level relevancy
107
+
108
+ // Optional: custom fields (open-ended)
109
+ interests: ['coding', 'apple', 'software development'],
110
+ summary: 'User wants a laptop for software development',
45
111
  });
112
+ ```
113
+
114
+ ### Request Parameters
115
+
116
+ | Parameter | Type | Required | Description |
117
+ |-----------|------|----------|-------------|
118
+ | `messages` | `MessageObject[]` | ✅ | Conversation history |
119
+ | `user` | `UserObject` | - | User targeting info |
120
+ | `device` | `DeviceObject` | - | Device/location info |
121
+ | `excludedTopics` | `string[]` | - | Topics to exclude |
122
+ | `relevancy` | `number` | - | Min relevancy (0-1) |
123
+ | `apiKey` | `string` | - | Override client API key |
124
+ | `[key: string]` | `any` | - | Custom fields allowed |
125
+
126
+ ### Message Object
127
+
128
+ ```typescript
129
+ interface MessageObject {
130
+ role: 'user' | 'assistant';
131
+ content: string;
132
+ }
133
+ ```
134
+
135
+ ### User Object
136
+
137
+ ```typescript
138
+ interface UserObject {
139
+ uid?: string; // Unique user ID
140
+ gender?: 'male' | 'female' | 'other'; // User gender
141
+ age?: string; // Age range (e.g., '25-34')
142
+ keywords?: string; // Interest keywords
143
+ }
144
+ ```
145
+
146
+ ### Device Object
147
+
148
+ ```typescript
149
+ interface DeviceObject {
150
+ ip: string; // IP address
151
+ country: string; // ISO country code
152
+ ua: string; // User agent
153
+ os?: string; // Operating system
154
+ ifa?: string; // Advertising ID
155
+ }
156
+ ```
157
+
158
+ ## Ad Response
159
+
160
+ The `getAd` method returns an `AdResponse` object or `null` if no relevant ad is found.
161
+
162
+ ```typescript
163
+ interface AdResponse {
164
+ adText: string; // The ad copy to display
165
+ impUrl?: string; // Impression tracking URL (fire on view)
166
+ clickUrl?: string; // Click-through URL
167
+ payout?: number; // Payout amount
168
+ }
169
+ ```
170
+
171
+ ### Handling the Response
172
+
173
+ ```typescript
174
+ const ad = await client.getAd({ messages });
46
175
 
47
176
  if (ad) {
48
- console.log('Ad Text:', ad.adText);
49
- console.log('Impression URL:', ad.impUrl);
50
- console.log("Click URL:", ad.clickUrl);
51
- console.log("Payout", ad.payout)
177
+ // Display the ad
178
+ console.log('Ad:', ad.adText);
179
+
180
+ // Track impression (fire pixel)
181
+ 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
188
+ }
52
189
  } else {
53
- console.log('No ad available for this context.');
190
+ // No relevant ad found - show fallback or nothing
191
+ console.log('No ad available');
54
192
  }
55
193
  ```
56
194
 
57
- ### Advanced Configuration
195
+ ## Error Handling
58
196
 
59
- You can override the default API endpoint or provide global excluded topics during initialization.
197
+ The client handles errors gracefully and returns `null` on failure. Errors are logged to the console.
60
198
 
61
199
  ```typescript
62
- const client = new Client('YOUR_API_KEY', {
63
- endpoint: 'https://custom.gravity.server',
64
- excludedTopics: ['politics', 'religion']
65
- });
200
+ const ad = await client.getAd({ messages });
201
+
202
+ // Returns null on:
203
+ // - Network errors
204
+ // - API errors (4xx, 5xx)
205
+ // - No relevant ad (204)
206
+ // - Invalid response data
207
+
208
+ if (!ad) {
209
+ // Handle gracefully - don't break the user experience
210
+ }
211
+ ```
212
+
213
+ ## TypeScript
214
+
215
+ Full TypeScript support with exported types:
216
+
217
+ ```typescript
218
+ import { Client, ClientParams } from '@gravity-ai/api';
219
+ import type { AdParams, AdResponse, MessageObject, DeviceObject, UserObject } from '@gravity-ai/api';
220
+ ```
221
+
222
+ ## Using with React
223
+
224
+ For React applications, consider using the companion package `@gravity-ai/react` which provides ready-to-use components with automatic tracking:
225
+
226
+ ```bash
227
+ npm install @gravity-ai/api @gravity-ai/react
228
+ ```
229
+
230
+ ```tsx
231
+ import { Client } from '@gravity-ai/api';
232
+ import { AdBanner } from '@gravity-ai/react';
233
+
234
+ const client = new Client('your-api-key');
235
+
236
+ function ChatApp() {
237
+ const [ad, setAd] = useState(null);
238
+
239
+ useEffect(() => {
240
+ client.getAd({ messages }).then(setAd);
241
+ }, [messages]);
242
+
243
+ return <AdBanner ad={ad} theme="dark" />;
244
+ }
66
245
  ```
67
246
 
68
247
  ## License
package/dist/index.d.mts CHANGED
@@ -1,71 +1,318 @@
1
+ /**
2
+ * Role type for conversation messages
3
+ * @description Indicates whether a message is from the user or the AI assistant
4
+ */
1
5
  type Role = 'user' | 'assistant';
6
+ /**
7
+ * Gender type for user targeting
8
+ * @description Used for demographic targeting of advertisements
9
+ */
2
10
  type Gender = 'male' | 'female' | 'other';
11
+ /**
12
+ * Represents a single message in a conversation
13
+ * @description Used to provide conversation context for contextual ad targeting
14
+ * @example
15
+ * ```typescript
16
+ * const message: MessageObject = {
17
+ * role: 'user',
18
+ * content: 'I need help finding a new laptop.'
19
+ * };
20
+ * ```
21
+ */
3
22
  interface MessageObject {
23
+ /** The role of the message sender - either 'user' or 'assistant' */
4
24
  role: Role;
25
+ /** The text content of the message */
5
26
  content: string;
6
27
  }
28
+ /**
29
+ * Device and location information for ad targeting
30
+ * @description Provides device-level context for better ad relevance and compliance
31
+ * @example
32
+ * ```typescript
33
+ * const device: DeviceObject = {
34
+ * ip: '192.168.1.1',
35
+ * country: 'US',
36
+ * ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...',
37
+ * os: 'macOS'
38
+ * };
39
+ * ```
40
+ */
7
41
  interface DeviceObject {
42
+ /** User's IP address for geo-targeting */
8
43
  ip: string;
44
+ /** ISO 3166-1 alpha-2 country code (e.g., 'US', 'GB', 'DE') */
9
45
  country: string;
46
+ /** User agent string from the browser */
10
47
  ua: string;
48
+ /** Operating system name (e.g., 'macOS', 'Windows', 'iOS', 'Android') */
11
49
  os?: string;
50
+ /** Identifier for Advertisers (mobile advertising ID) */
12
51
  ifa?: string;
13
52
  }
53
+ /**
54
+ * User profile information for ad targeting
55
+ * @description Demographic and interest data for personalized ad delivery
56
+ * @example
57
+ * ```typescript
58
+ * const user: UserObject = {
59
+ * uid: 'user-123',
60
+ * gender: 'male',
61
+ * age: '25-34',
62
+ * keywords: 'technology,programming,gaming'
63
+ * };
64
+ * ```
65
+ */
14
66
  interface UserObject {
67
+ /** Unique user identifier for frequency capping and tracking */
15
68
  uid?: string;
69
+ /** User's gender for demographic targeting */
16
70
  gender?: Gender;
71
+ /** Age range string (e.g., '18-24', '25-34', '35-44', '45-54', '55-64', '65+') */
17
72
  age?: string;
73
+ /** Comma-separated keywords representing user interests */
18
74
  keywords?: string;
19
75
  }
76
+ /**
77
+ * Parameters for requesting an advertisement
78
+ * @description The complete request payload for the getAd() method
79
+ * @example
80
+ * ```typescript
81
+ * const params: AdParams = {
82
+ * messages: [
83
+ * { role: 'user', content: 'What laptop should I buy?' },
84
+ * { role: 'assistant', content: 'What is your budget?' }
85
+ * ],
86
+ * user: { gender: 'male', age: '25-34' },
87
+ * device: { ip: '1.2.3.4', country: 'US', ua: 'Mozilla/5.0...' },
88
+ * excludedTopics: ['politics'],
89
+ * relevancy: 0.5
90
+ * };
91
+ * ```
92
+ */
20
93
  interface AdParams {
94
+ /** Override the client's API key for this request */
21
95
  apiKey?: string;
96
+ /** Array of conversation messages for contextual targeting (required) */
22
97
  messages: MessageObject[];
98
+ /** Device and location information */
23
99
  device?: DeviceObject;
100
+ /** User demographic and interest data */
24
101
  user?: UserObject;
102
+ /** Topics to exclude from ad matching (e.g., ['politics', 'religion']) */
25
103
  excludedTopics?: string[];
104
+ /** Minimum relevancy score threshold (0-1). Higher = more relevant but fewer ads */
26
105
  relevancy?: number | null;
27
- [key: string]: any;
106
+ /**
107
+ * Additional custom fields for publisher-specific targeting
108
+ * @description Any additional key-value pairs will be passed to the API
109
+ */
110
+ [key: string]: unknown;
28
111
  }
112
+ /**
113
+ * Response from the Gravity API containing ad data
114
+ * @description Returned by getAd() when a relevant advertisement is found
115
+ * @example
116
+ * ```typescript
117
+ * const ad: AdResponse = {
118
+ * adText: 'Check out our amazing laptops!',
119
+ * impUrl: 'https://tracking.example.com/imp?id=123',
120
+ * clickUrl: 'https://example.com/laptops',
121
+ * payout: 0.50
122
+ * };
123
+ * ```
124
+ */
29
125
  interface AdResponse {
126
+ /** The advertisement copy text to display to the user */
30
127
  adText: string;
128
+ /**
129
+ * Impression tracking URL - fire this when the ad is viewed
130
+ * @description Should be loaded (e.g., via image beacon) when ad becomes visible
131
+ */
31
132
  impUrl?: string;
133
+ /**
134
+ * Click-through URL - navigate user here when ad is clicked
135
+ * @description The destination page when the user clicks the ad
136
+ */
32
137
  clickUrl?: string;
138
+ /**
139
+ * Payout amount in USD for this ad impression
140
+ * @description The revenue earned for displaying this ad
141
+ */
33
142
  payout?: number;
34
143
  }
35
144
  /**
36
- * API error response structure
145
+ * Error response structure from the Gravity API
146
+ * @description Returned when the API encounters an error processing the request
37
147
  */
38
148
  interface ApiErrorResponse {
149
+ /** Error code or type identifier */
39
150
  error: string;
151
+ /** Human-readable error description */
40
152
  message?: string;
153
+ /** HTTP status code */
41
154
  statusCode?: number;
42
155
  }
43
156
 
157
+ /**
158
+ * Configuration options for the Gravity API Client
159
+ * @description Pass these options when creating a new Client instance
160
+ * @example
161
+ * ```typescript
162
+ * const params: ClientParams = {
163
+ * endpoint: 'https://custom.gravity.server',
164
+ * excludedTopics: ['politics', 'religion'],
165
+ * relevancy: 0.5
166
+ * };
167
+ * ```
168
+ */
44
169
  interface ClientParams {
170
+ /**
171
+ * Custom API endpoint URL
172
+ * @default 'https://server.trygravity.ai'
173
+ */
45
174
  endpoint?: string;
175
+ /**
176
+ * Topics to exclude from all ad requests
177
+ * @description These exclusions apply to all getAd() calls unless overridden
178
+ * @example ['politics', 'religion', 'adult']
179
+ */
46
180
  excludedTopics?: string[];
181
+ /**
182
+ * Default minimum relevancy threshold (0-1)
183
+ * @description Higher values return more relevant ads but may reduce fill rate
184
+ * @default null (no threshold)
185
+ */
47
186
  relevancy?: number | null;
48
187
  }
49
188
  /**
50
- * Client for the Gravity API
189
+ * Gravity API Client
190
+ *
191
+ * @description The main client for interacting with the Gravity AI advertising API.
192
+ * Use this client to fetch contextually relevant advertisements based on conversation content.
193
+ *
194
+ * @example Basic usage
195
+ * ```typescript
196
+ * import { Client } from '@gravity-ai/api';
197
+ *
198
+ * const client = new Client('your-api-key');
199
+ *
200
+ * const ad = await client.getAd({
201
+ * messages: [
202
+ * { role: 'user', content: 'What laptop should I buy?' }
203
+ * ]
204
+ * });
205
+ *
206
+ * if (ad) {
207
+ * console.log(ad.adText);
208
+ * }
209
+ * ```
210
+ *
211
+ * @example With configuration options
212
+ * ```typescript
213
+ * const client = new Client('your-api-key', {
214
+ * endpoint: 'https://custom.server.com',
215
+ * excludedTopics: ['politics'],
216
+ * relevancy: 0.7
217
+ * });
218
+ * ```
51
219
  */
52
220
  declare class Client {
221
+ /** The API key used for authentication */
53
222
  private apiKey;
54
- private endpoint?;
55
- private excludedTopics?;
56
- private relevancy?;
223
+ /** The API endpoint URL */
224
+ private endpoint;
225
+ /** Topics to exclude from ad matching */
226
+ private excludedTopics;
227
+ /** Minimum relevancy threshold */
228
+ private relevancy;
229
+ /** Axios HTTP client instance */
57
230
  private axios;
231
+ /**
232
+ * Create a new Gravity API client
233
+ *
234
+ * @param apiKey - Your Gravity API key (required)
235
+ * @param params - Optional configuration parameters
236
+ *
237
+ * @throws Will not throw - invalid API key errors occur on first request
238
+ *
239
+ * @example
240
+ * ```typescript
241
+ * // Basic initialization
242
+ * const client = new Client('your-api-key');
243
+ *
244
+ * // With custom options
245
+ * const client = new Client('your-api-key', {
246
+ * excludedTopics: ['gambling', 'alcohol'],
247
+ * relevancy: 0.6
248
+ * });
249
+ * ```
250
+ */
58
251
  constructor(apiKey: string, params?: ClientParams);
59
252
  /**
60
- * Request a text advertisement. Returns null if there is no relevant ad found.
61
- * @param params - AdParams matching the server schema
62
- * @returns Promise<BidResponse | null>
253
+ * Request a contextually relevant advertisement
254
+ *
255
+ * @description Fetches an ad based on the provided conversation context and targeting parameters.
256
+ * Returns `null` if no relevant ad is available or if an error occurs.
257
+ *
258
+ * @param params - Ad request parameters including conversation messages
259
+ * @returns Promise resolving to AdResponse or null if no ad available
260
+ *
261
+ * @example Basic request
262
+ * ```typescript
263
+ * const ad = await client.getAd({
264
+ * messages: [
265
+ * { role: 'user', content: 'I need a new laptop for programming' },
266
+ * { role: 'assistant', content: 'What is your budget range?' }
267
+ * ]
268
+ * });
269
+ * ```
270
+ *
271
+ * @example Full request with targeting
272
+ * ```typescript
273
+ * const ad = await client.getAd({
274
+ * messages: [...],
275
+ * user: {
276
+ * uid: 'user-123',
277
+ * gender: 'male',
278
+ * age: '25-34'
279
+ * },
280
+ * device: {
281
+ * ip: '192.168.1.1',
282
+ * country: 'US',
283
+ * ua: navigator.userAgent
284
+ * },
285
+ * excludedTopics: ['gambling'],
286
+ * relevancy: 0.8
287
+ * });
288
+ * ```
289
+ *
290
+ * @example Handling the response
291
+ * ```typescript
292
+ * const ad = await client.getAd({ messages });
293
+ *
294
+ * if (ad) {
295
+ * // Display the ad
296
+ * showAd(ad.adText);
297
+ *
298
+ * // Track impression
299
+ * if (ad.impUrl) {
300
+ * new Image().src = ad.impUrl;
301
+ * }
302
+ * }
303
+ * ```
63
304
  */
64
305
  getAd(params: AdParams): Promise<AdResponse | null>;
65
306
  /**
66
- * Handle API errors with logging
67
- * @param error - The error object
68
- * @param method - The method name where error occurred
307
+ * Handle and log API errors
308
+ *
309
+ * @description Processes errors from API calls and logs appropriate messages.
310
+ * Distinguishes between network errors, server errors, and unexpected errors.
311
+ *
312
+ * @param error - The error object from the failed request
313
+ * @param method - The name of the method where the error occurred
314
+ *
315
+ * @internal This method is for internal use only
69
316
  */
70
317
  private handleError;
71
318
  }
package/dist/index.d.ts CHANGED
@@ -1,71 +1,318 @@
1
+ /**
2
+ * Role type for conversation messages
3
+ * @description Indicates whether a message is from the user or the AI assistant
4
+ */
1
5
  type Role = 'user' | 'assistant';
6
+ /**
7
+ * Gender type for user targeting
8
+ * @description Used for demographic targeting of advertisements
9
+ */
2
10
  type Gender = 'male' | 'female' | 'other';
11
+ /**
12
+ * Represents a single message in a conversation
13
+ * @description Used to provide conversation context for contextual ad targeting
14
+ * @example
15
+ * ```typescript
16
+ * const message: MessageObject = {
17
+ * role: 'user',
18
+ * content: 'I need help finding a new laptop.'
19
+ * };
20
+ * ```
21
+ */
3
22
  interface MessageObject {
23
+ /** The role of the message sender - either 'user' or 'assistant' */
4
24
  role: Role;
25
+ /** The text content of the message */
5
26
  content: string;
6
27
  }
28
+ /**
29
+ * Device and location information for ad targeting
30
+ * @description Provides device-level context for better ad relevance and compliance
31
+ * @example
32
+ * ```typescript
33
+ * const device: DeviceObject = {
34
+ * ip: '192.168.1.1',
35
+ * country: 'US',
36
+ * ua: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...',
37
+ * os: 'macOS'
38
+ * };
39
+ * ```
40
+ */
7
41
  interface DeviceObject {
42
+ /** User's IP address for geo-targeting */
8
43
  ip: string;
44
+ /** ISO 3166-1 alpha-2 country code (e.g., 'US', 'GB', 'DE') */
9
45
  country: string;
46
+ /** User agent string from the browser */
10
47
  ua: string;
48
+ /** Operating system name (e.g., 'macOS', 'Windows', 'iOS', 'Android') */
11
49
  os?: string;
50
+ /** Identifier for Advertisers (mobile advertising ID) */
12
51
  ifa?: string;
13
52
  }
53
+ /**
54
+ * User profile information for ad targeting
55
+ * @description Demographic and interest data for personalized ad delivery
56
+ * @example
57
+ * ```typescript
58
+ * const user: UserObject = {
59
+ * uid: 'user-123',
60
+ * gender: 'male',
61
+ * age: '25-34',
62
+ * keywords: 'technology,programming,gaming'
63
+ * };
64
+ * ```
65
+ */
14
66
  interface UserObject {
67
+ /** Unique user identifier for frequency capping and tracking */
15
68
  uid?: string;
69
+ /** User's gender for demographic targeting */
16
70
  gender?: Gender;
71
+ /** Age range string (e.g., '18-24', '25-34', '35-44', '45-54', '55-64', '65+') */
17
72
  age?: string;
73
+ /** Comma-separated keywords representing user interests */
18
74
  keywords?: string;
19
75
  }
76
+ /**
77
+ * Parameters for requesting an advertisement
78
+ * @description The complete request payload for the getAd() method
79
+ * @example
80
+ * ```typescript
81
+ * const params: AdParams = {
82
+ * messages: [
83
+ * { role: 'user', content: 'What laptop should I buy?' },
84
+ * { role: 'assistant', content: 'What is your budget?' }
85
+ * ],
86
+ * user: { gender: 'male', age: '25-34' },
87
+ * device: { ip: '1.2.3.4', country: 'US', ua: 'Mozilla/5.0...' },
88
+ * excludedTopics: ['politics'],
89
+ * relevancy: 0.5
90
+ * };
91
+ * ```
92
+ */
20
93
  interface AdParams {
94
+ /** Override the client's API key for this request */
21
95
  apiKey?: string;
96
+ /** Array of conversation messages for contextual targeting (required) */
22
97
  messages: MessageObject[];
98
+ /** Device and location information */
23
99
  device?: DeviceObject;
100
+ /** User demographic and interest data */
24
101
  user?: UserObject;
102
+ /** Topics to exclude from ad matching (e.g., ['politics', 'religion']) */
25
103
  excludedTopics?: string[];
104
+ /** Minimum relevancy score threshold (0-1). Higher = more relevant but fewer ads */
26
105
  relevancy?: number | null;
27
- [key: string]: any;
106
+ /**
107
+ * Additional custom fields for publisher-specific targeting
108
+ * @description Any additional key-value pairs will be passed to the API
109
+ */
110
+ [key: string]: unknown;
28
111
  }
112
+ /**
113
+ * Response from the Gravity API containing ad data
114
+ * @description Returned by getAd() when a relevant advertisement is found
115
+ * @example
116
+ * ```typescript
117
+ * const ad: AdResponse = {
118
+ * adText: 'Check out our amazing laptops!',
119
+ * impUrl: 'https://tracking.example.com/imp?id=123',
120
+ * clickUrl: 'https://example.com/laptops',
121
+ * payout: 0.50
122
+ * };
123
+ * ```
124
+ */
29
125
  interface AdResponse {
126
+ /** The advertisement copy text to display to the user */
30
127
  adText: string;
128
+ /**
129
+ * Impression tracking URL - fire this when the ad is viewed
130
+ * @description Should be loaded (e.g., via image beacon) when ad becomes visible
131
+ */
31
132
  impUrl?: string;
133
+ /**
134
+ * Click-through URL - navigate user here when ad is clicked
135
+ * @description The destination page when the user clicks the ad
136
+ */
32
137
  clickUrl?: string;
138
+ /**
139
+ * Payout amount in USD for this ad impression
140
+ * @description The revenue earned for displaying this ad
141
+ */
33
142
  payout?: number;
34
143
  }
35
144
  /**
36
- * API error response structure
145
+ * Error response structure from the Gravity API
146
+ * @description Returned when the API encounters an error processing the request
37
147
  */
38
148
  interface ApiErrorResponse {
149
+ /** Error code or type identifier */
39
150
  error: string;
151
+ /** Human-readable error description */
40
152
  message?: string;
153
+ /** HTTP status code */
41
154
  statusCode?: number;
42
155
  }
43
156
 
157
+ /**
158
+ * Configuration options for the Gravity API Client
159
+ * @description Pass these options when creating a new Client instance
160
+ * @example
161
+ * ```typescript
162
+ * const params: ClientParams = {
163
+ * endpoint: 'https://custom.gravity.server',
164
+ * excludedTopics: ['politics', 'religion'],
165
+ * relevancy: 0.5
166
+ * };
167
+ * ```
168
+ */
44
169
  interface ClientParams {
170
+ /**
171
+ * Custom API endpoint URL
172
+ * @default 'https://server.trygravity.ai'
173
+ */
45
174
  endpoint?: string;
175
+ /**
176
+ * Topics to exclude from all ad requests
177
+ * @description These exclusions apply to all getAd() calls unless overridden
178
+ * @example ['politics', 'religion', 'adult']
179
+ */
46
180
  excludedTopics?: string[];
181
+ /**
182
+ * Default minimum relevancy threshold (0-1)
183
+ * @description Higher values return more relevant ads but may reduce fill rate
184
+ * @default null (no threshold)
185
+ */
47
186
  relevancy?: number | null;
48
187
  }
49
188
  /**
50
- * Client for the Gravity API
189
+ * Gravity API Client
190
+ *
191
+ * @description The main client for interacting with the Gravity AI advertising API.
192
+ * Use this client to fetch contextually relevant advertisements based on conversation content.
193
+ *
194
+ * @example Basic usage
195
+ * ```typescript
196
+ * import { Client } from '@gravity-ai/api';
197
+ *
198
+ * const client = new Client('your-api-key');
199
+ *
200
+ * const ad = await client.getAd({
201
+ * messages: [
202
+ * { role: 'user', content: 'What laptop should I buy?' }
203
+ * ]
204
+ * });
205
+ *
206
+ * if (ad) {
207
+ * console.log(ad.adText);
208
+ * }
209
+ * ```
210
+ *
211
+ * @example With configuration options
212
+ * ```typescript
213
+ * const client = new Client('your-api-key', {
214
+ * endpoint: 'https://custom.server.com',
215
+ * excludedTopics: ['politics'],
216
+ * relevancy: 0.7
217
+ * });
218
+ * ```
51
219
  */
52
220
  declare class Client {
221
+ /** The API key used for authentication */
53
222
  private apiKey;
54
- private endpoint?;
55
- private excludedTopics?;
56
- private relevancy?;
223
+ /** The API endpoint URL */
224
+ private endpoint;
225
+ /** Topics to exclude from ad matching */
226
+ private excludedTopics;
227
+ /** Minimum relevancy threshold */
228
+ private relevancy;
229
+ /** Axios HTTP client instance */
57
230
  private axios;
231
+ /**
232
+ * Create a new Gravity API client
233
+ *
234
+ * @param apiKey - Your Gravity API key (required)
235
+ * @param params - Optional configuration parameters
236
+ *
237
+ * @throws Will not throw - invalid API key errors occur on first request
238
+ *
239
+ * @example
240
+ * ```typescript
241
+ * // Basic initialization
242
+ * const client = new Client('your-api-key');
243
+ *
244
+ * // With custom options
245
+ * const client = new Client('your-api-key', {
246
+ * excludedTopics: ['gambling', 'alcohol'],
247
+ * relevancy: 0.6
248
+ * });
249
+ * ```
250
+ */
58
251
  constructor(apiKey: string, params?: ClientParams);
59
252
  /**
60
- * Request a text advertisement. Returns null if there is no relevant ad found.
61
- * @param params - AdParams matching the server schema
62
- * @returns Promise<BidResponse | null>
253
+ * Request a contextually relevant advertisement
254
+ *
255
+ * @description Fetches an ad based on the provided conversation context and targeting parameters.
256
+ * Returns `null` if no relevant ad is available or if an error occurs.
257
+ *
258
+ * @param params - Ad request parameters including conversation messages
259
+ * @returns Promise resolving to AdResponse or null if no ad available
260
+ *
261
+ * @example Basic request
262
+ * ```typescript
263
+ * const ad = await client.getAd({
264
+ * messages: [
265
+ * { role: 'user', content: 'I need a new laptop for programming' },
266
+ * { role: 'assistant', content: 'What is your budget range?' }
267
+ * ]
268
+ * });
269
+ * ```
270
+ *
271
+ * @example Full request with targeting
272
+ * ```typescript
273
+ * const ad = await client.getAd({
274
+ * messages: [...],
275
+ * user: {
276
+ * uid: 'user-123',
277
+ * gender: 'male',
278
+ * age: '25-34'
279
+ * },
280
+ * device: {
281
+ * ip: '192.168.1.1',
282
+ * country: 'US',
283
+ * ua: navigator.userAgent
284
+ * },
285
+ * excludedTopics: ['gambling'],
286
+ * relevancy: 0.8
287
+ * });
288
+ * ```
289
+ *
290
+ * @example Handling the response
291
+ * ```typescript
292
+ * const ad = await client.getAd({ messages });
293
+ *
294
+ * if (ad) {
295
+ * // Display the ad
296
+ * showAd(ad.adText);
297
+ *
298
+ * // Track impression
299
+ * if (ad.impUrl) {
300
+ * new Image().src = ad.impUrl;
301
+ * }
302
+ * }
303
+ * ```
63
304
  */
64
305
  getAd(params: AdParams): Promise<AdResponse | null>;
65
306
  /**
66
- * Handle API errors with logging
67
- * @param error - The error object
68
- * @param method - The method name where error occurred
307
+ * Handle and log API errors
308
+ *
309
+ * @description Processes errors from API calls and logs appropriate messages.
310
+ * Distinguishes between network errors, server errors, and unexpected errors.
311
+ *
312
+ * @param error - The error object from the failed request
313
+ * @param method - The name of the method where the error occurred
314
+ *
315
+ * @internal This method is for internal use only
69
316
  */
70
317
  private handleError;
71
318
  }
package/dist/index.js CHANGED
@@ -36,15 +36,37 @@ module.exports = __toCommonJS(index_exports);
36
36
 
37
37
  // client.ts
38
38
  var import_axios = __toESM(require("axios"));
39
+ var DEFAULT_ENDPOINT = "https://server.trygravity.ai";
40
+ var REQUEST_TIMEOUT = 1e4;
39
41
  var Client = class {
42
+ /**
43
+ * Create a new Gravity API client
44
+ *
45
+ * @param apiKey - Your Gravity API key (required)
46
+ * @param params - Optional configuration parameters
47
+ *
48
+ * @throws Will not throw - invalid API key errors occur on first request
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // Basic initialization
53
+ * const client = new Client('your-api-key');
54
+ *
55
+ * // With custom options
56
+ * const client = new Client('your-api-key', {
57
+ * excludedTopics: ['gambling', 'alcohol'],
58
+ * relevancy: 0.6
59
+ * });
60
+ * ```
61
+ */
40
62
  constructor(apiKey, params = {}) {
41
63
  this.apiKey = apiKey;
42
- this.endpoint = params.endpoint || "https://server.trygravity.ai";
64
+ this.endpoint = params.endpoint || DEFAULT_ENDPOINT;
43
65
  this.excludedTopics = params.excludedTopics || [];
44
- this.relevancy = params.relevancy || null;
66
+ this.relevancy = params.relevancy ?? null;
45
67
  this.axios = import_axios.default.create({
46
68
  baseURL: this.endpoint,
47
- timeout: 1e4,
69
+ timeout: REQUEST_TIMEOUT,
48
70
  headers: {
49
71
  "Authorization": `Bearer ${this.apiKey}`,
50
72
  "Content-Type": "application/json"
@@ -52,42 +74,97 @@ var Client = class {
52
74
  });
53
75
  }
54
76
  /**
55
- * Request a text advertisement. Returns null if there is no relevant ad found.
56
- * @param params - AdParams matching the server schema
57
- * @returns Promise<BidResponse | null>
77
+ * Request a contextually relevant advertisement
78
+ *
79
+ * @description Fetches an ad based on the provided conversation context and targeting parameters.
80
+ * Returns `null` if no relevant ad is available or if an error occurs.
81
+ *
82
+ * @param params - Ad request parameters including conversation messages
83
+ * @returns Promise resolving to AdResponse or null if no ad available
84
+ *
85
+ * @example Basic request
86
+ * ```typescript
87
+ * const ad = await client.getAd({
88
+ * messages: [
89
+ * { role: 'user', content: 'I need a new laptop for programming' },
90
+ * { role: 'assistant', content: 'What is your budget range?' }
91
+ * ]
92
+ * });
93
+ * ```
94
+ *
95
+ * @example Full request with targeting
96
+ * ```typescript
97
+ * const ad = await client.getAd({
98
+ * messages: [...],
99
+ * user: {
100
+ * uid: 'user-123',
101
+ * gender: 'male',
102
+ * age: '25-34'
103
+ * },
104
+ * device: {
105
+ * ip: '192.168.1.1',
106
+ * country: 'US',
107
+ * ua: navigator.userAgent
108
+ * },
109
+ * excludedTopics: ['gambling'],
110
+ * relevancy: 0.8
111
+ * });
112
+ * ```
113
+ *
114
+ * @example Handling the response
115
+ * ```typescript
116
+ * const ad = await client.getAd({ messages });
117
+ *
118
+ * if (ad) {
119
+ * // Display the ad
120
+ * showAd(ad.adText);
121
+ *
122
+ * // Track impression
123
+ * if (ad.impUrl) {
124
+ * new Image().src = ad.impUrl;
125
+ * }
126
+ * }
127
+ * ```
58
128
  */
59
129
  async getAd(params) {
60
130
  try {
61
131
  const body = {
62
132
  ...params,
63
- // prefer explicit apiKey in params, else default to client's apiKey
133
+ // Prefer explicit apiKey in params, else use client's apiKey
64
134
  apiKey: params.apiKey ?? this.apiKey,
65
- // supply top-level excludedTopics if not provided
135
+ // Use request-level excludedTopics, or fall back to client-level
66
136
  excludedTopics: params.excludedTopics ?? this.excludedTopics,
67
- // supply top-level relevancy if not provided
137
+ // Use request-level relevancy, or fall back to client-level
68
138
  relevancy: params.relevancy ?? this.relevancy
69
139
  };
70
140
  const response = await this.axios.post("/ad", body);
71
- if (response.status === 204) return null;
141
+ if (response.status === 204) {
142
+ return null;
143
+ }
72
144
  if (response.data && response.data.adText) {
73
- const payload = response.data;
74
145
  return {
75
- adText: payload.adText,
76
- impUrl: payload.impUrl,
77
- clickUrl: payload.clickUrl,
78
- payout: payload.payout
146
+ adText: response.data.adText,
147
+ impUrl: response.data.impUrl,
148
+ clickUrl: response.data.clickUrl,
149
+ payout: response.data.payout
79
150
  };
80
151
  }
152
+ return null;
81
153
  } catch (error) {
82
154
  this.handleError(error, "getAd");
83
155
  return null;
84
156
  }
85
- return null;
86
157
  }
87
158
  /**
88
- * Handle API errors with logging
89
- * @param error - The error object
90
- * @param method - The method name where error occurred
159
+ * Handle and log API errors
160
+ *
161
+ * @description Processes errors from API calls and logs appropriate messages.
162
+ * Distinguishes between network errors, server errors, and unexpected errors.
163
+ *
164
+ * @param error - The error object from the failed request
165
+ * @param method - The name of the method where the error occurred
166
+ *
167
+ * @internal This method is for internal use only
91
168
  */
92
169
  handleError(error, method) {
93
170
  if (import_axios.default.isAxiosError(error)) {
package/dist/index.mjs CHANGED
@@ -1,14 +1,36 @@
1
1
  // client.ts
2
2
  import axios from "axios";
3
+ var DEFAULT_ENDPOINT = "https://server.trygravity.ai";
4
+ var REQUEST_TIMEOUT = 1e4;
3
5
  var Client = class {
6
+ /**
7
+ * Create a new Gravity API client
8
+ *
9
+ * @param apiKey - Your Gravity API key (required)
10
+ * @param params - Optional configuration parameters
11
+ *
12
+ * @throws Will not throw - invalid API key errors occur on first request
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Basic initialization
17
+ * const client = new Client('your-api-key');
18
+ *
19
+ * // With custom options
20
+ * const client = new Client('your-api-key', {
21
+ * excludedTopics: ['gambling', 'alcohol'],
22
+ * relevancy: 0.6
23
+ * });
24
+ * ```
25
+ */
4
26
  constructor(apiKey, params = {}) {
5
27
  this.apiKey = apiKey;
6
- this.endpoint = params.endpoint || "https://server.trygravity.ai";
28
+ this.endpoint = params.endpoint || DEFAULT_ENDPOINT;
7
29
  this.excludedTopics = params.excludedTopics || [];
8
- this.relevancy = params.relevancy || null;
30
+ this.relevancy = params.relevancy ?? null;
9
31
  this.axios = axios.create({
10
32
  baseURL: this.endpoint,
11
- timeout: 1e4,
33
+ timeout: REQUEST_TIMEOUT,
12
34
  headers: {
13
35
  "Authorization": `Bearer ${this.apiKey}`,
14
36
  "Content-Type": "application/json"
@@ -16,42 +38,97 @@ var Client = class {
16
38
  });
17
39
  }
18
40
  /**
19
- * Request a text advertisement. Returns null if there is no relevant ad found.
20
- * @param params - AdParams matching the server schema
21
- * @returns Promise<BidResponse | null>
41
+ * Request a contextually relevant advertisement
42
+ *
43
+ * @description Fetches an ad based on the provided conversation context and targeting parameters.
44
+ * Returns `null` if no relevant ad is available or if an error occurs.
45
+ *
46
+ * @param params - Ad request parameters including conversation messages
47
+ * @returns Promise resolving to AdResponse or null if no ad available
48
+ *
49
+ * @example Basic request
50
+ * ```typescript
51
+ * const ad = await client.getAd({
52
+ * messages: [
53
+ * { role: 'user', content: 'I need a new laptop for programming' },
54
+ * { role: 'assistant', content: 'What is your budget range?' }
55
+ * ]
56
+ * });
57
+ * ```
58
+ *
59
+ * @example Full request with targeting
60
+ * ```typescript
61
+ * const ad = await client.getAd({
62
+ * messages: [...],
63
+ * user: {
64
+ * uid: 'user-123',
65
+ * gender: 'male',
66
+ * age: '25-34'
67
+ * },
68
+ * device: {
69
+ * ip: '192.168.1.1',
70
+ * country: 'US',
71
+ * ua: navigator.userAgent
72
+ * },
73
+ * excludedTopics: ['gambling'],
74
+ * relevancy: 0.8
75
+ * });
76
+ * ```
77
+ *
78
+ * @example Handling the response
79
+ * ```typescript
80
+ * const ad = await client.getAd({ messages });
81
+ *
82
+ * if (ad) {
83
+ * // Display the ad
84
+ * showAd(ad.adText);
85
+ *
86
+ * // Track impression
87
+ * if (ad.impUrl) {
88
+ * new Image().src = ad.impUrl;
89
+ * }
90
+ * }
91
+ * ```
22
92
  */
23
93
  async getAd(params) {
24
94
  try {
25
95
  const body = {
26
96
  ...params,
27
- // prefer explicit apiKey in params, else default to client's apiKey
97
+ // Prefer explicit apiKey in params, else use client's apiKey
28
98
  apiKey: params.apiKey ?? this.apiKey,
29
- // supply top-level excludedTopics if not provided
99
+ // Use request-level excludedTopics, or fall back to client-level
30
100
  excludedTopics: params.excludedTopics ?? this.excludedTopics,
31
- // supply top-level relevancy if not provided
101
+ // Use request-level relevancy, or fall back to client-level
32
102
  relevancy: params.relevancy ?? this.relevancy
33
103
  };
34
104
  const response = await this.axios.post("/ad", body);
35
- if (response.status === 204) return null;
105
+ if (response.status === 204) {
106
+ return null;
107
+ }
36
108
  if (response.data && response.data.adText) {
37
- const payload = response.data;
38
109
  return {
39
- adText: payload.adText,
40
- impUrl: payload.impUrl,
41
- clickUrl: payload.clickUrl,
42
- payout: payload.payout
110
+ adText: response.data.adText,
111
+ impUrl: response.data.impUrl,
112
+ clickUrl: response.data.clickUrl,
113
+ payout: response.data.payout
43
114
  };
44
115
  }
116
+ return null;
45
117
  } catch (error) {
46
118
  this.handleError(error, "getAd");
47
119
  return null;
48
120
  }
49
- return null;
50
121
  }
51
122
  /**
52
- * Handle API errors with logging
53
- * @param error - The error object
54
- * @param method - The method name where error occurred
123
+ * Handle and log API errors
124
+ *
125
+ * @description Processes errors from API calls and logs appropriate messages.
126
+ * Distinguishes between network errors, server errors, and unexpected errors.
127
+ *
128
+ * @param error - The error object from the failed request
129
+ * @param method - The name of the method where the error occurred
130
+ *
131
+ * @internal This method is for internal use only
55
132
  */
56
133
  handleError(error, method) {
57
134
  if (axios.isAxiosError(error)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ai/api",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Gravity JS SDK for retrieving targeted advertisements",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",