apogeoapi 1.0.0 → 1.0.2

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,532 +1,532 @@
1
- # @geo-api/sdk
2
-
3
- Official TypeScript SDK for Geo API - Professional geographic data API with comprehensive country, state, and city information.
4
-
5
- [![npm version](https://img.shields.io/npm/v/@geo-api/sdk)](https://www.npmjs.com/package/@geo-api/sdk)
6
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
-
8
- ## 🚀 Features
9
-
10
- - **Full TypeScript Support** - Complete type definitions with autocomplete
11
- - **Auto-Retry Logic** - Automatic retry with exponential backoff
12
- - **Error Handling** - Typed error responses
13
- - **Rate Limit Handling** - Respects retry-after headers
14
- - **Multiple Auth Methods** - API Key or JWT token
15
- - **Comprehensive Coverage** - All API endpoints covered
16
- - **Zero Config** - Works out of the box with sensible defaults
17
-
18
- ## 📦 Installation
19
-
20
- ```bash
21
- npm install @geo-api/sdk
22
-
23
- # or with yarn
24
- yarn add @geo-api/sdk
25
-
26
- # or with pnpm
27
- pnpm add @geo-api/sdk
28
- ```
29
-
30
- ## 🏃 Quick Start
31
-
32
- ```typescript
33
- import { GeoAPI } from '@geo-api/sdk';
34
-
35
- // Initialize with API key (recommended)
36
- const client = new GeoAPI({
37
- apiKey: 'geoapi_live_xxxxx',
38
- baseURL: 'https://api.yourcompany.com/v1' // optional
39
- });
40
-
41
- // Get all countries
42
- const countries = await client.geo.getCountries();
43
- console.log(`Total countries: ${countries.length}`);
44
-
45
- // Search for cities
46
- const cities = await client.geo.searchCities('New York', 10);
47
- console.log(cities);
48
-
49
- // Get usage statistics
50
- const dashboard = await client.account.getDashboard();
51
- console.log(`API calls this month: ${dashboard.usage.requestsThisMonth}`);
52
- ```
53
-
54
- ## 📚 Table of Contents
55
-
56
- - [Authentication](#authentication)
57
- - [Geography API](#geography-api)
58
- - [Account Management](#account-management)
59
- - [API Keys Management](#api-keys-management)
60
- - [Billing & Subscriptions](#billing--subscriptions)
61
- - [Webhooks](#webhooks)
62
- - [Error Handling](#error-handling)
63
- - [Advanced Configuration](#advanced-configuration)
64
-
65
- ---
66
-
67
- ## 🔐 Authentication
68
-
69
- ### API Key (Recommended for Client-Side)
70
-
71
- ```typescript
72
- const client = new GeoAPI({
73
- apiKey: 'geoapi_live_xxxxx'
74
- });
75
- ```
76
-
77
- ### JWT Token (After Login)
78
-
79
- ```typescript
80
- const client = new GeoAPI({
81
- token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
82
- });
83
-
84
- // Or set token after initialization
85
- client.setToken('new_token_here');
86
- ```
87
-
88
- ### Register & Login
89
-
90
- ```typescript
91
- // Register new user
92
- const { user, access_token, refresh_token } = await client.auth.register({
93
- email: 'user@example.com',
94
- password: 'securePassword123',
95
- username: 'johndoe'
96
- });
97
-
98
- // Login
99
- const tokens = await client.auth.login({
100
- email: 'user@example.com',
101
- password: 'securePassword123'
102
- });
103
-
104
- // Token is automatically set after login
105
- console.log('Logged in as:', tokens.user.username);
106
-
107
- // Refresh token
108
- const newTokens = await client.auth.refreshToken({
109
- refresh_token: tokens.refresh_token
110
- });
111
- ```
112
-
113
- ---
114
-
115
- ## 🌍 Geography API
116
-
117
- ### Countries
118
-
119
- ```typescript
120
- // Get all countries
121
- const countries = await client.geo.getCountries();
122
-
123
- // Get country by ISO code
124
- const usa = await client.geo.getCountryByIso('US');
125
- console.log(usa.name); // "United States"
126
- console.log(usa.capital); // "Washington"
127
- console.log(usa.currency); // "USD"
128
-
129
- // Search countries
130
- const matching = await client.geo.searchCountries('united', 5);
131
- ```
132
-
133
- ### States/Provinces
134
-
135
- ```typescript
136
- // Get all states of a country
137
- const usStates = await client.geo.getStates('US');
138
- console.log(`US has ${usStates.length} states`);
139
-
140
- // Get specific state
141
- const california = await client.geo.getStateById(1234);
142
- console.log(california.name); // "California"
143
-
144
- // Search states
145
- const texasMatch = await client.geo.searchStates('texas', 1);
146
- ```
147
-
148
- ### Cities
149
-
150
- ```typescript
151
- // Get cities of a state
152
- const californiaCities = await client.geo.getCities(1234, 100, 0);
153
-
154
- // Get specific city
155
- const city = await client.geo.getCityById(5678);
156
- console.log(`${city.name}, ${city.state.name}`);
157
-
158
- // Search cities
159
- const newYorkCities = await client.geo.searchCities('New York', 10);
160
- ```
161
-
162
- ### Universal Search
163
-
164
- ```typescript
165
- // Search across all types
166
- const results = await client.geo.search({
167
- query: 'san',
168
- limit: 20,
169
- offset: 0,
170
- type: 'city' // optional: 'country' | 'state' | 'city'
171
- });
172
-
173
- console.log(`Found ${results.total} results`);
174
- ```
175
-
176
- ---
177
-
178
- ## 👤 Account Management
179
-
180
- ### Dashboard
181
-
182
- ```typescript
183
- // Get complete dashboard
184
- const dashboard = await client.account.getDashboard();
185
-
186
- console.log('User:', dashboard.user.username);
187
- console.log('Tier:', dashboard.subscription.tier);
188
- console.log('Usage:', dashboard.usage.requestsThisMonth, '/', dashboard.usage.monthlyQuota);
189
- console.log('API Keys:', dashboard.apiKeys.active, '/', dashboard.apiKeys.max);
190
- ```
191
-
192
- ### Profile
193
-
194
- ```typescript
195
- // Update profile
196
- await client.account.updateProfile({
197
- username: 'new_username',
198
- email: 'newemail@example.com'
199
- });
200
-
201
- // Change password
202
- await client.account.changePassword({
203
- currentPassword: 'oldpass123',
204
- newPassword: 'newpass456'
205
- });
206
- ```
207
-
208
- ### Usage Statistics
209
-
210
- ```typescript
211
- // Get usage for date range
212
- const stats = await client.account.getUsage({
213
- startDate: new Date('2024-01-01'),
214
- endDate: new Date('2024-01-31'),
215
- groupBy: 'day' // or 'month'
216
- });
217
-
218
- stats.forEach(stat => {
219
- console.log(`${stat.date}: ${stat.requests} requests`);
220
- });
221
- ```
222
-
223
- ---
224
-
225
- ## 🔑 API Keys Management
226
-
227
- ### List & Create
228
-
229
- ```typescript
230
- // List all API keys
231
- const keys = await client.apiKeys.list();
232
-
233
- // Create new API key
234
- const newKey = await client.apiKeys.create({
235
- name: 'Production Server',
236
- expiresAt: new Date('2025-12-31')
237
- });
238
-
239
- console.log('🔑 Save this key:', newKey.key);
240
- // ⚠️ Key is only shown once!
241
- ```
242
-
243
- ### Update & Delete
244
-
245
- ```typescript
246
- // Rename key
247
- await client.apiKeys.update(keyId, {
248
- name: 'Production Server v2'
249
- });
250
-
251
- // Revoke key (deactivate)
252
- await client.apiKeys.revoke(keyId);
253
-
254
- // Reactivate key
255
- await client.apiKeys.activate(keyId);
256
-
257
- // Delete permanently
258
- await client.apiKeys.delete(keyId);
259
- ```
260
-
261
- ---
262
-
263
- ## 💳 Billing & Subscriptions
264
-
265
- ### Upgrade Plan
266
-
267
- ```typescript
268
- // Create checkout session
269
- const checkout = await client.billing.createCheckoutSession(
270
- 'professional', // tier
271
- 'https://myapp.com/success', // success URL
272
- 'https://myapp.com/cancel' // cancel URL
273
- );
274
-
275
- // Redirect user to Stripe
276
- window.location.href = checkout.url;
277
- ```
278
-
279
- ### Manage Subscription
280
-
281
- ```typescript
282
- // Access billing portal
283
- const portal = await client.billing.createPortalSession(
284
- 'https://myapp.com/account' // return URL
285
- );
286
-
287
- // Redirect user to Stripe portal
288
- window.location.href = portal.url;
289
- ```
290
-
291
- ### Invoices
292
-
293
- ```typescript
294
- // Get all invoices
295
- const invoices = await client.billing.getInvoices(10);
296
-
297
- invoices.forEach(invoice => {
298
- console.log(`${invoice.created}: $${invoice.amount/100} - ${invoice.status}`);
299
- console.log(`PDF: ${invoice.invoice_pdf}`);
300
- });
301
-
302
- // Get specific invoice
303
- const invoice = await client.billing.getInvoice('in_xxxxx');
304
- ```
305
-
306
- ### Cancel Subscription
307
-
308
- ```typescript
309
- // Cancel at period end
310
- await client.billing.cancelSubscription();
311
- // User keeps access until period ends
312
-
313
- // Reactivate before period ends
314
- await client.billing.reactivateSubscription();
315
- ```
316
-
317
- ---
318
-
319
- ## 🪝 Webhooks
320
-
321
- ### Create Webhook
322
-
323
- ```typescript
324
- // Create webhook
325
- const webhook = await client.webhooks.create({
326
- url: 'https://myapp.com/webhooks/geo-api',
327
- events: [
328
- 'usage.quota_warning',
329
- 'usage.quota_exceeded',
330
- 'subscription.updated'
331
- ]
332
- });
333
-
334
- console.log('Webhook ID:', webhook.id);
335
- console.log('Secret:', webhook.secret); // Use to validate payloads
336
- ```
337
-
338
- ### Manage Webhooks
339
-
340
- ```typescript
341
- // List all webhooks
342
- const webhooks = await client.webhooks.list();
343
-
344
- // Update webhook
345
- await client.webhooks.update(webhookId, {
346
- url: 'https://myapp.com/new-webhook-url',
347
- events: ['subscription.created', 'subscription.canceled']
348
- });
349
-
350
- // Test webhook
351
- const result = await client.webhooks.test(webhookId);
352
- console.log('Test success:', result.success);
353
-
354
- // Deactivate
355
- await client.webhooks.deactivate(webhookId);
356
-
357
- // Delete
358
- await client.webhooks.delete(webhookId);
359
- ```
360
-
361
- ### Delivery Logs
362
-
363
- ```typescript
364
- // Get webhook delivery logs
365
- const logs = await client.webhooks.getLogs(webhookId, 50);
366
-
367
- logs.forEach(log => {
368
- console.log(`${log.createdAt}: ${log.event} - ${log.success ? '✅' : '❌'}`);
369
- if (!log.success) {
370
- console.log(` Status: ${log.statusCode}`);
371
- }
372
- });
373
- ```
374
-
375
- ---
376
-
377
- ## ⚠️ Error Handling
378
-
379
- ```typescript
380
- import { GeoAPI, GeoAPIError } from '@geo-api/sdk';
381
-
382
- const client = new GeoAPI({ apiKey: 'xxx' });
383
-
384
- try {
385
- const country = await client.geo.getCountryByIso('INVALID');
386
- } catch (error) {
387
- if (error instanceof GeoAPIError) {
388
- console.error('Status:', error.statusCode);
389
- console.error('Message:', error.message);
390
- console.error('Response:', error.response);
391
-
392
- // Handle specific errors
393
- if (error.statusCode === 404) {
394
- console.log('Country not found');
395
- } else if (error.statusCode === 429) {
396
- console.log('Rate limit exceeded, retry after:', error.response?.retryAfter);
397
- } else if (error.statusCode === 403) {
398
- console.log('Quota exceeded or invalid API key');
399
- }
400
- } else {
401
- console.error('Unexpected error:', error);
402
- }
403
- }
404
- ```
405
-
406
- ---
407
-
408
- ## ⚙️ Advanced Configuration
409
-
410
- ### Custom Configuration
411
-
412
- ```typescript
413
- const client = new GeoAPI({
414
- apiKey: 'geoapi_live_xxxxx',
415
- baseURL: 'https://api.yourcompany.com/v1',
416
- timeout: 30000, // 30 seconds
417
- retries: 3, // retry failed requests 3 times
418
- debug: true // enable debug logging
419
- });
420
- ```
421
-
422
- ### Debug Mode
423
-
424
- ```typescript
425
- const client = new GeoAPI({
426
- apiKey: 'xxx',
427
- debug: true
428
- });
429
-
430
- // Logs all requests and retries
431
- // [SDK] GET /geo/countries
432
- // [SDK] Response 200 from /geo/countries
433
- ```
434
-
435
- ### Using Different Environments
436
-
437
- ```typescript
438
- // Development
439
- const devClient = new GeoAPI({
440
- apiKey: process.env.DEV_API_KEY,
441
- baseURL: 'http://localhost:3000/v1'
442
- });
443
-
444
- // Production
445
- const prodClient = new GeoAPI({
446
- apiKey: process.env.PROD_API_KEY,
447
- baseURL: 'https://api.yourcompany.com/v1'
448
- });
449
- ```
450
-
451
- ---
452
-
453
- ## 🧪 Examples
454
-
455
- ### Complete Application Example
456
-
457
- ```typescript
458
- import { GeoAPI } from '@geo-api/sdk';
459
-
460
- const client = new GeoAPI({
461
- apiKey: process.env.GEO_API_KEY!
462
- });
463
-
464
- async function main() {
465
- // 1. Get dashboard
466
- const dashboard = await client.account.getDashboard();
467
- console.log(`Welcome ${dashboard.user.username}!`);
468
- console.log(`You're on the ${dashboard.subscription.tier} plan`);
469
- console.log(`Usage: ${dashboard.usage.usagePercentage}%`);
470
-
471
- // 2. Query geography data
472
- const countries = await client.geo.getCountries();
473
- console.log(`\nTotal countries: ${countries.length}`);
474
-
475
- // 3. Search for specific location
476
- const cities = await client.geo.searchCities('Paris', 5);
477
- console.log(`\nCities named Paris:`);
478
- cities.forEach(city => {
479
- console.log(`- ${city.name}, ${city.state?.name}, ${city.country?.name}`);
480
- });
481
-
482
- // 4. Check usage
483
- const usage = await client.account.getUsage({
484
- startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
485
- endDate: new Date(),
486
- groupBy: 'day'
487
- });
488
- console.log(`\nLast 30 days usage:`, usage.length, 'days');
489
- }
490
-
491
- main().catch(console.error);
492
- ```
493
-
494
- ---
495
-
496
- ## 📝 TypeScript Support
497
-
498
- Full TypeScript support with complete type definitions:
499
-
500
- ```typescript
501
- import { GeoAPI, Country, City, Tier, WebhookEvent } from '@geo-api/sdk';
502
-
503
- const client = new GeoAPI({ apiKey: 'xxx' });
504
-
505
- // All responses are fully typed
506
- const country: Country = await client.geo.getCountryByIso('US');
507
- const cities: City[] = await client.geo.searchCities('London', 10);
508
-
509
- // Enums are typed
510
- const tier: Tier = 'professional';
511
- const events: WebhookEvent[] = ['usage.quota_warning', 'subscription.updated'];
512
- ```
513
-
514
- ---
515
-
516
- ## 🤝 Contributing
517
-
518
- Contributions are welcome! Please open an issue or submit a pull request.
519
-
520
- ## 📄 License
521
-
522
- MIT © Geo API Team
523
-
524
- ## 🔗 Links
525
-
526
- - [API Documentation](https://api.yourcompany.com/docs)
527
- - [GitHub Repository](https://github.com/your-org/geo-api-sdk)
528
- - [Support](mailto:support@yourcompany.com)
529
-
530
- ---
531
-
532
- **Made with ❤️ by the Geo API Team**
1
+ # apogeoapi — JavaScript/TypeScript SDK
2
+
3
+ Official TypeScript SDK for ApogeoAPI professional geographic data API with comprehensive country, state, and city information, IP geolocation, and exchange rates.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/apogeoapi)](https://www.npmjs.com/package/apogeoapi)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+
8
+ ## Features
9
+
10
+ - **Full TypeScript Support** - Complete type definitions with autocomplete
11
+ - **Auto-Retry Logic** - Automatic retry with exponential backoff
12
+ - **Error Handling** - Typed error responses
13
+ - **Rate Limit Handling** - Respects retry-after headers
14
+ - **Multiple Auth Methods** - API Key or JWT token
15
+ - **Comprehensive Coverage** - All API endpoints covered
16
+ - **Zero Config** - Works out of the box with sensible defaults
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install apogeoapi
22
+
23
+ # or with yarn
24
+ yarn add apogeoapi
25
+
26
+ # or with pnpm
27
+ pnpm add apogeoapi
28
+ ```
29
+
30
+ ## Quick Start
31
+
32
+ ```typescript
33
+ import { ApogeoAPI } from 'apogeoapi';
34
+
35
+ // Initialize with API key (recommended)
36
+ const client = new ApogeoAPI({
37
+ apiKey: 'geoapi_live_xxxxx'
38
+ });
39
+
40
+ // Get all countries
41
+ const countries = await client.geo.getCountries();
42
+ console.log(`Total countries: ${countries.length}`);
43
+
44
+ // Search for cities
45
+ const cities = await client.geo.searchCities('New York', 10);
46
+ console.log(cities);
47
+
48
+ // Get usage statistics
49
+ const dashboard = await client.account.getDashboard();
50
+ console.log(`API calls this month: ${dashboard.usage.requestsThisMonth}`);
51
+ ```
52
+
53
+ ## Table of Contents
54
+
55
+ - [Authentication](#authentication)
56
+ - [Geography API](#geography-api)
57
+ - [Account Management](#account-management)
58
+ - [API Keys Management](#api-keys-management)
59
+ - [Billing & Subscriptions](#billing--subscriptions)
60
+ - [Webhooks](#webhooks)
61
+ - [Error Handling](#error-handling)
62
+ - [Advanced Configuration](#advanced-configuration)
63
+
64
+ ---
65
+
66
+ ## Authentication
67
+
68
+ ### API Key (Recommended for Client-Side)
69
+
70
+ ```typescript
71
+ const client = new ApogeoAPI({
72
+ apiKey: 'geoapi_live_xxxxx'
73
+ });
74
+ ```
75
+
76
+ ### JWT Token (After Login)
77
+
78
+ ```typescript
79
+ const client = new ApogeoAPI({
80
+ token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
81
+ });
82
+
83
+ // Or set token after initialization
84
+ client.setToken('new_token_here');
85
+ ```
86
+
87
+ ### Register & Login
88
+
89
+ ```typescript
90
+ // Register new user
91
+ const { user, access_token, refresh_token } = await client.auth.register({
92
+ email: 'user@example.com',
93
+ password: 'securePassword123',
94
+ username: 'johndoe'
95
+ });
96
+
97
+ // Login
98
+ const tokens = await client.auth.login({
99
+ email: 'user@example.com',
100
+ password: 'securePassword123'
101
+ });
102
+
103
+ // Token is automatically set after login
104
+ console.log('Logged in as:', tokens.user.username);
105
+
106
+ // Refresh token
107
+ const newTokens = await client.auth.refreshToken({
108
+ refresh_token: tokens.refresh_token
109
+ });
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Geography API
115
+
116
+ ### Countries
117
+
118
+ ```typescript
119
+ // Get all countries
120
+ const countries = await client.geo.getCountries();
121
+
122
+ // Get country by ISO code
123
+ const usa = await client.geo.getCountryByIso('US');
124
+ console.log(usa.name); // "United States"
125
+ console.log(usa.capital); // "Washington"
126
+ console.log(usa.currency); // "USD"
127
+
128
+ // Search countries
129
+ const matching = await client.geo.searchCountries('united', 5);
130
+ ```
131
+
132
+ ### States/Provinces
133
+
134
+ ```typescript
135
+ // Get all states of a country
136
+ const usStates = await client.geo.getStates('US');
137
+ console.log(`US has ${usStates.length} states`);
138
+
139
+ // Get specific state
140
+ const california = await client.geo.getStateById(1234);
141
+ console.log(california.name); // "California"
142
+
143
+ // Search states
144
+ const texasMatch = await client.geo.searchStates('texas', 1);
145
+ ```
146
+
147
+ ### Cities
148
+
149
+ ```typescript
150
+ // Get cities of a state
151
+ const californiaCities = await client.geo.getCities(1234, 100, 0);
152
+
153
+ // Get specific city
154
+ const city = await client.geo.getCityById(5678);
155
+ console.log(`${city.name}, ${city.state.name}`);
156
+
157
+ // Search cities
158
+ const newYorkCities = await client.geo.searchCities('New York', 10);
159
+ ```
160
+
161
+ ### Universal Search
162
+
163
+ ```typescript
164
+ // Search across all types
165
+ const results = await client.geo.search({
166
+ query: 'san',
167
+ limit: 20,
168
+ offset: 0,
169
+ type: 'city' // optional: 'country' | 'state' | 'city'
170
+ });
171
+
172
+ console.log(`Found ${results.total} results`);
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Account Management
178
+
179
+ ### Dashboard
180
+
181
+ ```typescript
182
+ // Get complete dashboard
183
+ const dashboard = await client.account.getDashboard();
184
+
185
+ console.log('User:', dashboard.user.username);
186
+ console.log('Tier:', dashboard.subscription.tier);
187
+ console.log('Usage:', dashboard.usage.requestsThisMonth, '/', dashboard.usage.monthlyQuota);
188
+ console.log('API Keys:', dashboard.apiKeys.active, '/', dashboard.apiKeys.max);
189
+ ```
190
+
191
+ ### Profile
192
+
193
+ ```typescript
194
+ // Update profile
195
+ await client.account.updateProfile({
196
+ username: 'new_username',
197
+ email: 'newemail@example.com'
198
+ });
199
+
200
+ // Change password
201
+ await client.account.changePassword({
202
+ currentPassword: 'oldpass123',
203
+ newPassword: 'newpass456'
204
+ });
205
+ ```
206
+
207
+ ### Usage Statistics
208
+
209
+ ```typescript
210
+ // Get usage for date range
211
+ const stats = await client.account.getUsage({
212
+ startDate: new Date('2024-01-01'),
213
+ endDate: new Date('2024-01-31'),
214
+ groupBy: 'day' // or 'month'
215
+ });
216
+
217
+ stats.forEach(stat => {
218
+ console.log(`${stat.date}: ${stat.requests} requests`);
219
+ });
220
+ ```
221
+
222
+ ---
223
+
224
+ ## API Keys Management
225
+
226
+ ### List & Create
227
+
228
+ ```typescript
229
+ // List all API keys
230
+ const keys = await client.apiKeys.list();
231
+
232
+ // Create new API key
233
+ const newKey = await client.apiKeys.create({
234
+ name: 'Production Server',
235
+ expiresAt: new Date('2025-12-31')
236
+ });
237
+
238
+ console.log('Save this key:', newKey.key);
239
+ // Key is only shown once!
240
+ ```
241
+
242
+ ### Update & Delete
243
+
244
+ ```typescript
245
+ // Rename key
246
+ await client.apiKeys.update(keyId, {
247
+ name: 'Production Server v2'
248
+ });
249
+
250
+ // Revoke key (deactivate)
251
+ await client.apiKeys.revoke(keyId);
252
+
253
+ // Reactivate key
254
+ await client.apiKeys.activate(keyId);
255
+
256
+ // Delete permanently
257
+ await client.apiKeys.delete(keyId);
258
+ ```
259
+
260
+ ---
261
+
262
+ ## Billing & Subscriptions
263
+
264
+ ### Upgrade Plan
265
+
266
+ ```typescript
267
+ // Create checkout session
268
+ const checkout = await client.billing.createCheckoutSession(
269
+ 'professional', // tier
270
+ 'https://myapp.com/success', // success URL
271
+ 'https://myapp.com/cancel' // cancel URL
272
+ );
273
+
274
+ // Redirect user to payment page
275
+ window.location.href = checkout.url;
276
+ ```
277
+
278
+ ### Manage Subscription
279
+
280
+ ```typescript
281
+ // Access billing portal
282
+ const portal = await client.billing.createPortalSession(
283
+ 'https://myapp.com/account' // return URL
284
+ );
285
+
286
+ // Redirect user to billing portal
287
+ window.location.href = portal.url;
288
+ ```
289
+
290
+ ### Invoices
291
+
292
+ ```typescript
293
+ // Get all invoices
294
+ const invoices = await client.billing.getInvoices(10);
295
+
296
+ invoices.forEach(invoice => {
297
+ console.log(`${invoice.created}: $${invoice.amount/100} - ${invoice.status}`);
298
+ console.log(`PDF: ${invoice.invoice_pdf}`);
299
+ });
300
+
301
+ // Get specific invoice
302
+ const invoice = await client.billing.getInvoice('in_xxxxx');
303
+ ```
304
+
305
+ ### Cancel Subscription
306
+
307
+ ```typescript
308
+ // Cancel at period end
309
+ await client.billing.cancelSubscription();
310
+ // User keeps access until period ends
311
+
312
+ // Reactivate before period ends
313
+ await client.billing.reactivateSubscription();
314
+ ```
315
+
316
+ ---
317
+
318
+ ## Webhooks
319
+
320
+ ### Create Webhook
321
+
322
+ ```typescript
323
+ // Create webhook
324
+ const webhook = await client.webhooks.create({
325
+ url: 'https://myapp.com/webhooks/apogeoapi',
326
+ events: [
327
+ 'usage.quota_warning',
328
+ 'usage.quota_exceeded',
329
+ 'subscription.updated'
330
+ ]
331
+ });
332
+
333
+ console.log('Webhook ID:', webhook.id);
334
+ console.log('Secret:', webhook.secret); // Use to validate payloads
335
+ ```
336
+
337
+ ### Manage Webhooks
338
+
339
+ ```typescript
340
+ // List all webhooks
341
+ const webhooks = await client.webhooks.list();
342
+
343
+ // Update webhook
344
+ await client.webhooks.update(webhookId, {
345
+ url: 'https://myapp.com/new-webhook-url',
346
+ events: ['subscription.created', 'subscription.canceled']
347
+ });
348
+
349
+ // Test webhook
350
+ const result = await client.webhooks.test(webhookId);
351
+ console.log('Test success:', result.success);
352
+
353
+ // Deactivate
354
+ await client.webhooks.deactivate(webhookId);
355
+
356
+ // Delete
357
+ await client.webhooks.delete(webhookId);
358
+ ```
359
+
360
+ ### Delivery Logs
361
+
362
+ ```typescript
363
+ // Get webhook delivery logs
364
+ const logs = await client.webhooks.getLogs(webhookId, 50);
365
+
366
+ logs.forEach(log => {
367
+ console.log(`${log.createdAt}: ${log.event} - ${log.success ? 'OK' : 'FAIL'}`);
368
+ if (!log.success) {
369
+ console.log(` Status: ${log.statusCode}`);
370
+ }
371
+ });
372
+ ```
373
+
374
+ ---
375
+
376
+ ## Error Handling
377
+
378
+ ```typescript
379
+ import { ApogeoAPI, ApogeoAPIError } from 'apogeoapi';
380
+
381
+ const client = new ApogeoAPI({ apiKey: 'xxx' });
382
+
383
+ try {
384
+ const country = await client.geo.getCountryByIso('INVALID');
385
+ } catch (error) {
386
+ if (error instanceof ApogeoAPIError) {
387
+ console.error('Status:', error.statusCode);
388
+ console.error('Message:', error.message);
389
+ console.error('Response:', error.response);
390
+
391
+ // Handle specific errors
392
+ if (error.statusCode === 404) {
393
+ console.log('Country not found');
394
+ } else if (error.statusCode === 429) {
395
+ console.log('Rate limit exceeded, retry after:', error.response?.retryAfter);
396
+ } else if (error.statusCode === 403) {
397
+ console.log('Quota exceeded or invalid API key');
398
+ }
399
+ } else {
400
+ console.error('Unexpected error:', error);
401
+ }
402
+ }
403
+ ```
404
+
405
+ ---
406
+
407
+ ## Advanced Configuration
408
+
409
+ ### Custom Configuration
410
+
411
+ ```typescript
412
+ const client = new ApogeoAPI({
413
+ apiKey: 'geoapi_live_xxxxx',
414
+ baseURL: 'https://api.apogeoapi.com/v1',
415
+ timeout: 30000, // 30 seconds
416
+ retries: 3, // retry failed requests 3 times
417
+ debug: true // enable debug logging
418
+ });
419
+ ```
420
+
421
+ ### Debug Mode
422
+
423
+ ```typescript
424
+ const client = new ApogeoAPI({
425
+ apiKey: 'xxx',
426
+ debug: true
427
+ });
428
+
429
+ // Logs all requests and retries
430
+ // [SDK] GET /geo/countries
431
+ // [SDK] Response 200 from /geo/countries
432
+ ```
433
+
434
+ ### Using Different Environments
435
+
436
+ ```typescript
437
+ // Development
438
+ const devClient = new ApogeoAPI({
439
+ apiKey: process.env.DEV_API_KEY,
440
+ baseURL: 'http://localhost:3000/v1'
441
+ });
442
+
443
+ // Production
444
+ const prodClient = new ApogeoAPI({
445
+ apiKey: process.env.PROD_API_KEY,
446
+ baseURL: 'https://api.apogeoapi.com/v1'
447
+ });
448
+ ```
449
+
450
+ ---
451
+
452
+ ## Examples
453
+
454
+ ### Complete Application Example
455
+
456
+ ```typescript
457
+ import { ApogeoAPI } from 'apogeoapi';
458
+
459
+ const client = new ApogeoAPI({
460
+ apiKey: process.env.GEO_API_KEY!
461
+ });
462
+
463
+ async function main() {
464
+ // 1. Get dashboard
465
+ const dashboard = await client.account.getDashboard();
466
+ console.log(`Welcome ${dashboard.user.username}!`);
467
+ console.log(`You're on the ${dashboard.subscription.tier} plan`);
468
+ console.log(`Usage: ${dashboard.usage.usagePercentage}%`);
469
+
470
+ // 2. Query geography data
471
+ const countries = await client.geo.getCountries();
472
+ console.log(`\nTotal countries: ${countries.length}`);
473
+
474
+ // 3. Search for specific location
475
+ const cities = await client.geo.searchCities('Paris', 5);
476
+ console.log(`\nCities named Paris:`);
477
+ cities.forEach(city => {
478
+ console.log(`- ${city.name}, ${city.state?.name}, ${city.country?.name}`);
479
+ });
480
+
481
+ // 4. Check usage
482
+ const usage = await client.account.getUsage({
483
+ startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
484
+ endDate: new Date(),
485
+ groupBy: 'day'
486
+ });
487
+ console.log(`\nLast 30 days usage:`, usage.length, 'days');
488
+ }
489
+
490
+ main().catch(console.error);
491
+ ```
492
+
493
+ ---
494
+
495
+ ## TypeScript Support
496
+
497
+ Full TypeScript support with complete type definitions:
498
+
499
+ ```typescript
500
+ import { ApogeoAPI, Country, City, Tier, WebhookEvent } from 'apogeoapi';
501
+
502
+ const client = new ApogeoAPI({ apiKey: 'xxx' });
503
+
504
+ // All responses are fully typed
505
+ const country: Country = await client.geo.getCountryByIso('US');
506
+ const cities: City[] = await client.geo.searchCities('London', 10);
507
+
508
+ // Enums are typed
509
+ const tier: Tier = 'professional';
510
+ const events: WebhookEvent[] = ['usage.quota_warning', 'subscription.updated'];
511
+ ```
512
+
513
+ ---
514
+
515
+ ## Contributing
516
+
517
+ Contributions are welcome! Please open an issue or submit a pull request.
518
+
519
+ ## License
520
+
521
+ MIT © ApogeoAPI
522
+
523
+ ## Links
524
+
525
+ - [API Documentation](https://api.apogeoapi.com/api/docs)
526
+ - [npm Package](https://www.npmjs.com/package/apogeoapi)
527
+ - [Website](https://apogeoapi.com)
528
+ - [Support](mailto:support@apogeoapi.com)
529
+
530
+ ---
531
+
532
+ **Made with care by the ApogeoAPI Team**