oilpriceapi 0.8.2 → 0.9.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.
Files changed (53) hide show
  1. package/README.md +201 -19
  2. package/dist/cjs/client.js +139 -19
  3. package/dist/cjs/index.js +17 -3
  4. package/dist/cjs/resources/analytics.js +99 -137
  5. package/dist/cjs/resources/bunker-fuels.js +37 -23
  6. package/dist/cjs/resources/data-sources.js +13 -12
  7. package/dist/cjs/resources/ei/frac-focus.js +16 -6
  8. package/dist/cjs/resources/ei/well-permits.js +18 -6
  9. package/dist/cjs/resources/forecasts.js +11 -5
  10. package/dist/cjs/resources/futures.js +244 -16
  11. package/dist/cjs/resources/indicators.js +79 -0
  12. package/dist/cjs/resources/raw.js +128 -0
  13. package/dist/cjs/resources/rig-counts.js +5 -2
  14. package/dist/cjs/resources/spreads.js +105 -0
  15. package/dist/cjs/resources/storage.js +5 -5
  16. package/dist/cjs/resources/streaming.js +350 -0
  17. package/dist/cjs/resources/webhooks.js +3 -14
  18. package/dist/cjs/version.js +1 -1
  19. package/dist/client.d.ts +97 -1
  20. package/dist/client.js +139 -19
  21. package/dist/index.d.ts +12 -3
  22. package/dist/index.js +5 -0
  23. package/dist/resources/analytics.d.ts +147 -214
  24. package/dist/resources/analytics.js +99 -137
  25. package/dist/resources/bunker-fuels.d.ts +35 -12
  26. package/dist/resources/bunker-fuels.js +37 -23
  27. package/dist/resources/data-sources.d.ts +31 -31
  28. package/dist/resources/data-sources.js +13 -12
  29. package/dist/resources/ei/frac-focus.d.ts +23 -9
  30. package/dist/resources/ei/frac-focus.js +16 -6
  31. package/dist/resources/ei/well-permits.d.ts +25 -9
  32. package/dist/resources/ei/well-permits.js +18 -6
  33. package/dist/resources/forecasts.d.ts +4 -1
  34. package/dist/resources/forecasts.js +11 -5
  35. package/dist/resources/futures.d.ts +287 -33
  36. package/dist/resources/futures.js +241 -15
  37. package/dist/resources/indicators.d.ts +170 -0
  38. package/dist/resources/indicators.js +75 -0
  39. package/dist/resources/raw.d.ts +94 -0
  40. package/dist/resources/raw.js +124 -0
  41. package/dist/resources/rig-counts.js +5 -2
  42. package/dist/resources/spreads.d.ts +121 -0
  43. package/dist/resources/spreads.js +101 -0
  44. package/dist/resources/storage.d.ts +5 -4
  45. package/dist/resources/storage.js +5 -5
  46. package/dist/resources/streaming.d.ts +272 -0
  47. package/dist/resources/streaming.js +342 -0
  48. package/dist/resources/webhooks.d.ts +37 -23
  49. package/dist/resources/webhooks.js +3 -14
  50. package/dist/types.d.ts +41 -0
  51. package/dist/version.d.ts +1 -1
  52. package/dist/version.js +1 -1
  53. package/package.json +7 -1
@@ -4,6 +4,13 @@
4
4
  *
5
5
  * Access advanced analytics including performance metrics, statistical analysis,
6
6
  * correlations, trend detection, spreads, and forecasts.
7
+ *
8
+ * NOTE ON PARAMETERS: The OilPriceAPI analytics controller reads commodity
9
+ * identifiers as `code` / `code1` / `code2` and the lookback window as `period`
10
+ * (in days). Earlier versions of this SDK sent `commodity` / `commodity1` /
11
+ * `commodity2` / `days`, which the API silently ignored (and `correlation`
12
+ * returned "code1 and code2 parameters are required"). These methods now send
13
+ * the parameter names the controller actually reads.
7
14
  */
8
15
  Object.defineProperty(exports, "__esModule", { value: true });
