oilpriceapi 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.js CHANGED
@@ -1,4 +1,4 @@
1
- import { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, TimeoutError, } from "./errors.js";
1
+ import { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, TimeoutError, ValidationError, } from "./errors.js";
2
2
  import { DieselResource } from "./resources/diesel.js";
3
3
  import { AlertsResource } from "./resources/alerts.js";
4
4
  import { CommoditiesResource } from "./resources/commodities.js";
@@ -18,6 +18,7 @@ import { SpreadsResource } from "./resources/spreads.js";
18
18
  import { IndicatorsResource } from "./resources/indicators.js";
19
19
  import { RawResource } from "./resources/raw.js";
20
20
  import { StreamingResource } from "./resources/streaming.js";
21
+ import { SubscriptionsResource } from "./resources/subscriptions.js";
21
22
  /**
22
23
  * Official Node.js client for Oil Price API
23
24
  *
@@ -77,6 +78,7 @@ export class OilPriceAPI {
77
78
  this.indicators = new IndicatorsResource(this);
78
79
  this.raw = new RawResource(this);
79
80
  this.stream = new StreamingResource(this);
81
+ this.subscriptions = new SubscriptionsResource(this);
80
82
  }
81
83
  /**
82
84
  * Log debug messages if debug mode is enabled
@@ -212,6 +214,14 @@ export class OilPriceAPI {
212
214
  if (this.appName) {
213
215
  headers["X-App-Name"] = this.appName;
214
216
  }
217
+ // Per-request headers (e.g. MCP attribution X-OPA-Source / X-OPA-Tool).
218
+ if (options?.headers) {
219
+ Object.entries(options.headers).forEach(([key, value]) => {
220
+ if (value !== undefined && value !== null) {
221
+ headers[key] = value;
222
+ }
223
+ });
224
+ }
215
225
  const fetchOptions = {
216
226
  method: options?.method || "GET",
217
227
  headers,
@@ -521,6 +531,45 @@ export class OilPriceAPI {
521
531
  async getCommodity(code) {
522
532
  return this.request(`/v1/commodities/${code}`, {});
523
533
  }
534
+ /**
535
+ * Get a multi-commodity market brief (OilPriceAPI #3245 Phase 1a).
536
+ *
537
+ * Returns a structured summary (latest price, 24h change, freshness, and a
538
+ * 1-month forecast band) for each requested commodity, optionally with a
539
+ * natural-language narrative. Counts as a single request against your quota,
540
+ * like `/v1/prices/batch`. The per-tier cap on `codes` is enforced server-side.
541
+ *
542
+ * @param codes - Commodity codes (e.g. ["BRENT_CRUDE_USD", "WTI_USD"]). Shorthand
543
+ * codes like "WTI"/"BRENT" are accepted and resolved server-side.
544
+ * @param options - `{ narrative }` to request the natural-language summary.
545
+ * @returns The structured (and optional narrative) market brief.
546
+ *
547
+ * @throws {ValidationError} If `codes` is empty.
548
+ *
549
+ * @example
550
+ * ```typescript
551
+ * const brief = await client.getMarketBrief(['BRENT_CRUDE_USD', 'WTI_USD']);
552
+ * for (const c of brief.commodities) {
553
+ * console.log(`${c.name}: $${c.price} (${c.change_24h_pct}%)`);
554
+ * }
555
+ *
556
+ * // With narrative
557
+ * const withText = await client.getMarketBrief(['BRENT_CRUDE_USD'], { narrative: true });
558
+ * console.log(withText.narrative);
559
+ * ```
560
+ */
561
+ async getMarketBrief(codes, options) {
562
+ if (!Array.isArray(codes) || codes.length === 0) {
563
+ throw new ValidationError("codes is required and must be a non-empty array of commodity codes");
564
+ }
565
+ const params = {
566
+ codes: codes.join(","),
567
+ };
568
+ if (options?.narrative) {
569
+ params.narrative = "true";
570
+ }
571
+ return this.request("/v1/market-brief", params);
572
+ }
524
573
  /**
525
574
  * Fetch live sample prices from the public, no-auth demo endpoint.
526
575
  *
package/dist/index.d.ts CHANGED
@@ -26,6 +26,9 @@ export type { MonthlyForecast, ForecastAccuracy, ArchivedForecast } from "./reso
26
26
  export type { DataQualitySummary, DataQualityReportMeta, DataQualityReport, } from "./resources/data-quality.js";
27
27
  export type { DrillingIntelligenceData, LatestDrillingData, DrillingSummary, DrillingTrend, FracSpreadData, WellPermitData, DUCWellData, CompletionData, WellsDrilledData, BasinDrillingData, } from "./resources/drilling.js";
28
28
  export type { WellTimelineEvent, WellTimeline, RigCountRecord, RigCountByBasin, RigCountByState, HistoricalRigCount, OilInventoryRecord, OilInventorySummary, InventoryByProduct, HistoricalInventory, CushingInventory, OPECProductionRecord, TotalOPECProduction, ProductionByCountry, HistoricalProduction, TopProducer, DrillingProductivityRecord, DrillingProductivitySummary, DUCWellInventory, ProductivityByBasin, HistoricalProductivity, ProductivityTrend, ForecastRecord, ForecastSummary, PriceForecast, ProductionForecast, HistoricalForecast, ForecastComparison, WellPermitRecord, WellPermitSummary, PermitsByState, PermitsByOperator, PermitsByFormation, WellPermitSearchQuery, FracFocusRecord, FracFocusSummary, DisclosuresByState, DisclosuresByOperator, ChemicalUsage, WellChemical, FracFocusSearchQuery, } from "./resources/ei/index.js";
29
+ export type { MarketBrief, MarketBriefCommodity, MarketBriefForecast, MarketBriefOptions, } from "./resources/market-brief.js";
30
+ export type { Subscription, SubscriptionStatus, SubscriptionSource, SubscriptionInterval, CreateSubscriptionParams, SubscriptionEvent, SubscriptionEventsResult, SubscriptionEventsOptions, } from "./resources/subscriptions.js";
31
+ export { SubscriptionsResource, intervalToSeconds } from "./resources/subscriptions.js";
29
32
  export type { WebhookEndpoint, CreateWebhookParams, UpdateWebhookParams, WebhookTestResponse as WebhookTestResult, WebhookEvent, } from "./resources/webhooks.js";
30
33
  export type { DataSourceType, DataSourceStatus, DataSource, CreateDataSourceParams, UpdateDataSourceParams, DataSourceTestResponse, DataSourceLog, DataSourceHealth, CredentialRotationResponse, } from "./resources/data-sources.js";
31
34
  export { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, ValidationError, TimeoutError, } from "./errors.js";
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ export { FUTURES_CONTRACTS, FUTURES_FAMILY_SLUGS, FuturesContractFamily, } from
12
12
  export { SpreadsResource } from "./resources/spreads.js";
13
13
  export { IndicatorsResource } from "./resources/indicators.js";
14
14
  export { RawResource } from "./resources/raw.js";
15
+ export { SubscriptionsResource, intervalToSeconds } from "./resources/subscriptions.js";
15
16
  export { OilPriceAPIError, AuthenticationError, RateLimitError, NotFoundError, ServerError, ValidationError, TimeoutError, } from "./errors.js";
16
17
  export { DieselResource } from "./resources/diesel.js";
17
18
  export { AlertsResource } from "./resources/alerts.js";
@@ -6,23 +6,71 @@
6
6
  */
