oilpriceapi 0.6.0 → 0.8.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.
Files changed (80) hide show
  1. package/README.md +418 -123
  2. package/dist/cjs/client.js +490 -0
  3. package/dist/cjs/errors.js +80 -0
  4. package/dist/cjs/index.js +82 -0
  5. package/dist/cjs/package.json +1 -0
  6. package/dist/cjs/resources/alerts.js +387 -0
  7. package/dist/cjs/resources/analytics.js +226 -0
  8. package/dist/cjs/resources/bunker-fuels.js +196 -0
  9. package/dist/cjs/resources/commodities.js +115 -0
  10. package/dist/cjs/resources/data-quality.js +144 -0
  11. package/dist/cjs/resources/data-sources.js +297 -0
  12. package/dist/cjs/resources/diesel.js +119 -0
  13. package/dist/cjs/resources/drilling.js +269 -0
  14. package/dist/cjs/resources/ei/drilling-productivity.js +108 -0
  15. package/dist/cjs/resources/ei/forecasts.js +106 -0
  16. package/dist/cjs/resources/ei/frac-focus.js +155 -0
  17. package/dist/cjs/resources/ei/index.js +98 -0
  18. package/dist/cjs/resources/ei/oil-inventories.js +97 -0
  19. package/dist/cjs/resources/ei/opec-production.js +97 -0
  20. package/dist/cjs/resources/ei/rig-counts.js +93 -0
  21. package/dist/cjs/resources/ei/well-permits.js +124 -0
  22. package/dist/cjs/resources/forecasts.js +162 -0
  23. package/dist/cjs/resources/futures.js +233 -0
  24. package/dist/cjs/resources/rig-counts.js +161 -0
  25. package/dist/cjs/resources/storage.js +166 -0
  26. package/dist/cjs/resources/webhooks.js +294 -0
  27. package/dist/cjs/types.js +2 -0
  28. package/dist/cjs/version.js +24 -0
  29. package/dist/client.d.ts +116 -5
  30. package/dist/client.js +169 -47
  31. package/dist/errors.d.ts +6 -0
  32. package/dist/errors.js +25 -16
  33. package/dist/index.d.ts +45 -6
  34. package/dist/index.js +40 -3
  35. package/dist/resources/alerts.d.ts +52 -15
  36. package/dist/resources/alerts.js +121 -109
  37. package/dist/resources/analytics.d.ts +325 -0
  38. package/dist/resources/analytics.js +222 -0
  39. package/dist/resources/bunker-fuels.d.ts +270 -0
  40. package/dist/resources/bunker-fuels.js +192 -0
  41. package/dist/resources/commodities.d.ts +148 -0
  42. package/dist/resources/commodities.js +111 -0
  43. package/dist/resources/data-quality.d.ts +229 -0
  44. package/dist/resources/data-quality.js +140 -0
  45. package/dist/resources/data-sources.d.ts +365 -0
  46. package/dist/resources/data-sources.js +293 -0
  47. package/dist/resources/diesel.d.ts +1 -1
  48. package/dist/resources/diesel.js +9 -38
  49. package/dist/resources/drilling.d.ts +403 -0
  50. package/dist/resources/drilling.js +265 -0
  51. package/dist/resources/ei/drilling-productivity.d.ts +173 -0
  52. package/dist/resources/ei/drilling-productivity.js +104 -0
  53. package/dist/resources/ei/forecasts.d.ts +177 -0
  54. package/dist/resources/ei/forecasts.js +102 -0
  55. package/dist/resources/ei/frac-focus.d.ts +212 -0
  56. package/dist/resources/ei/frac-focus.js +151 -0
  57. package/dist/resources/ei/index.d.ts +140 -0
  58. package/dist/resources/ei/index.js +88 -0
  59. package/dist/resources/ei/oil-inventories.d.ts +155 -0
  60. package/dist/resources/ei/oil-inventories.js +93 -0
  61. package/dist/resources/ei/opec-production.d.ts +146 -0
  62. package/dist/resources/ei/opec-production.js +93 -0
  63. package/dist/resources/ei/rig-counts.d.ts +131 -0
  64. package/dist/resources/ei/rig-counts.js +89 -0
  65. package/dist/resources/ei/well-permits.d.ts +178 -0
  66. package/dist/resources/ei/well-permits.js +120 -0
  67. package/dist/resources/forecasts.d.ts +200 -0
  68. package/dist/resources/forecasts.js +158 -0
  69. package/dist/resources/futures.d.ts +322 -0
  70. package/dist/resources/futures.js +229 -0
  71. package/dist/resources/rig-counts.d.ts +221 -0
  72. package/dist/resources/rig-counts.js +157 -0
  73. package/dist/resources/storage.d.ts +182 -0
  74. package/dist/resources/storage.js +162 -0
  75. package/dist/resources/webhooks.d.ts +326 -0
  76. package/dist/resources/webhooks.js +290 -0
  77. package/dist/types.d.ts +79 -8
  78. package/dist/version.d.ts +1 -1
  79. package/dist/version.js +2 -2
  80. package/package.json +17 -8
package/README.md CHANGED
@@ -1,9 +1,15 @@
1
1
  # Oil Price API - Node.js SDK
2
2
 