9
16
  exports.AnalyticsResource = void 0;
@@ -20,13 +27,8 @@ const errors_js_1 = require("../errors.js");
20
27
  *
21
28
  * const client = new OilPriceAPI({ apiKey: 'your_key' });
22
29
  *
23
- * // Get performance metrics
24
- * const perf = await client.analytics.performance({ commodity: 'WTI_USD', days: 30 });
25
- * console.log(`30-day return: ${perf.return_percent}%`);
26
- * console.log(`Volatility: ${perf.volatility}`);
27
- *
28
- * // Analyze correlation
29
- * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', 90);
30
+ * // Analyze correlation between two commodities (90-day window)
31
+ * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', { period: 90 });
30
32
  * console.log(`Correlation: ${corr.correlation}`);
31
33
  * ```
32
34
  */
@@ -35,192 +37,152 @@ class AnalyticsResource {
35
37
  this.client = client;
36
38
  }
37
39
  /**
38
- * Get performance metrics for a commodity
39
- *
40
- * Returns key performance indicators including returns, volatility,
41
- * and price range over a specified period.
42
- *
43
- * @param options - Analysis parameters
44
- * @returns Performance metrics
40
+ * Get the authenticated user's API usage analytics for the dashboard.
45
41
  *
46
- * @throws {OilPriceAPIError} If API request fails
42
+ * Maps to `GET /v1/analytics/performance`, which reads a `range`
43
+ * parameter (`7d` | `30d` | `90d`).
47
44
  *
48
- * @example
49
- * ```typescript
50
- * const metrics = await client.analytics.performance({
51
- * commodity: 'WTI_USD',
52
- * days: 30
53
- * });
54
- * console.log(`Return: ${metrics.return_percent}%`);
55
- * console.log(`Volatility: ${metrics.volatility}`);
56
- * console.log(`High: $${metrics.high}, Low: $${metrics.low}`);
57
- * ```
45
+ * @param options - `{ range }` (default range '30d')
46
+ * @returns Usage analytics (overview, daily usage, endpoint breakdown, ...)
58
47
  */
59
48
  async performance(options) {
60
49
  const params = {};
61
- if (options?.commodity)
62
- params.commodity = options.commodity;
63
- if (options?.days)
64
- params.days = options.days.toString();
50
+ if (options?.range)
51
+ params.range = options.range;
65
52
  return this.client["request"]("/v1/analytics/performance", params);
66
53
  }
67
54
  /**
68
- * Get statistical analysis for a commodity
55
+ * Get statistical analysis for a commodity.
69
56
  *
70
- * Returns comprehensive statistical metrics including mean, median,
71
- * standard deviation, and distribution characteristics.
57
+ * Maps to `GET /v1/analytics/statistics`, which reads `code` and `period`.
72
58
  *
73
- * @param commodity - Commodity code to analyze
74
- * @param days - Number of days to analyze (default: 30)
59
+ * @param code - Commodity code to analyze (e.g. 'WTI_USD')
60
+ * @param period - Lookback window in days (default: 30)
75
61
  * @returns Statistical analysis
76
62
  *
77
- * @throws {NotFoundError} If commodity not found
78
- * @throws {OilPriceAPIError} If API request fails
79
- *
80
- * @example
81
- * ```typescript
82
- * const stats = await client.analytics.statistics('BRENT_CRUDE_USD', 90);
83
- * console.log(`Mean: $${stats.mean}`);
84
- * console.log(`Std Dev: ${stats.std_dev}`);
85
- * console.log(`Range: $${stats.min} - $${stats.max}`);
86
- * ```
63
+ * @throws {ValidationError} If code is empty
87
64
  */
88
- async statistics(commodity, days) {
89
- if (!commodity || typeof commodity !== "string") {
65
+ async statistics(code, period) {
66
+ if (!code || typeof code !== "string") {
90
67
  throw new errors_js_1.ValidationError("Commodity code must be a non-empty string");
91
68
  }
92
- const params = { commodity };
93
- if (days)
94
- params.days = days.toString();
69
+ const params = { code };
70
+ if (period !== undefined)
71
+ params.period = period.toString();
95
72
  return this.client["request"]("/v1/analytics/statistics", params);
96
73
  }
97
74
  /**
98
- * Analyze correlation between two commodities
75
+ * Analyze correlation between two commodities.
99
76
  *
100
- * Calculates the Pearson correlation coefficient to measure how closely
101
- * two commodities move together.
77
+ * Maps to `GET /v1/analytics/correlation`, which reads `code1`, `code2`,
78
+ * `period` and optional `type`, `window`, `codes`.
102
79
  *
103
- * @param commodity1 - First commodity code
104
- * @param commodity2 - Second commodity code
105
- * @param days - Number of days to analyze (default: 30)
80
+ * @param code1 - First commodity code
81
+ * @param code2 - Second commodity code
82
+ * @param options - Lookback window in days, or `{ period, type, window, codes }`
106
83
  * @returns Correlation analysis
107
84
  *
108
- * @throws {NotFoundError} If either commodity not found
109
- * @throws {OilPriceAPIError} If API request fails
85
+ * @throws {ValidationError} If either code is empty
110
86
  *
111
87
  * @example
112
88
  * ```typescript