7
7
  import type { OilPriceAPI } from "../client.js";
8
8
  /**
9
- * Futures contract price data
9
+ * A single futures contract month within a {@link FuturesPrice} response.
10
+ *
11
+ * Returned at the top level under `front_month` and for every entry in
12
+ * `contracts[]`. The latest traded price is `last_price`.
13
+ */
14
+ export interface FuturesContractMonth {
15
+ /** Contract code (e.g. "BRENT_FUTURES_2026_08"). */
16
+ code?: string;
17
+ /** Contract month in YYYY-MM form (e.g. "2026-08"). */
18
+ contract_month?: string;
19
+ /** Latest traded/settlement price for this contract month. */
20
+ last_price?: number;
21
+ /** Currency code (e.g. "USD"). */
22
+ currency?: string;
23
+ /** Opening price (may be returned as a string by the API). */
24
+ open?: number | string;
25
+ /** Closing price (may be returned as a string by the API). */
26
+ close?: number | string;
27
+ /** Session high. */
28
+ high?: number | string;
29
+ /** Session low. */
30
+ low?: number | string;
31
+ /** Any additional fields the API returns for a contract month. */
32
+ [key: string]: unknown;
33
+ }
34
+ /**
35
+ * Futures contract price data.
36
+ *
37
+ * `GET /v1/futures/{slug}` returns a TOP-LEVEL object (there is NO
38
+ * `{ status, data }` envelope). The latest price lives at
39
+ * `front_month.last_price`, with the full term structure in `contracts[]`.
40
+ *
41
+ * Legacy flat fields (`contract`, `price`, `currency`, `timestamp`) are kept
42
+ * optional for backward compatibility, but real responses populate
43
+ * `front_month` / `contracts` instead.
10
44
  */