3
+ > **Real-time oil and commodity price data for Node.js** - Professional-grade API at 98% less cost than Bloomberg Terminal
4
+
3
5
  [![npm version](https://badge.fury.io/js/oilpriceapi.svg)](https://www.npmjs.com/package/oilpriceapi)
6
+ [![npm downloads](https://img.shields.io/npm/dm/oilpriceapi)](https://www.npmjs.com/package/oilpriceapi)
7
+ [![Tests](https://github.com/OilpriceAPI/oilpriceapi-node/actions/workflows/test.yml/badge.svg)](https://github.com/OilpriceAPI/oilpriceapi-node/actions/workflows/test.yml)
4
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
9
 
6
- Official Node.js SDK for [Oil Price API](https://www.oilpriceapi.com) - Get real-time and historical oil & commodity prices.
10
+ **[Get Free API Key](https://www.oilpriceapi.com/signup?utm_source=npm&utm_medium=sdk&utm_campaign=readme)** | **[Documentation](https://docs.oilpriceapi.com)** | **[Pricing](https://www.oilpriceapi.com/pricing?utm_source=npm&utm_medium=sdk&utm_campaign=pricing)**
11
+
12
+ The official Node.js/TypeScript SDK for [OilPriceAPI](https://www.oilpriceapi.com) - Real-time and historical oil prices for Brent Crude, WTI, Natural Gas, and 100+ commodities.
7
13
 
8
14
  ## Features
9
15
 
@@ -18,6 +24,7 @@ Official Node.js SDK for [Oil Price API](https://www.oilpriceapi.com) - Get real
18
24
  - 🐛 **Debuggable** - Built-in debug logging mode
19
25
  - ⛽ **NEW v0.4.0** - Diesel prices (state averages + station-level pricing)
20
26
  - 🔔 **NEW v0.5.0** - Price alerts with webhook notifications
27
+ - 📊 **NEW v0.7.0** - Futures, storage, rig counts, analytics, drilling intelligence, webhooks, and energy intelligence
21
28
 
22
29
  ## Installation
23
30
 
@@ -28,13 +35,13 @@ npm install oilpriceapi
28
35
  ## Quick Start
29
36
 
30
37
  ```typescript
31
- import { OilPriceAPI } from 'oilpriceapi';
38
+ import { OilPriceAPI } from "oilpriceapi";
32
39
 
33
40
  // Initialize the client
34
41
  const client = new OilPriceAPI({
35
- apiKey: 'your_api_key_here', // Get your free key at https://www.oilpriceapi.com
36
- retries: 3, // Automatic retries (default: 3)
37
- timeout: 30000 // Request timeout in ms (default: 30000)
42
+ apiKey: "your_api_key_here", // Get your free key at https://www.oilpriceapi.com/signup
43
+ retries: 3, // Automatic retries (default: 3)
44
+ timeout: 30000, // Request timeout in ms (default: 30000)
38
45
  });
39
46
 
40
47
  // Get latest prices
@@ -68,11 +75,11 @@ const prices = await client.getLatestPrices();
68
75
 
69
76
  ```typescript
70
77
  // Get only WTI crude oil price
71
- const wti = await client.getLatestPrices({ commodity: 'WTI_USD' });
78
+ const wti = await client.getLatestPrices({ commodity: "WTI_USD" });
72
79
  console.log(`WTI: ${wti[0].formatted} per barrel`);
73
80
 
74
81
  // Get only Brent crude price
75
- const brent = await client.getLatestPrices({ commodity: 'BRENT_CRUDE_USD' });
82
+ const brent = await client.getLatestPrices({ commodity: "BRENT_CRUDE_USD" });
76
83
  console.log(`Brent: ${brent[0].formatted} per barrel`);
77
84
  ```
78
85
 
@@ -80,8 +87,8 @@ console.log(`Brent: ${brent[0].formatted} per barrel`);
80
87
 
81
88
  ```typescript
82
89
  const weekPrices = await client.getHistoricalPrices({
83
- period: 'past_week',
84
- commodity: 'WTI_USD'
90
+ period: "past_week",
91
+ commodity: "WTI_USD",
85
92
  });
86
93
 
87
94
  console.log(`Got ${weekPrices.length} data points from the past week`);
@@ -91,9 +98,9 @@ console.log(`Got ${weekPrices.length} data points from the past week`);
91
98
 
92
99
  ```typescript
93
100
  const prices = await client.getHistoricalPrices({
94
- startDate: '2024-01-01',
95
- endDate: '2024-12-31',
96
- commodity: 'BRENT_CRUDE_USD'
101
+ startDate: "2024-01-01",
102
+ endDate: "2024-12-31",
103
+ commodity: "BRENT_CRUDE_USD",
97
104
  });
98
105
 
99
106
  console.log(`Got ${prices.length} data points for 2024`);
@@ -106,9 +113,9 @@ For year-long queries, use the `interval` parameter to dramatically improve resp
106
113
  ```typescript
107
114
  // FAST: Daily aggregation returns 365 data points (~1 second)
108
115
  const yearlyPrices = await client.getHistoricalPrices({
109
- period: 'past_year',
110
- commodity: 'BRENT_CRUDE_USD',
111
- interval: 'daily' // Options: 'raw', 'hourly', 'daily', 'weekly', 'monthly'
116
+ period: "past_year",
117
+ commodity: "BRENT_CRUDE_USD",
118
+ interval: "daily", // Options: 'raw', 'hourly', 'daily', 'weekly', 'monthly'
112
119
  });
113
120
 
114
121
  console.log(`Got ${yearlyPrices.length} daily averages`);
@@ -124,7 +131,7 @@ console.log(`Got ${yearlyPrices.length} daily averages`);
124
131
 
125
132
  ```typescript
126
133
  // Get California diesel price
127
- const caPrice = await client.diesel.getPrice('CA');
134
+ const caPrice = await client.diesel.getPrice("CA");
128
135
  console.log(`California diesel: $${caPrice.price}/gallon`);
129
136
  console.log(`Source: ${caPrice.source}`);
130
137
  console.log(`Last updated: ${caPrice.updated_at}`);
@@ -140,16 +147,18 @@ console.log(`Last updated: ${caPrice.updated_at}`);
140
147
  ```typescript
141
148
  // Find diesel stations near San Francisco
142
149
  const result = await client.diesel.getStations({
143
- lat: 37.7749, // San Francisco latitude
150
+ lat: 37.7749, // San Francisco latitude
144
151
  lng: -122.4194, // San Francisco longitude
145
- radius: 8047 // 5 miles in meters (default if not specified)
152
+ radius: 8047, // 5 miles in meters (default if not specified)
146
153
  });
147
154
 
148
155
  console.log(`Regional average: $${result.regional_average.price}/gallon`);
149
- console.log(`Found ${result.stations.length} stations within ${result.search_area.radius_miles} miles`);
156
+ console.log(
157
+ `Found ${result.stations.length} stations within ${result.search_area.radius_miles} miles`,
158
+ );
150
159
 
151
160
  // Print each station
152
- result.stations.forEach(station => {
161
+ result.stations.forEach((station) => {
153
162
  console.log(`\n${station.name}`);
154
163
  console.log(` Address: ${station.address}`);
155
164
  console.log(` Price: ${station.formatted_price}`);
@@ -175,18 +184,20 @@ result.stations.forEach(station => {
175
184
 
176
185
  ```typescript
177
186
  const result = await client.diesel.getStations({
178
- lat: 34.0522, // Los Angeles
187
+ lat: 34.0522, // Los Angeles
179
188
  lng: -118.2437,
180
- radius: 5000 // ~3 miles
189
+ radius: 5000, // ~3 miles
181
190
  });
182
191
 
183
192
  // Find the cheapest station
184
193
  const cheapest = result.stations.reduce((min, station) =>
185
- station.diesel_price < min.diesel_price ? station : min
194
+ station.diesel_price < min.diesel_price ? station : min,
186
195
  );
187
196
 
188
197
  console.log(`Cheapest diesel: ${cheapest.name} at ${cheapest.formatted_price}`);
189
- console.log(`Savings: ${Math.abs(cheapest.price_delta!).toFixed(2)} per gallon vs regional average`);
198
+ console.log(
199
+ `Savings: ${Math.abs(cheapest.price_delta!).toFixed(2)} per gallon vs regional average`,
200
+ );
190
201
  ```
191
202
 
192
203
  **Note:** Station-level diesel prices are available on paid tiers (Exploration and above). State averages are free.
@@ -198,13 +209,13 @@ console.log(`Savings: ${Math.abs(cheapest.price_delta!).toFixed(2)} per gallon v
198
209
  ```typescript
199
210
  // Create an alert when Brent crude exceeds $85
200
211
  const alert = await client.alerts.create({
201
- name: 'Brent High Alert',
202
- commodity_code: 'BRENT_CRUDE_USD',
203
- condition_operator: 'greater_than',
204
- condition_value: 85.00,
205
- webhook_url: 'https://your-app.com/webhooks/price-alert',
212
+ name: "Brent High Alert",
213
+ commodity_code: "BRENT_CRUDE_USD",
214
+ condition_operator: "greater_than",
215
+ condition_value: 85.0,
216
+ webhook_url: "https://your-app.com/webhooks/price-alert",
206
217
  enabled: true,
207
- cooldown_minutes: 60 // Wait 60 minutes between triggers
218
+ cooldown_minutes: 60, // Wait 60 minutes between triggers
208
219
  });
209
220
 
210
221
  console.log(`Alert created: ${alert.name} (ID: ${alert.id})`);
@@ -215,11 +226,13 @@ console.log(`Alert created: ${alert.name} (ID: ${alert.id})`);
215
226
  ```typescript
216
227
  const alerts = await client.alerts.list();
217
228
 
218
- alerts.forEach(alert => {
219
- console.log(`${alert.name}: ${alert.commodity_code} ${alert.condition_operator} ${alert.condition_value}`);
220
- console.log(` Status: ${alert.enabled ? 'Active' : 'Disabled'}`);
229
+ alerts.forEach((alert) => {
230
+ console.log(
231
+ `${alert.name}: ${alert.commodity_code} ${alert.condition_operator} ${alert.condition_value}`,
232
+ );
233
+ console.log(` Status: ${alert.enabled ? "Active" : "Disabled"}`);
221
234
  console.log(` Triggers: ${alert.trigger_count}`);
222
- console.log(` Last triggered: ${alert.last_triggered_at || 'Never'}`);
235
+ console.log(` Last triggered: ${alert.last_triggered_at || "Never"}`);
223
236
  });
224
237
  ```
225
238
 
@@ -231,13 +244,13 @@ await client.alerts.update(alertId, { enabled: false });
231
244
 
232
245
  // Change threshold and cooldown
233
246
  await client.alerts.update(alertId, {
234
- condition_value: 90.00,
235
- cooldown_minutes: 120
247
+ condition_value: 90.0,
248
+ cooldown_minutes: 120,
236
249
  });
237
250
 
238
251
  // Update webhook URL
239
252
  await client.alerts.update(alertId, {
240
- webhook_url: 'https://new-app.com/webhook'
253
+ webhook_url: "https://new-app.com/webhook",
241
254
  });
242
255
  ```
243
256
 
@@ -245,22 +258,25 @@ await client.alerts.update(alertId, {
245
258
 
246
259
  ```typescript
247
260
  await client.alerts.delete(alertId);
248
- console.log('Alert deleted successfully');
261
+ console.log("Alert deleted successfully");
249
262
  ```
250
263
 
251
264
  #### Test Webhook Endpoint
252
265
 
253
266
  ```typescript
254
- const result = await client.alerts.testWebhook('https://your-app.com/webhook');
267
+ const result = await client.alerts.testWebhook("https://your-app.com/webhook");
255
268
 
256
269
  if (result.success) {
257
- console.log(`Webhook OK (${result.status_code}) - ${result.response_time_ms}ms`);
270
+ console.log(
271
+ `Webhook OK (${result.status_code}) - ${result.response_time_ms}ms`,
272
+ );
258
273
  } else {
259
274
  console.error(`Webhook failed: ${result.error}`);
260
275
  }
261
276
  ```
262
277
 
263
278
  **Alert Operators:**
279
+
264
280
  - `greater_than` - Trigger when price exceeds threshold
265
281
  - `less_than` - Trigger when price falls below threshold
266
282
  - `equals` - Trigger when price matches threshold exactly
@@ -269,6 +285,7 @@ if (result.success) {
269
285
 
270
286
  **Webhook Payload Example:**
271
287
  When an alert triggers, a POST request is sent to your webhook URL with:
288
+
272
289
  ```json
273
290
  {
274
291
  "event": "price_alert.triggered",
@@ -276,36 +293,247 @@ When an alert triggers, a POST request is sent to your webhook URL with:
276
293
  "alert_name": "Brent High Alert",
277
294
  "commodity_code": "BRENT_CRUDE_USD",
278
295
  "condition_operator": "greater_than",
279
- "condition_value": 85.00,
280
- "current_price": 86.50,
296
+ "condition_value": 85.0,
297
+ "current_price": 86.5,
281
298
  "triggered_at": "2025-12-15T14:30:00Z"
282
299
  }
283
300
  ```
284
301
 
285
302
  **Limits:**
303
+
286
304
  - Maximum 100 alerts per user
287
305
  - Cooldown period: 0-1440 minutes (24 hours)
288
306
  - Condition value: Must be between $0.01 and $1,000,000
289
307
  - Webhook URL: Must use HTTPS protocol
290
308
 
309
+ ### Commodities Metadata (New in v0.7.0)
310
+
311
+ ```typescript
312
+ // List all available commodities
313
+ const { commodities } = await client.commodities.list();
314
+ console.log(`${commodities.length} commodities available`);
315
+
316
+ // Get specific commodity details
317
+ const wti = await client.commodities.get("WTI_USD");
318
+ console.log(`${wti.name}: ${wti.description}`);
319
+ console.log(`Unit: ${wti.unit}, Currency: ${wti.currency}`);
320
+
321
+ // Get commodities by category
322
+ const categories = await client.commodities.categories();
323
+ console.log(`Oil category: ${categories.oil.commodities.length} commodities`);
324
+ ```
325
+
326
+ ### Futures Contracts (New in v0.7.0)
327
+
328
+ ```typescript
329
+ // Get latest futures price
330
+ const wti = await client.futures.latest("CL.1");
331
+ console.log(`WTI Front Month: $${wti.price}`);
332
+
333
+ // Get OHLC data
334
+ const ohlc = await client.futures.ohlc("CL.1", "2024-01-15");
335
+ console.log(`High: $${ohlc.high}, Low: $${ohlc.low}`);
336
+
337
+ // Get futures curve
338
+ const curve = await client.futures.curve("CL");
339
+ curve.curve.forEach((point) => {
340
+ console.log(`${point.months_out} months: $${point.price}`);
341
+ });
342
+ ```
343
+
344
+ ### Storage Levels (New in v0.7.0)
345
+
346
+ ```typescript
347
+ // Get total US crude storage
348
+ const storage = await client.storage.all();
349
+ console.log(`US inventory: ${storage.level} ${storage.unit}`);
350
+
351
+ // Get Cushing hub levels
352
+ const cushing = await client.storage.cushing();
353
+ console.log(`Cushing: ${cushing.level} ${cushing.unit}`);
354
+
355
+ // Get Strategic Petroleum Reserve
356
+ const spr = await client.storage.spr();
357
+ console.log(`SPR: ${spr.level} ${spr.unit}`);
358
+ ```
359
+
360
+ ### Rig Counts (New in v0.7.0)
361
+
362
+ ```typescript
363
+ // Get latest Baker Hughes rig count
364
+ const rigCounts = await client.rigCounts.latest();
365
+ console.log(`Total rigs: ${rigCounts.total}`);
366
+ console.log(`Oil: ${rigCounts.oil}, Gas: ${rigCounts.gas}`);
367
+
368
+ // Get summary with changes
369
+ const summary = await client.rigCounts.summary();
370
+ console.log(`Week-over-week: ${summary.week_change}`);
371
+ console.log(`Year-over-year: ${summary.year_change}`);
372
+ ```
373
+
374
+ ### Analytics (New in v0.7.0)
375
+
376
+ ```typescript
377
+ // Get performance metrics
378
+ const perf = await client.analytics.performance({
379
+ commodity: "WTI_USD",
380
+ days: 30,
381
+ });
382
+ console.log(`30-day return: ${perf.return_percent}%`);
383
+ console.log(`Volatility: ${perf.volatility}`);
384
+
385
+ // Analyze correlation between commodities
386
+ const corr = await client.analytics.correlation(
387
+ "WTI_USD",
388
+ "BRENT_CRUDE_USD",
389
+ 90,
390
+ );
391
+ console.log(`Correlation: ${corr.correlation} (${corr.strength})`);
392
+ ```
393
+
394
+ ### Drilling Intelligence (New in v0.7.0)
395
+
396
+ ```typescript
397
+ // Get latest drilling activity
398
+ const drilling = await client.drilling.latest();
399
+ console.log(`Active rigs: ${drilling.total_rigs}`);
400
+ console.log(`Frac spreads: ${drilling.total_frac_spreads}`);
401
+
402
+ // Get basin-specific data
403
+ const permian = await client.drilling.basin("Permian");
404
+ console.log(`Permian rigs: ${permian.active_rigs}`);
405
+ console.log(`DUC wells: ${permian.duc_wells}`);
406
+ ```
407
+
408
+ ### Energy Intelligence (New in v0.7.0)
409
+
410
+ Access comprehensive energy market intelligence from EIA, Baker Hughes, and FracFocus.
411
+
412
+ ```typescript
413
+ // Rig counts
414
+ const rigCounts = await client.ei.rigCounts.latest();
415
+ console.log(`Total rigs: ${rigCounts.total_rigs}`);
416
+
417
+ // Oil inventories
418
+ const inventories = await client.ei.oilInventories.latest();
419
+ console.log(`Crude stocks: ${inventories.level} ${inventories.unit}`);
420
+
421
+ // OPEC production
422
+ const opec = await client.ei.opecProduction.total();
423
+ console.log(`OPEC production: ${opec.total_production_bpd} bpd`);
424
+
425
+ // Well timeline
426
+ const timeline = await client.ei.wellTimeline("42-123-12345");
427
+ timeline.events.forEach((e) => {
428
+ console.log(`${e.date}: ${e.event_type}`);
429
+ });
430
+ ```
431
+
432
+ ### Webhooks (New in v0.7.0)
433
+
434
+ ```typescript
435
+ // Create a webhook
436
+ const webhook = await client.webhooks.create({
437
+ name: "Price Updates",
438
+ url: "https://myapp.com/webhooks/prices",
439
+ events: ["price.updated", "alert.triggered"],
440
+ enabled: true,
441
+ });
442
+
443
+ // Test the webhook
444
+ const test = await client.webhooks.test(webhook.id);
445
+ console.log(`Test ${test.success ? "passed" : "failed"}`);
446
+
447
+ // List all webhooks
448
+ const webhooks = await client.webhooks.list();
449
+ webhooks.forEach((wh) => {
450
+ console.log(`${wh.name}: ${wh.successful_deliveries} successful`);
451
+ });
452
+ ```
453
+
454
+ ### Bunker Fuels (New in v0.7.0)
455
+
456
+ ```typescript
457
+ // Get bunker fuel prices at all ports
458
+ const bunkerPrices = await client.bunkerFuels.all();
459
+ console.log(`${bunkerPrices.length} port prices available`);
460
+
461
+ // Get prices at specific port
462
+ const singapore = await client.bunkerFuels.port("SGSIN");
463
+ console.log(`Singapore VLSFO: $${singapore.prices.VLSFO}/MT`);
464
+
465
+ // Compare prices across ports
466
+ const comparison = await client.bunkerFuels.compare("VLSFO");
467
+ comparison.ports.forEach((p) => {
468
+ console.log(`${p.port_name}: $${p.price}/MT (rank ${p.rank})`);
469
+ });
470
+ ```
471
+
472
+ ### Forecasts (New in v0.7.0)
473
+
474
+ ```typescript
475
+ // Get monthly forecasts
476
+ const forecasts = await client.forecasts.monthly();
477
+ forecasts.forEach((f) => {
478
+ console.log(`${f.period}: $${f.forecast_price} (${f.source})`);
479
+ });
480
+
481
+ // Check forecast accuracy
482
+ const accuracy = await client.forecasts.accuracy();
483
+ console.log(`EIA MAPE: ${accuracy.mape}%`);
484
+
485
+ // Get specific forecast
486
+ const wtiQ2 = await client.forecasts.get({
487
+ commodity: "WTI_USD",
488
+ period: "2024-Q2",
489
+ });
490
+ console.log(`WTI Q2 forecast: $${wtiQ2.forecast_price}`);
491
+ ```
492
+
493
+ ### Data Sources (New in v0.7.0)
494
+
495
+ Manage custom data source integrations for Bring Your Own Source (BYOS).
496
+
497
+ ```typescript
498
+ // Create a data source
499
+ const source = await client.dataSources.create({
500
+ name: "Internal Pricing Database",
501
+ type: "database",
502
+ config: { host: "db.example.com", port: 5432 },
503
+ sync_frequency_minutes: 60,
504
+ });
505
+
506
+ // Test the connection
507
+ const test = await client.dataSources.test(source.id);
508
+ console.log(`Connection ${test.success ? "OK" : "failed"}`);
509
+
510
+ // View sync logs
511
+ const logs = await client.dataSources.logs(source.id);
512
+ logs.forEach((log) => {
513
+ console.log(
514
+ `${log.timestamp}: ${log.status} - ${log.records_synced} records`,
515
+ );
516
+ });
517
+ ```
518
+
291
519
  ### Advanced Configuration
292
520
 
293
521
  ```typescript
294
- import { OilPriceAPI } from 'oilpriceapi';
522
+ import { OilPriceAPI } from "oilpriceapi";
295
523
 
296
524
  const client = new OilPriceAPI({
297
- apiKey: 'your_key',
525
+ apiKey: "your_key",
298
526
 
299
527
  // Retry configuration
300
- retries: 3, // Max retry attempts (default: 3)
301
- retryDelay: 1000, // Initial delay in ms (default: 1000)
302
- retryStrategy: 'exponential', // 'exponential', 'linear', or 'fixed'
528
+ retries: 3, // Max retry attempts (default: 3)
529
+ retryDelay: 1000, // Initial delay in ms (default: 1000)
530
+ retryStrategy: "exponential", // 'exponential', 'linear', or 'fixed'
303
531
 
304
532
  // Timeout configuration
305
- timeout: 30000, // Request timeout in ms (default: 30000)
533
+ timeout: 30000, // Request timeout in ms (default: 30000)
306
534
 
307
535
  // Debug mode
308
- debug: true // Enable debug logging (default: false)
536
+ debug: true, // Enable debug logging (default: false)
309
537
  });
310
538
  ```
311
539
 
@@ -318,26 +546,30 @@ import {
318
546
  RateLimitError,
319
547
  NotFoundError,
320
548
  TimeoutError,
321
- ServerError
322
- } from 'oilpriceapi';
549
+ ServerError,
550
+ } from "oilpriceapi";
323
551
 
324
- const client = new OilPriceAPI({ apiKey: 'your_key' });
552
+ const client = new OilPriceAPI({ apiKey: "your_key" });
325
553
 
326
554
  try {
327
555
  const prices = await client.getLatestPrices();
328
556
  } catch (error) {
329
557
  if (error instanceof AuthenticationError) {
330
- console.error('Invalid API key:', error.message);
558
+ console.error("Invalid API key:", error.message);
331
559
  } else if (error instanceof RateLimitError) {
332
- console.error('Rate limit exceeded. Retry after:', error.retryAfter, 'seconds');
560
+ console.error(
561
+ "Rate limit exceeded. Retry after:",
562
+ error.retryAfter,
563
+ "seconds",
564
+ );
333
565
  } else if (error instanceof TimeoutError) {
334
- console.error('Request timed out:', error.message);
566
+ console.error("Request timed out:", error.message);
335
567
  } else if (error instanceof ServerError) {
336
- console.error('Server error:', error.statusCode, error.message);
568
+ console.error("Server error:", error.statusCode, error.message);
337
569
  } else if (error instanceof NotFoundError) {
338
- console.error('Commodity not found:', error.message);
570
+ console.error("Commodity not found:", error.message);
339
571
  } else {
340
- console.error('Unknown error:', error);
572
+ console.error("Unknown error:", error);
341
573
  }
342
574
  }
343
575
  ```
@@ -348,8 +580,8 @@ Enable debug logging to see detailed request/response information:
348
580
 
349
581
  ```typescript
350
582
  const client = new OilPriceAPI({
351
- apiKey: 'your_key',
352
- debug: true
583
+ apiKey: "your_key",
584
+ debug: true,
353
585
  });
354
586
 
355
587
  // This will log all requests, responses, retries, and errors
@@ -374,49 +606,54 @@ See the [`examples/`](./examples) directory for complete, runnable code examples
374
606
  ### Quick Examples
375
607
 
376
608
  **Get Latest Price:**
609
+
377
610
  ```typescript
378
- const prices = await client.getLatestPrices({ commodity: 'WTI_USD' });
611
+ const prices = await client.getLatestPrices({ commodity: "WTI_USD" });
379
612
  console.log(prices[0].formatted); // "$74.25"
380
613
  ```
381
614
 
382
615
  **Historical Data:**
616
+
383
617
  ```typescript
384
618
  const history = await client.getHistoricalPrices({
385
- commodity: 'BRENT_CRUDE_USD',
386
- period: 'past_week'
619
+ commodity: "BRENT_CRUDE_USD",
620
+ period: "past_week",
387
621
  });
388
622
  ```
389
623
 
390
624
  **Commodity Metadata:**
625
+
391
626
  ```typescript
392
627
  const { commodities } = await client.getCommodities();
393
628
  console.log(`Found ${commodities.length} commodities`);
394
629
  ```
395
630
 
396
631
  **Diesel Prices:**
632
+
397
633
  ```typescript
398
634
  // State average (free)
399
- const caPrice = await client.diesel.getPrice('CA');
635
+ const caPrice = await client.diesel.getPrice("CA");
400
636
  console.log(`CA diesel: $${caPrice.price}/gal`);
401
637
 
402
638
  // Nearby stations (paid tiers)
403
639
  const stations = await client.diesel.getStations({
404
640
  lat: 37.7749,
405
641
  lng: -122.4194,
406
- radius: 8047 // 5 miles
642
+ radius: 8047, // 5 miles
407
643
  });
408
644
  console.log(`Found ${stations.stations.length} stations`);
409
645
  ```
410
646
 
411
647
  **Price Alerts:**
648
+
412
649
  ```typescript
413
650
  // Create an alert
414
651
  const alert = await client.alerts.create({
415
- name: 'Brent High Alert',
416
- commodity_code: 'BRENT_CRUDE_USD',
417
- condition_operator: 'greater_than',
418
- condition_value: 85.00,
419
- webhook_url: 'https://your-app.com/webhook'
652
+ name: "Brent High Alert",
653
+ commodity_code: "BRENT_CRUDE_USD",
654
+ condition_operator: "greater_than",
655
+ condition_value: 85.0,
656
+ webhook_url: "https://your-app.com/webhook",
420
657
  });
421
658
 
422
659
  // List all alerts
@@ -426,13 +663,37 @@ const alerts = await client.alerts.list();
426
663
  await client.alerts.update(alert.id, { enabled: false });
427
664
  ```
428
665
 
666
+ **Futures & Storage:**
667
+
668
+ ```typescript
669
+ // Get WTI futures price
670
+ const wti = await client.futures.latest("CL.1");
671
+ console.log(`WTI: $${wti.price}`);
672
+
673
+ // Get Cushing storage
674
+ const cushing = await client.storage.cushing();
675
+ console.log(`Cushing: ${cushing.level} ${cushing.unit}`);
676
+ ```
677
+
678
+ **Analytics:**
679
+
680
+ ```typescript
681
+ // Get performance metrics
682
+ const perf = await client.analytics.performance({
683
+ commodity: "WTI_USD",
684
+ days: 30,
685
+ });
686
+ console.log(`30-day return: ${perf.return_percent}%`);
687
+ ```
688
+
429
689
  **Error Handling:**
690
+
430
691
  ```typescript
431
692
  try {
432
693
  const prices = await client.getLatestPrices();
433
694
  } catch (error) {
434
695
  if (error instanceof RateLimitError) {
435
- console.log('Rate limited, retry after:', error.retryAfter);
696
+ console.log("Rate limited, retry after:", error.retryAfter);
436
697
  }
437
698
  }
438
699
  ```
@@ -450,7 +711,8 @@ new OilPriceAPI(config: OilPriceAPIConfig)
450
711
  ```
451
712
 
452
713
  **Parameters:**
453
- - `config.apiKey` (string, required) - Your API key from https://www.oilpriceapi.com
714
+
715
+ - `config.apiKey` (string, required) - Your API key from https://www.oilpriceapi.com/signup
454
716
  - `config.baseUrl` (string, optional) - Custom API base URL (for testing)
455
717
 
456
718
  #### Methods
@@ -460,6 +722,7 @@ new OilPriceAPI(config: OilPriceAPIConfig)
460
722
  Get the latest prices for all commodities or a specific commodity.
461
723
 
462
724
  **Parameters:**
725
+
463
726
  - `options.commodity` (string, optional) - Filter by commodity code (e.g., "WTI_USD")
464
727
 
465
728
  **Returns:** `Promise<Price[]>`
@@ -469,6 +732,7 @@ Get the latest prices for all commodities or a specific commodity.
469
732
  Get historical prices for a time period.
470
733
 
471
734
  **Parameters:**
735
+
472
736
  - `options.period` (string, optional) - One of: "past_week", "past_month", "past_year"
473
737
  - `options.commodity` (string, optional) - Filter by commodity code
474
738
  - `options.startDate` (string, optional) - Start date in ISO 8601 format (YYYY-MM-DD)
@@ -496,6 +760,7 @@ Get all commodity categories with their commodities.
496
760
  Get metadata for a specific commodity by code.
497
761
 
498
762
  **Parameters:**
763
+
499
764
  - `code` (string, required) - Commodity code (e.g., "WTI_USD")
500
765
 
501
766
  **Returns:** `Promise<Commodity>` - Commodity metadata object
@@ -509,13 +774,15 @@ Resource for diesel price data (state averages and station-level pricing).
509
774
  Get average diesel price for a US state from EIA data.
510
775
 
511
776
  **Parameters:**
777
+
512
778
  - `state` (string, required) - Two-letter US state code (e.g., "CA", "TX", "NY")
513
779
 
514
780
  **Returns:** `Promise<DieselPrice>`
515
781
 
516
782
  **Example:**
783
+
517
784
  ```typescript
518
- const caPrice = await client.diesel.getPrice('CA');
785
+ const caPrice = await client.diesel.getPrice("CA");
519
786
  console.log(`California: $${caPrice.price}/gallon`);
520
787
  ```
521
788
 
@@ -524,6 +791,7 @@ console.log(`California: $${caPrice.price}/gallon`);
524
791
  Get nearby diesel stations with current pricing from Google Maps data.
525
792
 
526
793
  **Parameters:**
794
+
527
795
  - `options.lat` (number, required) - Latitude (-90 to 90)
528
796
  - `options.lng` (number, required) - Longitude (-180 to 180)
529
797
  - `options.radius` (number, optional) - Search radius in meters (default: 8047 = 5 miles, max: 50000)
@@ -533,18 +801,19 @@ Get nearby diesel stations with current pricing from Google Maps data.
533
801
  **Tier Requirements:** Available on paid tiers (Exploration and above)
534
802
 
535
803
  **Example:**
804
+
536
805
  ```typescript
537
806
  const result = await client.diesel.getStations({
538
807
  lat: 37.7749,
539
808
  lng: -122.4194,
540
- radius: 8047 // 5 miles
809
+ radius: 8047, // 5 miles
541
810
  });
542
811
 
543
812
  console.log(`Found ${result.stations.length} stations`);
544
813
  console.log(`Regional average: $${result.regional_average.price}/gallon`);
545
814
 
546
815
  const cheapest = result.stations.reduce((min, s) =>
547
- s.diesel_price < min.diesel_price ? s : min
816
+ s.diesel_price < min.diesel_price ? s : min,
548
817
  );
549
818
  console.log(`Cheapest: ${cheapest.name} at ${cheapest.formatted_price}`);
550
819
  ```
@@ -555,14 +824,14 @@ console.log(`Cheapest: ${cheapest.name} at ${cheapest.formatted_price}`);
555
824
 
556
825
  ```typescript
557
826
  interface Price {
558
- code: string; // Commodity code (e.g., "WTI_USD")
559
- name: string; // Human-readable name
560
- value: number; // Price value
561
- currency: string; // Currency code (e.g., "USD")
562
- unit: string; // Unit of measurement (e.g., "barrel")
563
- timestamp: string; // ISO 8601 timestamp
564
- created_at: string; // ISO 8601 timestamp
565
- updated_at: string; // ISO 8601 timestamp
827
+ code: string; // Commodity code (e.g., "WTI_USD")
828
+ name: string; // Human-readable name
829
+ value: number; // Price value
830
+ currency: string; // Currency code (e.g., "USD")
831
+ unit: string; // Unit of measurement (e.g., "barrel")
832
+ timestamp: string; // ISO 8601 timestamp
833
+ created_at: string; // ISO 8601 timestamp
834
+ updated_at: string; // ISO 8601 timestamp
566
835
  }
567
836
  ```
568
837
 
@@ -570,14 +839,14 @@ interface Price {
570
839
 
571
840
  ```typescript
572
841
  interface DieselPrice {
573
- state: string; // State code (e.g., "CA", "TX")
574
- price: number; // Average diesel price in USD per gallon
575
- currency: string; // Currency code (always "USD")
576
- unit: string; // Unit of measurement (always "gallon")
577
- granularity: string; // Level (e.g., "state", "national")
578
- source: string; // Data source (e.g., "EIA")
579
- updated_at: string; // ISO 8601 timestamp of last update
580
- cached?: boolean; // Whether served from cache
842
+ state: string; // State code (e.g., "CA", "TX")
843
+ price: number; // Average diesel price in USD per gallon
844
+ currency: string; // Currency code (always "USD")
845
+ unit: string; // Unit of measurement (always "gallon")
846
+ granularity: string; // Level (e.g., "state", "national")
847
+ source: string; // Data source (e.g., "EIA")
848
+ updated_at: string; // ISO 8601 timestamp of last update
849
+ cached?: boolean; // Whether served from cache
581
850
  }
582
851
  ```
583
852
 
@@ -585,20 +854,20 @@ interface DieselPrice {
585
854
 
586
855
  ```typescript
587
856
  interface DieselStation {
588
- name: string; // Station name
589
- address: string; // Full street address
857
+ name: string; // Station name
858
+ address: string; // Full street address
590
859
  location: {
591
- lat: number; // Latitude
592
- lng: number; // Longitude
860
+ lat: number; // Latitude
861
+ lng: number; // Longitude
593
862
  };
594
- diesel_price: number; // Price at this station (USD per gallon)
595
- formatted_price: string;// Formatted price (e.g., "$3.89")
596
- currency: string; // Currency code (always "USD")
597
- unit: string; // Unit (always "gallon")
598
- price_delta?: number; // Difference from regional average
863
+ diesel_price: number; // Price at this station (USD per gallon)
864
+ formatted_price: string; // Formatted price (e.g., "$3.89")
865
+ currency: string; // Currency code (always "USD")
866
+ unit: string; // Unit (always "gallon")
867
+ price_delta?: number; // Difference from regional average
599
868
  price_vs_average?: string; // Human-readable comparison
600
- fuel_types?: string[]; // Available fuel types
601
- last_updated?: string; // ISO 8601 timestamp
869
+ fuel_types?: string[]; // Available fuel types
870
+ last_updated?: string; // ISO 8601 timestamp
602
871
  }
603
872
  ```
604
873
 
@@ -607,28 +876,28 @@ interface DieselStation {
607
876
  ```typescript
608
877
  interface DieselStationsResponse {
609
878
  regional_average: {
610
- price: number; // Regional average price
611
- currency: string; // Currency code
612
- unit: string; // Unit
613
- region: string; // Region name
614
- granularity: string; // Granularity level
615
- source: string; // Data source
879
+ price: number; // Regional average price
880
+ currency: string; // Currency code
881
+ unit: string; // Unit
882
+ region: string; // Region name
883
+ granularity: string; // Granularity level
884
+ source: string; // Data source
616
885
  };
617
886
  stations: DieselStation[]; // List of nearby stations
618
887
  search_area: {
619
888
  center: {
620
- lat: number; // Search center latitude
621
- lng: number; // Search center longitude
889
+ lat: number; // Search center latitude
890
+ lng: number; // Search center longitude
622
891
  };
623
- radius_meters: number;// Search radius in meters
892
+ radius_meters: number; // Search radius in meters
624
893
  radius_miles: number; // Search radius in miles
625
894
  };
626
895
  metadata: {
627
896
  total_stations: number; // Number of stations found
628
- source: string; // Data source
629
- cached: boolean; // Whether served from cache
630
- api_cost: number; // Cost in dollars
631
- timestamp: string; // ISO 8601 timestamp
897
+ source: string; // Data source
898
+ cached: boolean; // Whether served from cache
899
+ api_cost: number; // Cost in dollars
900
+ timestamp: string; // ISO 8601 timestamp
632
901
  cache_age_hours?: number; // Cache age in hours
633
902
  };
634
903
  }
@@ -665,7 +934,7 @@ See the [full list of 79 commodities](https://www.oilpriceapi.com/commodities) i
665
934
  - **Business**: 200,000 requests/month - $199/mo
666
935
  - **Enterprise**: Custom limits - Contact us
667
936
 
668
- Get started with a free API key at [oilpriceapi.com](https://www.oilpriceapi.com).
937
+ Get started with a free API key at [oilpriceapi.com/signup](https://www.oilpriceapi.com/signup?utm_source=npm&utm_medium=sdk&utm_campaign=readme).
669
938
 
670
939
  ## Requirements
671
940
 
@@ -687,10 +956,9 @@ We welcome contributions! Please see our [Contributing Guide](https://github.com
687
956
 
688
957
  ## Support
689
958
 
690
- - 📧 Email: support@oilpriceapi.com
691
- - 🐛 Issues: [GitHub Issues](https://github.com/OilpriceAPI/oilpriceapi-node/issues)
692
- - 📚 Documentation: [oilpriceapi.com/docs](https://www.oilpriceapi.com/docs)
693
- - 💬 Discord: [Join our community](https://discord.gg/oilpriceapi)
959
+ - Email: support@oilpriceapi.com
960
+ - Issues: [GitHub Issues](https://github.com/OilpriceAPI/oilpriceapi-node/issues)
961
+ - Docs: [Documentation](https://docs.oilpriceapi.com)
694
962
 
695
963
  ## License
696
964
 
@@ -698,11 +966,38 @@ MIT License - see [LICENSE](LICENSE) file for details.
698
966
 
699
967
  ## Links
700
968
 
701
- - [Website](https://www.oilpriceapi.com)
702
- - [API Documentation](https://www.oilpriceapi.com/docs)
969
+ - [OilPriceAPI Website](https://www.oilpriceapi.com)
970
+ - [API Documentation](https://docs.oilpriceapi.com)
971
+ - [Pricing](https://www.oilpriceapi.com/pricing?utm_source=npm&utm_medium=sdk&utm_campaign=pricing)
972
+ - [Status Page](https://status.oilpriceapi.com)
703
973
  - [GitHub Repository](https://github.com/OilpriceAPI/oilpriceapi-node)
704
974
  - [npm Package](https://www.npmjs.com/package/oilpriceapi)
705
975
 
706
976
  ---
707
977
 
708
- Made with ❤️ by the Oil Price API team
978
+ ## Why OilPriceAPI?
979
+
980
+ [OilPriceAPI](https://www.oilpriceapi.com) provides professional-grade commodity price data at **98% less cost than Bloomberg Terminal** ($24,000/year vs $45/month). Trusted by energy traders, financial analysts, and developers worldwide.
981
+
982
+ ### Key Benefits
983
+
984
+ - **Real-time data** updated every 5 minutes
985
+ - **Historical data** for trend analysis and backtesting
986
+ - **99.9% uptime** with enterprise-grade reliability
987
+ - **5-minute integration** with this Node.js SDK
988
+ - **Free tier** with 100 requests to get started
989
+
990
+ **[Start Free](https://www.oilpriceapi.com/signup?utm_source=npm&utm_medium=sdk&utm_campaign=readme)** | **[View Pricing](https://www.oilpriceapi.com/pricing?utm_source=npm&utm_medium=sdk&utm_campaign=pricing)** | **[Read Docs](https://docs.oilpriceapi.com)**
991
+
992
+ ---
993
+
994
+ ## Also Available As
995
+
996
+ - **[Python SDK](https://pypi.org/project/oilpriceapi/)** - Python client with Pandas integration
997
+ - **[Go SDK](https://github.com/OilpriceAPI/oilpriceapi-go)** - Idiomatic Go client
998
+ - **[MCP Server](https://www.npmjs.com/package/oilpriceapi-mcp)** - Model Context Protocol server for Claude, Cursor, and VS Code
999
+ - **[Google Sheets Add-on](https://github.com/OilpriceAPI/google-sheets-addin)** - Custom functions for spreadsheets
1000
+
1001
+ ---
1002
+
1003
+ Made with care by the OilPriceAPI Team