113
- * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', 90);
114
- * console.log(`Correlation: ${corr.correlation}`);
115
- * console.log(`Strength: ${corr.strength}`);
116
- * console.log(`R-squared: ${corr.r_squared}`);
89
+ * const corr = await client.analytics.correlation('WTI_USD', 'BRENT_CRUDE_USD', { period: 90 });
90
+ * console.log(corr.correlation);
117
91
  * ```
118
92
  */
119
- async correlation(commodity1, commodity2, days) {
120
- if (!commodity1 || typeof commodity1 !== "string") {
93
+ async correlation(code1, code2, options) {
94
+ if (!code1 || typeof code1 !== "string") {
121
95
  throw new errors_js_1.ValidationError("First commodity code must be a non-empty string");
122
96
  }
123
- if (!commodity2 || typeof commodity2 !== "string") {
97
+ if (!code2 || typeof code2 !== "string") {
124
98
  throw new errors_js_1.ValidationError("Second commodity code must be a non-empty string");
125
99
  }
126
- const params = {
127
- commodity1,
128
- commodity2,
129
- };
130
- if (days)
131
- params.days = days.toString();
100
+ const opts = typeof options === "number" ? { period: options } : options || {};
101
+ const params = { code1, code2 };
102
+ if (opts.period !== undefined)
103
+ params.period = opts.period.toString();
104
+ if (opts.type)
105
+ params.type = opts.type;
106
+ if (opts.window !== undefined)
107
+ params.window = opts.window.toString();
108
+ if (opts.codes && opts.codes.length > 0)
109
+ params.codes = opts.codes.join(",");
132
110
  return this.client["request"]("/v1/analytics/correlation", params);
133
111
  }
134
112
  /**
135
- * Analyze price trend for a commodity
113
+ * Analyze price trend for a commodity.
136
114
  *
137
- * Detects trend direction, strength, and key levels (support/resistance).
115
+ * Maps to `GET /v1/analytics/trend`, which reads `code`, `period` and
116
+ * optional `type` ('analysis' | 'sma' | 'ema' | 'rsi' | 'levels') and `window`.
138
117
  *
139
- * @param commodity - Commodity code to analyze
140
- * @param days - Number of days to analyze (default: 30)
118
+ * @param code - Commodity code to analyze
119
+ * @param options - Lookback window in days, or `{ period, type, window }`
141
120
  * @returns Trend analysis
142
121
  *
143
- * @throws {NotFoundError} If commodity not found
144
- * @throws {OilPriceAPIError} If API request fails
145
- *
146
- * @example
147
- * ```typescript
148
- * const trend = await client.analytics.trend('WTI_USD', 60);
149
- * console.log(`Trend: ${trend.trend} (strength: ${trend.strength})`);
150
- * console.log(`Support: $${trend.support}`);
151
- * console.log(`Resistance: $${trend.resistance}`);
152
- * ```
122
+ * @throws {ValidationError} If code is empty
153
123
  */
154
- async trend(commodity, days) {
155
- if (!commodity || typeof commodity !== "string") {
124
+ async trend(code, options) {
125
+ if (!code || typeof code !== "string") {
156
126
  throw new errors_js_1.ValidationError("Commodity code must be a non-empty string");
157
127
  }
158
- const params = { commodity };
159
- if (days)
160
- params.days = days.toString();
128
+ const opts = typeof options === "number" ? { period: options } : options || {};
129
+ const params = { code };
130
+ if (opts.period !== undefined)
131
+ params.period = opts.period.toString();
132
+ if (opts.type)
133
+ params.type = opts.type;
134
+ if (opts.window !== undefined)
135
+ params.window = opts.window.toString();
161
136
  return this.client["request"]("/v1/analytics/trend", params);
162
137
  }
163
138
  /**
164
- * Analyze spread between two commodities
139
+ * Analyze a named commodity spread (basis / crack / ratio).
165
140
  *
166
- * Calculates current spread and compares to historical patterns.
141
+ * Maps to `GET /v1/analytics/spread`, which reads `spread` (the named spread,
142
+ * e.g. 'wti_brent'), `period` and optional `type` ('current' | 'historical').
143
+ * Call with no `spread` to list the available named spreads.
167
144
  *
168
- * @param commodity1 - First commodity code
169
- * @param commodity2 - Second commodity code
170
- * @returns Spread analysis
171
- *
172
- * @throws {NotFoundError} If either commodity not found
173
- * @throws {OilPriceAPIError} If API request fails
145
+ * @param spread - Named spread (e.g. 'wti_brent'); omit to list available spreads
146
+ * @param options - Lookback window in days, or `{ period, type }`
147
+ * @returns Spread analysis (or the list of available spreads)
174
148
  *
175
149
  * @example
176
150
  * ```typescript