11
45
  export interface FuturesPrice {
12
- /** Contract symbol */
13
- contract: string;
14
- /** Current price */
15
- price: number;
16
- /** Formatted price string */
46
+ /** Commodity identifier (e.g. "BRENT_FUTURES"). */
47
+ commodity?: string;
48
+ /** Data source (e.g. "ICE"). */
49
+ source?: string;
50
+ /** ISO timestamp the data was last updated. */
51
+ updated_at?: string;
52
+ /** Settlement date for the prices. */
53
+ settlement_date?: string;
54
+ /** Front-month contract — the latest price is `front_month.last_price`. */
55
+ front_month?: FuturesContractMonth;
56
+ /** Full forward term structure, one entry per contract month. */
57
+ contracts?: FuturesContractMonth[];
58
+ /** Optional warning when the returned data is stale. */
59
+ data_age_warning?: unknown;
60
+ /** Additional metadata returned by the API. */
61
+ metadata?: Record<string, unknown>;
62
+ /** @deprecated Legacy flat contract symbol — use `front_month.code`. */
63
+ contract?: string;
64
+ /** @deprecated Legacy flat price — use `front_month.last_price`. */
65
+ price?: number;
66
+ /** @deprecated Legacy formatted price string. */
17
67
  formatted?: string;
18
- /** Currency code */
19
- currency: string;
20
- /** Contract expiration date */
68
+ /** @deprecated Legacy currency — use `front_month.currency`. */
69
+ currency?: string;
70
+ /** @deprecated Legacy contract expiration date. */
21
71
  expiration?: string;
22
- /** ISO timestamp when price was recorded */
23
- timestamp: string;
24
- /** Additional metadata */
25
- metadata?: Record<string, unknown>;
72
+ /** @deprecated Legacy ISO timestamp use `updated_at`. */
73
+ timestamp?: string;
26
74
  }
27
75
  /**
28
76
  * Historical futures price data
@@ -141,15 +189,25 @@ export interface FuturesCurvePoint {
141
189
  contract?: string;
142
190
  }
143
191
  /**
144
- * Futures curve data
192
+ * Futures curve data.
193
+ *
194
+ * `GET /v1/futures/{slug}/curve` can legitimately return a no-data response of
195
+ * the form `{ error: "No futures data available for curve analysis", date }`
196
+ * when a curve cannot be built. That is a valid state (not an HTTP error), so
197
+ * `curve` is optional and `error` / `date` are surfaced for callers to detect
198
+ * the no-data case.
145
199
  */
146
200
  export interface FuturesCurveData {
147
201
  /** Base contract */
148
- contract: string;
202
+ contract?: string;
149
203
  /** ISO timestamp when curve was generated */
150
- timestamp: string;
151
- /** Array of curve points */
152
- curve: FuturesCurvePoint[];
204
+ timestamp?: string;
205
+ /** Array of curve points (absent in the no-data response) */
206
+ curve?: FuturesCurvePoint[];
207
+ /** Present in the no-data response: "No futures data available for curve analysis". */
208
+ error?: string;
209
+ /** Date associated with the no-data response. */
210
+ date?: string;
153
211
  }