177
- * const spread = await client.analytics.spread('BRENT_CRUDE_USD', 'WTI_USD');
178
- * console.log(`Current spread: $${spread.spread}`);
179
- * console.log(`Average spread: $${spread.average_spread}`);
180
- * console.log(`Z-score: ${spread.z_score}`);
151
+ * const spread = await client.analytics.spread('wti_brent', { period: 30 });
152
+ * console.log(spread.current_spread);
181
153
  * ```
182
154
  */
183
- async spread(commodity1, commodity2) {
184
- if (!commodity1 || typeof commodity1 !== "string") {
185
- throw new errors_js_1.ValidationError("First commodity code must be a non-empty string");
186
- }
187
- if (!commodity2 || typeof commodity2 !== "string") {
188
- throw new errors_js_1.ValidationError("Second commodity code must be a non-empty string");
189
- }
190
- return this.client["request"]("/v1/analytics/spread", {
191
- commodity1,
192
- commodity2,
193
- });
155
+ async spread(spread, options) {
156
+ const opts = typeof options === "number" ? { period: options } : options || {};
157
+ const params = {};
158
+ if (spread)
159
+ params.spread = spread;
160
+ if (opts.period !== undefined)
161
+ params.period = opts.period.toString();
162
+ if (opts.type)
163
+ params.type = opts.type;
164
+ return this.client["request"]("/v1/analytics/spread", params);
194
165
  }
195
166
  /**
196
- * Get price forecast for a commodity
197
- *
198
- * Returns forecasted prices with confidence intervals.
199
- *
200
- * @param commodity - Commodity code to forecast
201
- * @returns Price forecast
167
+ * Get a statistical price forecast for a commodity.
202
168
  *
203
- * @throws {NotFoundError} If commodity not found
204
- * @throws {OilPriceAPIError} If API request fails
169
+ * Maps to `GET /v1/analytics/forecast`, which reads `code`, `method`
170
+ * (default 'ema') and `period` (default 90). Call with no `code` to list
171
+ * the available forecast methods.
205
172
  *
206
- * @example
207
- * ```typescript
208
- * const forecast = await client.analytics.forecast('WTI_USD');
209
- * console.log(`Forecast model: ${forecast.model}`);
210
- * console.log(`Horizon: ${forecast.horizon_days} days`);
211
- *
212
- * forecast.forecast.forEach(point => {
213
- * console.log(`${point.date}: $${point.price} (${point.lower_bound}-${point.upper_bound})`);
214
- * });
215
- * ```
173
+ * @param code - Commodity code to forecast; omit to list available methods
174
+ * @param options - `{ method, period }`
175
+ * @returns Price forecast (or the list of available methods)
216
176
  */
217
- async forecast(commodity) {
218
- if (!commodity || typeof commodity !== "string") {
219
- throw new errors_js_1.ValidationError("Commodity code must be a non-empty string");
220
- }
221
- return this.client["request"]("/v1/analytics/forecast", {
222
- commodity,
223
- });
177
+ async forecast(code, options) {
178
+ const params = {};
179
+ if (code)
180
+ params.code = code;
181
+ if (options?.method)
182
+ params.method = options.method;
183
+ if (options?.period !== undefined)
184
+ params.period = options.period.toString();
185
+ return this.client["request"]("/v1/analytics/forecast", params);
224
186
  }
225
187
  }
226
188
  exports.AnalyticsResource = AnalyticsResource;
@@ -54,7 +54,8 @@ class BunkerFuelsResource {
54
54
  * ```
55
55
  */
56
56
  async all() {
57
- const response = await this.client["request"]("/v1/bunker-fuels", {});
57
+ // Route is GET /v1/bunker-fuels/all (the bare /v1/bunker-fuels has no route).
58
+ const response = await this.client["request"]("/v1/bunker-fuels/all", {});
58
59
  return Array.isArray(response) ? response : response.prices;
59
60
  }
60
61
  /**
@@ -107,24 +108,33 @@ class BunkerFuelsResource {
107
108
  });
108
109
  }
109
110
  /**
110
- * Get bunker fuel price spreads
111
+ * Get the bunker fuel price spread between two ports.
111
112
  *
112
- * Returns spreads between different fuel grades (e.g., VLSFO-IFO380).
113
+ * Maps to `GET /v1/bunker-fuels/spreads/ports`, which reads `from`, `to`
114
+ * and `grade`. (Earlier SDKs called `/v1/bunker-fuels/spreads` with no params,
115
+ * which 404'd.)
113
116
  *
114
- * @returns Fuel price spreads
117
+ * @param options - `{ from, to, grade? }`
118
+ * @returns Port-to-port fuel price spread
115
119
  *
116
- * @throws {OilPriceAPIError} If API request fails
120
+ * @throws {ValidationError} If from/to are missing
117
121
  *
118
122
  * @example
119
123
  * ```typescript
120
- * const spreads = await client.bunkerFuels.spreads();
121
- * spreads.spreads.forEach(spread => {
122
- * console.log(`${spread.fuel1}-${spread.fuel2} spread: $${spread.average_spread}`);
123
- * });
124
+ * const spread = await client.bunkerFuels.spreads({ from: 'SIN', to: 'RTM', grade: 'VLSFO' });
124
125
  * ```
125
126
  */