154
212
  /**
155
213
  * Continuous contract data point
@@ -196,9 +254,10 @@ export interface FuturesSpreadHistory {
196
254
  /**
197
255
  * Slugs for the supported ICE / gas / carbon futures contract families.
198
256
  *
199
- * These map to the `GET /v1/futures/{slug}/...` endpoints. Each family
200
- * supports `/latest`, `/historical`, `/ohlc`, `/intraday`, `/spreads`,
201
- * `/curve`, and `/spread-history`.
257
+ * These map to the `GET /v1/futures/{slug}` (latest) endpoint plus the
258
+ * `GET /v1/futures/{slug}/...` sub-resources. Latest is the bare slug path
259
+ * (there is NO `/latest` suffix). Each family also supports `/historical`,
260
+ * `/ohlc`, `/intraday`, `/spreads`, `/curve`, and `/spread-history`.
202
261
  */
203
262
  export type FuturesContractFamilySlug = "ice-brent" | "ice-gasoil" | "ice-wti" | "natural-gas" | "ttf-gas" | "lng-jkm" | "eua-carbon" | "uk-carbon";
204
263
  /**
@@ -241,6 +300,14 @@ export declare const FUTURES_CONTRACTS: {
241
300
  * path segment used by the typed family helpers.
242
301
  */
243
302
  export declare const FUTURES_FAMILY_SLUGS: Record<string, FuturesContractFamilySlug>;
303
+ /**
304
+ * Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
305
+ * family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
306
+ *
307
+ * Matching is case-insensitive for codes. Returns `null` if the input maps to
308
+ * neither a known code nor a known family slug.
309
+ */
310
+ export declare function resolveFuturesFamilySlug(codeOrSlug: string): FuturesContractFamilySlug | null;
244
311
  /**
245
312
  * Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
246
313
  *
@@ -264,6 +331,9 @@ export declare class FuturesContractFamily {
264
331
  slug: FuturesContractFamilySlug);
265
332
  /**
266
333
  * Get the latest price for this contract family.
334
+ *
335
+ * Latest is served from the bare slug path `GET /v1/futures/{slug}` —
336
+ * there is NO `/latest` suffix (that path 404s).
267
337
  */
268
338
  latest(): Promise<FuturesPrice>;
269
339
  /**
@@ -307,16 +377,13 @@ export declare class FuturesContractFamily {
307
377
  *
308
378
  * const client = new OilPriceAPI({ apiKey: 'your_key' });
309
379
  *
310
- * // Get latest price
311
- * const latest = await client.futures.latest('CL.1');
380
+ * // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
381
+ * const latest = await client.futures.latest('CL');
312
382
  * console.log(`${latest.contract}: $${latest.price}`);
313
383
  *
314
- * // Get OHLC data
315
- * const ohlc = await client.futures.ohlc('CL.1', '2024-01-15');
316
- * console.log(`High: $${ohlc.high}, Low: $${ohlc.low}`);
317
- *
318
- * // Get futures curve
319
- * const curve = await client.futures.curve('CL');
384
+ * // Typed family helpers are the most ergonomic option:
385
+ * const brent = await client.futures.brent().latest();
386
+ * const curve = await client.futures.brent().curve();
320
387
  * curve.curve.forEach(point => {
321
388
  * console.log(`${point.months_out}mo: $${point.price}`);
322
389
  * });
@@ -326,18 +393,28 @@ export declare class FuturesResource {
326
393
  private client;
327
394
  constructor(client: OilPriceAPI);
328
395
  /**
329
- * Get latest price for a futures contract
396
+ * Get the latest curve/quote for a futures contract family.
330
397
  *
331
- * @param contract - Contract symbol (e.g., "CL.1", "BZ.2")
332
- * @returns Latest futures price data
398
+ * Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
399
+ * family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
400
+ * and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
401
+ * with NO `/latest` suffix (the suffixed path 404s).
333
402
  *
334
- * @throws {NotFoundError} If contract not found
403
+ * Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
404
+ * TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
405
+ * ttf-gas, lng-jkm, eua-carbon, uk-carbon.
406
+ *
407
+ * @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
408
+ * @returns Latest futures price/curve data
409
+ *
410
+ * @throws {ValidationError} If the code/slug is empty or unrecognized.
335
411
  * @throws {OilPriceAPIError} If API request fails
336
412
  *
337
413
  * @example
338
414
  * ```typescript
339
- * const price = await client.futures.latest('CL.1');
340
- * console.log(`WTI Front Month: $${price.price}`);
415
+ * import { FUTURES_CONTRACTS } from 'oilpriceapi';
416
+ * const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
417
+ * const wti = await client.futures.latest('ice-wti');
341
418
  * ```
342
419
  */