126
- async spreads() {
127
- return this.client["request"]("/v1/bunker-fuels/spreads", {});
127
+ async spreads(options) {
128
+ if (!options?.from || !options?.to) {
129
+ throw new errors_js_1.ValidationError("Both 'from' and 'to' port codes are required");
130
+ }
131
+ const params = {
132
+ from: options.from,
133
+ to: options.to,
134
+ };
135
+ if (options.grade)
136
+ params.grade = options.grade;
137
+ return this.client["request"]("/v1/bunker-fuels/spreads/ports", params);
128
138
  }
129
139
  /**
130
140
  * Get historical bunker fuel prices
@@ -137,9 +147,16 @@ class BunkerFuelsResource {
137
147
  * @throws {NotFoundError} If port or fuel type not found
138
148
  * @throws {OilPriceAPIError} If API request fails
139
149
  *
150
+ * The history endpoint is keyed by port in the PATH (`/historical/:port_code`)
151
+ * and returns all grades for that port; it does not filter by a single fuel
152
+ * type. It reads `from` / `to` / `interval` query params.
153
+ *
154
+ * @param port - Port code (e.g., "SIN", "RTM") — used as a path segment
155
+ * @param options - `{ startDate, endDate, interval }`
156
+ *
140
157
  * @example
141
158
  * ```typescript
142
- * const history = await client.bunkerFuels.historical('SIN', 'VLSFO', {
159
+ * const history = await client.bunkerFuels.historical('SIN', {
143
160
  * startDate: '2024-01-01',
144
161
  * endDate: '2024-12-31'
145
162
  * });
@@ -149,22 +166,19 @@ class BunkerFuelsResource {
149
166
  * });
150
167
  * ```
151
168
  */
152
- async historical(port, fuelType, options) {
169
+ async historical(port, options) {
153
170
  if (!port || typeof port !== "string") {
154
171
  throw new errors_js_1.ValidationError("Port code must be a non-empty string");
155
172
  }
156
- if (!fuelType || typeof fuelType !== "string") {
157
- throw new errors_js_1.ValidationError("Fuel type must be a non-empty string");
158
- }
159
- const params = {
160
- port,
161
- fuel_type: fuelType,
162
- };
173
+ const params = {};
163
174
  if (options?.startDate)
164
- params.start_date = options.startDate;
175
+ params.from = options.startDate;
165
176
  if (options?.endDate)
166
- params.end_date = options.endDate;
167
- const response = await this.client["request"]("/v1/bunker-fuels/historical", params);
177
+ params.to = options.endDate;
178
+ if (options?.interval)
179
+ params.interval = options.interval;
180
+ // Port code is a PATH segment: GET /v1/bunker-fuels/historical/:port_code
181
+ const response = await this.client["request"](`/v1/bunker-fuels/historical/${port}`, params);
168
182
  return Array.isArray(response) ? response : response.data;
169
183
  }
170
184
  /**
@@ -123,22 +123,18 @@ class DataSourcesResource {
123
123
  if (!params.name || typeof params.name !== "string") {
124
124
  throw new errors_js_1.ValidationError("Data source name is required");
125
125
  }
126
- if (!params.type) {
127
- throw new errors_js_1.ValidationError("Data source type is required");
128
- }
129
- if (!params.config || typeof params.config !== "object") {
130
- throw new errors_js_1.ValidationError("Data source config is required");
126
+ if (!params.source_type) {
127
+ throw new errors_js_1.ValidationError("Data source source_type is required");
131
128
  }
132
129
  const response = await this.client["request"]("/v1/data-sources", {}, {
133
130
  method: "POST",
134
131
  body: {
135
132
  data_source: {
136
133
  name: params.name,
137
- type: params.type,
138
- config: params.config,
139
- enabled: params.enabled ?? true,
140
- sync_frequency_minutes: params.sync_frequency_minutes ?? 60,
141
- metadata: params.metadata,
134
+ source_type: params.source_type,
135
+ status: params.status,
136
+ credentials: params.credentials,
137
+ scraper_config: params.scraper_config,
142
138
  },
143
139
  },
144
140
  });
@@ -287,11 +283,16 @@ class DataSourcesResource {
287
283
  * console.log(`Credential rotation: ${result.success ? 'success' : 'failed'}`);
288
284
  * ```
289
285
  */
290
- async rotateCredentials(id) {
286
+ async rotateCredentials(id, credentials) {
291
287
  if (!id || typeof id !== "string") {
292
288
  throw new errors_js_1.ValidationError("Data source ID must be a non-empty string");
293
289
  }
294
- return this.client["request"](`/v1/data-sources/${id}/rotate-credentials`, {}, { method: "POST" });
290
+ if (!credentials || typeof credentials !== "object") {
291
+ throw new errors_js_1.ValidationError("New credentials object is required");
292
+ }
293
+ // Route is POST /v1/data-sources/:id/rotate_credentials (underscore) and
294
+ // the controller does params.require(:credentials).
295
+ return this.client["request"](`/v1/data-sources/${id}/rotate_credentials`, {}, { method: "POST", body: { credentials } });
295
296
  }
296
297
  }
297
298
  exports.DataSourcesResource = DataSourcesResource;
@@ -112,12 +112,22 @@ class EIFracFocusResource {
112
112
  */
113
113
  async search(query) {
114
114
  const params = {};
115
- if (query.state)
116
- params.state = query.state;
117
- if (query.operator)
118
- params.operator = query.operator;
119
- if (query.chemical)
120
- params.chemical = query.chemical;
115
+ if (query.states)
116
+ params.states = query.states;
117
+ if (query.county)
118
+ params.county = query.county;
119
+ if (query.well_name)
120
+ params.well_name = query.well_name;
121
+ if (query.api_number)
122
+ params.api_number = query.api_number;
123
+ if (query.min_water_gallons !== undefined)
124
+ params.min_water_gallons = query.min_water_gallons.toString();
125
+ if (query.latitude !== undefined)
126
+ params.latitude = query.latitude.toString();
127
+ if (query.longitude !== undefined)
128
+ params.longitude = query.longitude.toString();
129
+ if (query.radius_miles !== undefined)
130
+ params.radius_miles = query.radius_miles.toString();
121
131
  if (query.start_date)
122
132
  params.start_date = query.start_date;
123
133
  if (query.end_date)
@@ -107,12 +107,24 @@ class EIWellPermitsResource {
107
107
  */
108
108
  async search(query) {
109
109
  const params = {};
110
- if (query.state)
111
- params.state = query.state;
112
- if (query.operator)
113
- params.operator = query.operator;
114
- if (query.formation)
115
- params.formation = query.formation;
110
+ if (query.states)
111
+ params.states = query.states;
112
+ if (query.county)
113
+ params.county = query.county;
114
+ if (query.well_name)
115
+ params.well_name = query.well_name;
116
+ if (query.permit_type)
117
+ params.permit_type = query.permit_type;
118
+ if (query.well_type)
119
+ params.well_type = query.well_type;
120
+ if (query.address)
121
+ params.address = query.address;
122
+ if (query.latitude !== undefined)
123
+ params.latitude = query.latitude.toString();
124
+ if (query.longitude !== undefined)
125
+ params.longitude = query.longitude.toString();
126
+ if (query.radius_miles !== undefined)
127
+ params.radius_miles = query.radius_miles.toString();
116
128
  if (query.start_date)
117
129
  params.start_date = query.start_date;
118
130
  if (query.end_date)
@@ -88,7 +88,8 @@ class ForecastsResource {
88
88
  * ```
89
89
  */
90
90
  async accuracy() {
91
- return this.client["request"]("/v1/forecasts/accuracy", {});
91
+ // Route is /v1/forecasts/monthly/accuracy (the bare /accuracy 404s).
92
+ return this.client["request"]("/v1/forecasts/monthly/accuracy", {});
92
93
  }
93
94
  /**
94
95
  * Get archived forecasts
@@ -119,11 +120,16 @@ class ForecastsResource {
119
120
  * });
120
121
  * ```
121
122
  */
122
- async archive(year) {
123
+ async archive(options) {
124
+ // Route is /v1/forecasts/monthly/archive (the bare /archive 404s). The
125
+ // controller reads only `page` / `per_page` — it does NOT filter by year,
126
+ // so the previous `year` argument was silently ignored.
123
127
  const params = {};
124
- if (year)
125
- params.year = year.toString();
126
- const response = await this.client["request"]("/v1/forecasts/archive", params);
128
+ if (options?.page !== undefined)
129
+ params.page = options.page.toString();
130
+ if (options?.perPage !== undefined)
131
+ params.per_page = options.perPage.toString();
132
+ const response = await this.client["request"]("/v1/forecasts/monthly/archive", params);
127
133
  return Array.isArray(response) ? response : response.forecasts;
128
134
  }
129
135
  /**