343
420
  latest(contract: string): Promise<FuturesPrice>;
@@ -45,15 +45,34 @@ export const FUTURES_CONTRACTS = {
45
45
  * path segment used by the typed family helpers.
46
46
  */
47
47
  export const FUTURES_FAMILY_SLUGS = {
48
- [FUTURES_CONTRACTS.BRENT]: "ice-brent",
49
- [FUTURES_CONTRACTS.WTI]: "ice-wti",
50
- [FUTURES_CONTRACTS.GASOIL]: "ice-gasoil",
51
- [FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas",
52
- [FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas",
53
- [FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm",
54
- [FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon",
55
- [FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon",
48
+ [FUTURES_CONTRACTS.BRENT]: "ice-brent", // BZ
49
+ [FUTURES_CONTRACTS.WTI]: "ice-wti", // CL
50
+ [FUTURES_CONTRACTS.GASOIL]: "ice-gasoil", // G
51
+ QS: "ice-gasoil", // ICE Gasoil also trades under the QS ticker prefix
52
+ [FUTURES_CONTRACTS.NATURAL_GAS]: "natural-gas", // NG
53
+ [FUTURES_CONTRACTS.TTF_GAS]: "ttf-gas", // TTF
54
+ [FUTURES_CONTRACTS.LNG_JKM]: "lng-jkm", // JKM
55
+ [FUTURES_CONTRACTS.EUA_CARBON]: "eua-carbon", // EUA
56
+ [FUTURES_CONTRACTS.UK_CARBON]: "uk-carbon", // UKA
56
57
  };
58
+ /**
59
+ * Resolve a futures contract code (e.g. `"BZ"`, `"QS"`) or an already-valid
60
+ * family slug (e.g. `"ice-brent"`) to its `/v1/futures/{slug}` path segment.
61
+ *
62
+ * Matching is case-insensitive for codes. Returns `null` if the input maps to
63
+ * neither a known code nor a known family slug.
64
+ */
65
+ export function resolveFuturesFamilySlug(codeOrSlug) {
66
+ const trimmed = codeOrSlug.trim();
67
+ // Direct code match (case-insensitive — codes are upper-case).
68
+ const byCode = FUTURES_FAMILY_SLUGS[trimmed.toUpperCase()];
69
+ if (byCode)
70
+ return byCode;
71
+ // Already a valid family slug?
72
+ const lower = trimmed.toLowerCase();
73
+ const isSlug = Object.values(FUTURES_FAMILY_SLUGS).includes(lower);
74
+ return isSlug ? lower : null;
75
+ }
57
76
  /**
58
77
  * Typed helper for a single futures contract family (e.g., ICE Brent, Gasoil).
59
78
  *
@@ -77,9 +96,12 @@ export class FuturesContractFamily {
77
96
  }
78
97
  /**
79
98
  * Get the latest price for this contract family.
99
+ *
100
+ * Latest is served from the bare slug path `GET /v1/futures/{slug}` —
101
+ * there is NO `/latest` suffix (that path 404s).
80
102
  */
81
103
  async latest() {
82
- return this.client["request"](`/v1/futures/${this.slug}/latest`, {});
104
+ return this.client["request"](`/v1/futures/${this.slug}`, {});
83
105
  }
84
106
  /**
85
107
  * Get historical prices for this contract family.
@@ -152,16 +174,13 @@ export class FuturesContractFamily {
152
174
  *
153
175
  * const client = new OilPriceAPI({ apiKey: 'your_key' });
154
176
  *
155
- * // Get latest price
156
- * const latest = await client.futures.latest('CL.1');
177
+ * // Get the latest curve by contract code (resolves to GET /v1/futures/ice-wti)
178
+ * const latest = await client.futures.latest('CL');
157
179
  * console.log(`${latest.contract}: $${latest.price}`);
158
180
  *
159
- * // Get OHLC data
160
- * const ohlc = await client.futures.ohlc('CL.1', '2024-01-15');
161
- * console.log(`High: $${ohlc.high}, Low: $${ohlc.low}`);
162
- *
163
- * // Get futures curve
164
- * const curve = await client.futures.curve('CL');
181
+ * // Typed family helpers are the most ergonomic option:
182
+ * const brent = await client.futures.brent().latest();
183
+ * const curve = await client.futures.brent().curve();
165
184
  * curve.curve.forEach(point => {
166
185
  * console.log(`${point.months_out}mo: $${point.price}`);
167
186
  * });
@@ -172,25 +191,42 @@ export class FuturesResource {
172
191
  this.client = client;
173
192
  }
174
193
  /**
175
- * Get latest price for a futures contract
194
+ * Get the latest curve/quote for a futures contract family.
176
195
  *
177
- * @param contract - Contract symbol (e.g., "CL.1", "BZ.2")
178
- * @returns Latest futures price data
196
+ * Accepts an ergonomic contract code (e.g. `"BZ"`, `"CL"`, `"QS"`) or a
197
+ * family slug (e.g. `"ice-brent"`). The code is resolved to its family slug
198
+ * and the request is sent to `GET /v1/futures/{slug}` — the bare slug path,
199
+ * with NO `/latest` suffix (the suffixed path 404s).
179
200
  *
180
- * @throws {NotFoundError} If contract not found
201
+ * Supported codes: BZ (Brent), CL (WTI), G/QS (Gasoil), NG (Natural Gas),
202
+ * TTF, JKM, EUA, UKA. Slugs: ice-brent, ice-wti, ice-gasoil, natural-gas,
203
+ * ttf-gas, lng-jkm, eua-carbon, uk-carbon.
204
+ *
205
+ * @param contract - Contract code (e.g. "BZ") or family slug (e.g. "ice-brent").
206
+ * @returns Latest futures price/curve data
207
+ *
208
+ * @throws {ValidationError} If the code/slug is empty or unrecognized.
181
209
  * @throws {OilPriceAPIError} If API request fails
182
210
  *
183
211
  * @example
184
212
  * ```typescript
185
- * const price = await client.futures.latest('CL.1');
186
- * console.log(`WTI Front Month: $${price.price}`);
213
+ * import { FUTURES_CONTRACTS } from 'oilpriceapi';
214
+ * const price = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
215
+ * const wti = await client.futures.latest('ice-wti');
187
216
  * ```
188
217
  */
189
218
  async latest(contract) {
190
219
  if (!contract || typeof contract !== "string") {
191
220
  throw new ValidationError("Contract symbol must be a non-empty string");
192
221
  }
193
- return this.client["request"](`/v1/futures/${contract}`, {});
222
+ const slug = resolveFuturesFamilySlug(contract);
223
+ if (!slug) {
224
+ throw new ValidationError(`Unknown futures contract "${contract}". Use a contract code ` +
225
+ `(BZ, CL, G, QS, NG, TTF, JKM, EUA, UKA) or a family slug ` +
226
+ `(ice-brent, ice-wti, ice-gasoil, natural-gas, ttf-gas, lng-jkm, ` +
227
+ `eua-carbon, uk-carbon).`);
228
+ }
229
+ return this.client["request"](`/v1/futures/${slug}`, {});
194
230
  }
195
231
  /**
196
232
  * Get historical prices for a futures contract
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Market Brief types (OilPriceAPI #3245 Phase 1a)
3
+ *
4
+ * A multi-commodity structured (+ optional narrative) market summary composed
5
+ * from existing price + forecast data. Served by `GET /v1/market-brief` and
6
+ * surfaced on the client as {@link OilPriceAPI.getMarketBrief}.
7
+ */
8
+ /**
9
+ * Short-horizon (1-month) point forecast for a commodity in a market brief.
10
+ */
11
+ export interface MarketBriefForecast {
12
+ /** Central point estimate. */
13
+ point: number;
14
+ /** Low end of the forecast band. */
15
+ low: number;
16
+ /** High end of the forecast band. */
17
+ high: number;
18
+ /** Model confidence label (e.g. "low", "medium", "high"). */
19
+ confidence: string;
20
+ }
21
+ /**
22
+ * One commodity's slice of a market brief.
23
+ */
24
+ export interface MarketBriefCommodity {
25
+ /** Commodity code (e.g. "BRENT_CRUDE_USD"). */
26
+ code: string;
27
+ /** Human-readable commodity name. */
28
+ name: string;
29
+ /** Latest price. */
30
+ price: number;
31
+ /** ISO currency code (e.g. "USD"). */
32
+ currency: string;
33
+ /** Price unit (e.g. "barrel"). */
34
+ unit: string;
35
+ /** 24h percentage change. */
36
+ change_24h_pct: number;
37
+ /** 24h absolute change. */
38
+ change_24h_abs: number;
39
+ /** ISO timestamp the price was observed. */
40
+ as_of: string;
41
+ /** Upstream data source. */
42
+ source: string;
43
+ /** True when the price is stale (no fresh update). */
44
+ stale: boolean;
45
+ /** 1-month forecast band, when available. */
46
+ forecast_1m: MarketBriefForecast | null;
47
+ }
48
+ /**
49
+ * A multi-commodity market brief.
50
+ *
51
+ * Returned by {@link OilPriceAPI.getMarketBrief}.
52
+ */
53
+ export interface MarketBrief {
54
+ /** ISO timestamp the brief was generated. */
55
+ as_of: string;
56
+ /** The (resolved, canonical) codes included in the brief. */
57
+ codes: string[];
58
+ /** Per-commodity structured summary. */
59
+ commodities: MarketBriefCommodity[];
60
+ /** Optional natural-language narrative (only when `narrative: true`). */
61
+ narrative?: string;
62
+ }
63
+ /**
64
+ * Options for {@link OilPriceAPI.getMarketBrief}.
65
+ */
66
+ export interface MarketBriefOptions {
67
+ /**
68
+ * Request a natural-language narrative alongside the structured data.
69
+ * Defaults to `false`.
70
+ */
71
+ narrative?: boolean;
72
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Market Brief types (OilPriceAPI #3245 Phase 1a)
3
+ *
4
+ * A multi-commodity structured (+ optional narrative) market summary composed
5
+ * from existing price + forecast data. Served by `GET /v1/market-brief` and
6
+ * surfaced on the client as {@link OilPriceAPI.getMarketBrief}.
7
+ */
8
+ export {};
@@ -4,7 +4,7 @@
4
4
  * Real-time price streaming via the OilPriceAPI ActionCable endpoint
5
5
  * (`wss://api.oilpriceapi.com/cable`).
6
6
  *
7
- * Streaming is a **Reservoir Mastery (Professional+)** feature. Connections
7
+ * Streaming is a **Professional plan ($99/mo) or higher** feature. Connections
8
8
  * authenticate with your API key and subscribe to the `EnergyPricesChannel`,
9
9
  * which pushes an initial `welcome` snapshot followed by live `price_update`
10
10
  * and (for drilling-tier accounts) `rig_count_update` messages.
@@ -105,7 +105,7 @@ export interface WelcomeMessage {
105
105
  };
106
106
  }
107
107
  /**
108
- * Rig-count update broadcast (drilling / Reservoir Mastery accounts).
108
+ * Rig-count update broadcast (drilling / Professional+ accounts).
109
109
  */
110
110
  export interface RigCountUpdateMessage {
111
111
  type: "rig_count_update";
@@ -4,7 +4,7 @@
4
4
  * Real-time price streaming via the OilPriceAPI ActionCable endpoint
5
5
  * (`wss://api.oilpriceapi.com/cable`).
6
6
  *
7
- * Streaming is a **Reservoir Mastery (Professional+)** feature. Connections
7
+ * Streaming is a **Professional plan ($99/mo) or higher** feature. Connections
8
8
  * authenticate with your API key and subscribe to the `EnergyPricesChannel`,
9
9
  * which pushes an initial `welcome` snapshot followed by live `price_update`
10
10
  * and (for drilling-tier accounts) `rig_count_update` messages.
@@ -157,8 +157,8 @@ export class PriceStreamSubscription extends EventEmitter {
157
157
  return;
158
158
  }
159
159
  if (transportType === "reject_subscription") {
160
- this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a Reservoir Mastery " +
161
- "(Professional+) plan and a valid API key."));
160
+ this.emit("error", new Error("WebSocket subscription rejected. Streaming requires a Professional " +
161
+ "plan ($99/mo) or higher and a valid API key."));
162
162
  return;
163
163
  }
164
164
  if (transportType === "disconnect") {