oilpriceapi 0.7.0 → 0.9.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.
Files changed (81) hide show
  1. package/README.md +244 -30
  2. package/dist/cjs/client.js +610 -0
  3. package/dist/cjs/errors.js +80 -0
  4. package/dist/cjs/index.js +96 -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 +188 -0
  8. package/dist/cjs/resources/bunker-fuels.js +210 -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 +298 -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 +165 -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 +136 -0
  22. package/dist/cjs/resources/forecasts.js +168 -0
  23. package/dist/cjs/resources/futures.js +424 -0
  24. package/dist/cjs/resources/indicators.js +79 -0
  25. package/dist/cjs/resources/raw.js +128 -0
  26. package/dist/cjs/resources/rig-counts.js +164 -0
  27. package/dist/cjs/resources/spreads.js +105 -0
  28. package/dist/cjs/resources/storage.js +166 -0
  29. package/dist/cjs/resources/streaming.js +350 -0
  30. package/dist/cjs/resources/webhooks.js +283 -0
  31. package/dist/cjs/types.js +2 -0
  32. package/dist/cjs/version.js +24 -0
  33. package/dist/client.d.ts +130 -3
  34. package/dist/client.js +206 -30
  35. package/dist/errors.d.ts +6 -0
  36. package/dist/errors.js +25 -16
  37. package/dist/index.d.ts +28 -5
  38. package/dist/index.js +29 -1
  39. package/dist/resources/alerts.js +31 -77
  40. package/dist/resources/analytics.d.ts +147 -214
  41. package/dist/resources/analytics.js +104 -141
  42. package/dist/resources/bunker-fuels.d.ts +35 -12
  43. package/dist/resources/bunker-fuels.js +41 -26
  44. package/dist/resources/commodities.js +2 -1
  45. package/dist/resources/data-quality.js +2 -1
  46. package/dist/resources/data-sources.d.ts +31 -31
  47. package/dist/resources/data-sources.js +30 -85
  48. package/dist/resources/diesel.d.ts +1 -1
  49. package/dist/resources/diesel.js +9 -38
  50. package/dist/resources/drilling.js +2 -1
  51. package/dist/resources/ei/drilling-productivity.js +2 -1
  52. package/dist/resources/ei/forecasts.js +2 -1
  53. package/dist/resources/ei/frac-focus.d.ts +23 -9
  54. package/dist/resources/ei/frac-focus.js +20 -9
  55. package/dist/resources/ei/index.js +2 -1
  56. package/dist/resources/ei/oil-inventories.js +2 -1
  57. package/dist/resources/ei/opec-production.js +2 -1
  58. package/dist/resources/ei/rig-counts.js +2 -1
  59. package/dist/resources/ei/well-permits.d.ts +25 -9
  60. package/dist/resources/ei/well-permits.js +20 -7
  61. package/dist/resources/forecasts.d.ts +4 -1
  62. package/dist/resources/forecasts.js +13 -6
  63. package/dist/resources/futures.d.ts +178 -1
  64. package/dist/resources/futures.js +199 -8
  65. package/dist/resources/indicators.d.ts +170 -0
  66. package/dist/resources/indicators.js +75 -0
  67. package/dist/resources/raw.d.ts +94 -0
  68. package/dist/resources/raw.js +124 -0
  69. package/dist/resources/rig-counts.js +5 -2
  70. package/dist/resources/spreads.d.ts +121 -0
  71. package/dist/resources/spreads.js +101 -0
  72. package/dist/resources/storage.d.ts +5 -4
  73. package/dist/resources/storage.js +7 -6
  74. package/dist/resources/streaming.d.ts +272 -0
  75. package/dist/resources/streaming.js +342 -0
  76. package/dist/resources/webhooks.d.ts +73 -23
  77. package/dist/resources/webhooks.js +59 -77
  78. package/dist/types.d.ts +43 -1
  79. package/dist/version.d.ts +1 -1
  80. package/dist/version.js +2 -2
  81. package/package.json +21 -6
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
 
@@ -19,6 +25,7 @@ Official Node.js SDK for [Oil Price API](https://www.oilpriceapi.com) - Get real
19
25
  - ⛽ **NEW v0.4.0** - Diesel prices (state averages + station-level pricing)
20
26
  - 🔔 **NEW v0.5.0** - Price alerts with webhook notifications
21
27
  - 📊 **NEW v0.7.0** - Futures, storage, rig counts, analytics, drilling intelligence, webhooks, and energy intelligence
28
+ - 🧰 **NEW** - Typed ICE Brent / Gasoil / WTI & gas/carbon futures helpers, `spreads`, `indicators`, and raw HTTP responses (`client.raw.*` with status + headers)
22
29
 
23
30
  ## Installation
24
31
 
@@ -33,7 +40,7 @@ import { OilPriceAPI } from "oilpriceapi";
33
40
 
34
41
  // Initialize the client
35
42
  const client = new OilPriceAPI({
36
- apiKey: "your_api_key_here", // Get your free key at https://www.oilpriceapi.com
43
+ apiKey: "your_api_key_here", // Get your free key at https://www.oilpriceapi.com/signup
37
44
  retries: 3, // Automatic retries (default: 3)
38
45
  timeout: 30000, // Request timeout in ms (default: 30000)
39
46
  });
@@ -261,9 +268,7 @@ console.log("Alert deleted successfully");
261
268
  const result = await client.alerts.testWebhook("https://your-app.com/webhook");
262
269
 
263
270
  if (result.success) {
264
- console.log(
265
- `Webhook OK (${result.status_code}) - ${result.response_time_ms}ms`,
266
- );
271
+ console.log(`Webhook OK (${result.status_code}) - ${result.response_time_ms}ms`);
267
272
  } else {
268
273
  console.error(`Webhook failed: ${result.error}`);
269
274
  }
@@ -335,6 +340,138 @@ curve.curve.forEach((point) => {
335
340
  });
336
341
  ```
337
342
 
343
+ #### Typed contract-family helpers (ICE Brent, Gasoil, WTI, gas & carbon)
344
+
345
+ The generic `futures.*` methods take raw contract codes. For the most-requested
346
+ families you can use ergonomic, typed helpers that map to the
347
+ `/v1/futures/{family}/...` endpoints — no need to remember URL slugs. Each
348
+ family supports `latest`, `historical`, `ohlc`, `intraday`, `spreads`, `curve`,
349
+ and `spreadHistory`.
350
+
351
+ ```typescript
352
+ import { OilPriceAPI, FUTURES_CONTRACTS } from "oilpriceapi";
353
+
354
+ const client = new OilPriceAPI({ apiKey: "your_key" });
355
+
356
+ // ICE Brent
357
+ const brent = await client.futures.brent().latest();
358
+ console.log(`Brent: $${brent.price}`);
359
+
360
+ // ICE Gasoil
361
+ const gasoil = await client.futures.gasoil().curve();
362
+
363
+ // ICE WTI
364
+ const wti = await client.futures.wti().ohlc("2024-01-15");
365
+
366
+ // Natural gas families
367
+ await client.futures.naturalGas().latest(); // Henry Hub
368
+ await client.futures.ttfGas().historical({ startDate: "2024-01-01" }); // TTF (Europe)
369
+ await client.futures.lngJkm().spreads(); // LNG JKM (Asia)
370
+
371
+ // Carbon
372
+ await client.futures.euaCarbon().latest(); // EU carbon allowance
373
+ await client.futures.ukCarbon().spreadHistory(); // UK carbon allowance
374
+
375
+ // Or address a family by slug
376
+ const fam = client.futures.family("ice-brent");
377
+ await fam.intraday();
378
+
379
+ // Ergonomic contract-code constants for the generic methods
380
+ const brentLatest = await client.futures.latest(FUTURES_CONTRACTS.BRENT); // "BZ"
381
+ const gasoilCode = FUTURES_CONTRACTS.GASOIL; // "G"
382
+ ```
383
+
384
+ Available families: `ice-brent`, `ice-gasoil`, `ice-wti`, `natural-gas`,
385
+ `ttf-gas`, `lng-jkm`, `eua-carbon`, `uk-carbon`.
386
+
387
+ ### Spreads
388
+
389
+ Crack spreads, basis differentials, curve structure (contango/backwardation),
390
+ refining margins, and physical premiums. Each spread type supports the latest
391
+ value, full history, and an `all` listing
392
+ (`/v1/spreads/{type}`, `/v1/spreads/{type}/historical`, `/v1/spreads/{type}/all`).
393
+
394
+ ```typescript
395
+ // Latest values via named helpers
396
+ const crack = await client.spreads.crack();
397
+ console.log(`Crack spread: ${crack.value} ${crack.unit}`);
398
+
399
+ await client.spreads.basis();
400
+ await client.spreads.curveStructure();
401
+ await client.spreads.margin();
402
+ await client.spreads.physicalPremium();
403
+
404
+ // Or address a type directly
405
+ const margin = await client.spreads.get("margin");
406
+
407
+ // Historical spread series
408
+ const history = await client.spreads.historical("basis", {
409
+ startDate: "2024-01-01",
410
+ endDate: "2024-12-31",
411
+ });
412
+
413
+ // All values for a spread type
414
+ const allCrack = await client.spreads.all("crack");
415
+ ```
416
+
417
+ ### Indicators
418
+
419
+ Derived market indicators and signals: fuel-switching economics, price context,
420
+ storage analytics, market annotations, CFTC positioning, and congressional
421
+ energy-sector trades (`/v1/indicators/{type}`).
422
+
423
+ ```typescript
424
+ // Fuel-switching economics
425
+ const fs = await client.indicators.fuelSwitching();
426
+ console.log(`Switching economical: ${fs.economical}`);
427
+
428
+ // Where the current price sits historically
429
+ const ctx = await client.indicators.priceContext();
430
+ console.log(`Percentile: ${ctx.percentile}`);
431
+
432
+ // Storage analytics
433
+ await client.indicators.storageAnalytics();
434
+
435
+ // Market annotations (notable events)
436
+ const annotations = await client.indicators.annotations();
437
+
438
+ // CFTC positioning (Commitment of Traders)
439
+ const cftc = await client.indicators.cftcPositioning();
440
+ cftc.forEach((p) => console.log(`${p.market}: net ${p.net_position}`));
441
+
442
+ // Congressional energy-sector trades
443
+ const trades = await client.indicators.congressionalTrades();
444
+
445
+ // Or address a type directly
446
+ const custom = await client.indicators.get("price-context");
447
+ ```
448
+
449
+ ### Raw HTTP responses (status + headers)
450
+
451
+ By default the SDK returns just the parsed data. When you also need the
452
+ underlying HTTP status code and response headers (e.g. rate-limit headers),
453
+ use the `client.raw.*` accessor. It returns `{ data, status, headers }` while
454
+ `data` keeps the exact same shape as the equivalent non-raw method.
455
+
456
+ ```typescript
457
+ const { data, status, headers } = await client.raw.getLatestPrices({
458
+ commodity: "WTI_USD",
459
+ });
460
+
461
+ console.log(`HTTP ${status}`);
462
+ console.log(`Rate limit remaining: ${headers.get("x-ratelimit-remaining")}`);
463
+ console.log(`Price: ${data[0].price}`);
464
+
465
+ // Also available: getHistoricalPrices, getCommodities,
466
+ // getCommodityCategories, getCommodity
467
+ const commodities = await client.raw.getCommodities();
468
+ console.log(commodities.status, commodities.headers.get("content-type"));
469
+
470
+ // Generic raw GET for any endpoint without a dedicated helper
471
+ const futures = await client.raw.get("/v1/futures/CL.1");
472
+ console.log(futures.status, futures.data);
473
+ ```
474
+
338
475
  ### Storage Levels (New in v0.7.0)
339
476
 
340
477
  ```typescript
@@ -377,11 +514,7 @@ console.log(`30-day return: ${perf.return_percent}%`);
377
514
  console.log(`Volatility: ${perf.volatility}`);
378
515
 
379
516
  // Analyze correlation between commodities
380
- const corr = await client.analytics.correlation(
381
- "WTI_USD",
382
- "BRENT_CRUDE_USD",
383
- 90,
384
- );
517
+ const corr = await client.analytics.correlation("WTI_USD", "BRENT_CRUDE_USD", 90);
385
518
  console.log(`Correlation: ${corr.correlation} (${corr.strength})`);
386
519
  ```
387
520
 
@@ -504,12 +637,73 @@ console.log(`Connection ${test.success ? "OK" : "failed"}`);
504
637
  // View sync logs
505
638
  const logs = await client.dataSources.logs(source.id);
506
639
  logs.forEach((log) => {
507
- console.log(
508
- `${log.timestamp}: ${log.status} - ${log.records_synced} records`,
509
- );
640
+ console.log(`${log.timestamp}: ${log.status} - ${log.records_synced} records`);
510
641
  });
511
642
  ```
512
643
 
644
+ ### Real-time Streaming (WebSocket)
645
+
646
+ Stream live price updates over a persistent WebSocket connection instead of
647
+ polling. Streaming uses the server's ActionCable `/cable` endpoint and the
648
+ `EnergyPricesChannel`, and is available on the **Reservoir Mastery
649
+ (Professional+)** plan.
650
+
651
+ The `client.stream.prices()` method returns a subscription handle (an
652
+ `EventEmitter`). It performs the ActionCable handshake, answers server pings,
653
+ auto-reconnects with exponential backoff, and surfaces typed events. Call
654
+ `.close()` for a clean teardown.
655
+
656
+ ```typescript
657
+ import { OilPriceAPI } from "oilpriceapi";
658
+
659
+ const client = new OilPriceAPI({ apiKey: process.env.OILPRICEAPI_KEY });
660
+
661
+ // Optional onUpdate callback fires on every live price_update.
662
+ const sub = client.stream.prices(
663
+ { commodities: ["WTI_USD", "BRENT_CRUDE_USD"] }, // optional client-side filter
664
+ (update) => {
665
+ const wti = update.prices.oil.wti;
666
+ if (wti) {
667
+ console.log(`WTI ${wti.original_price} ${wti.original_currency} @ ${update.timestamp}`);
668
+ }
669
+ },
670
+ );
671
+
672
+ // Lifecycle + typed events
673
+ sub.on("connected", () => console.log("subscription confirmed"));
674
+ sub.on("welcome", (snapshot) => console.log("initial snapshot", snapshot.data));
675
+ sub.on("price_update", (update) => console.log("oil:", update.prices.oil));
676
+ sub.on("rig_count_update", (m) => console.log(`${m.rig_count.region}: ${m.rig_count.count} rigs`));
677
+ sub.on("reconnecting", ({ attempt, delay }) => console.log(`reconnect #${attempt} in ${delay}ms`));
678
+ sub.on("disconnected", ({ code }) => console.log("socket closed", code));
679
+ sub.on("error", (err) => console.error("stream error:", err.message));
680
+
681
+ // Clean teardown (unsubscribe + close socket)
682
+ process.on("SIGINT", () => {
683
+ sub.close();
684
+ process.exit(0);
685
+ });
686
+ ```
687
+
688
+ **Events emitted by the subscription handle:**
689
+
690
+ | Event | Payload | Description |
691
+ | ------------------ | ----------------------- | ------------------------------------------------------ |
692
+ | `connected` | — | Channel subscription confirmed by the server |
693
+ | `welcome` | `WelcomeMessage` | Initial price snapshot sent on subscribe |
694
+ | `price_update` | `PriceUpdateMessage` | Live price broadcast (oil + natural gas) |
695
+ | `rig_count_update` | `RigCountUpdateMessage` | Drilling rig-count broadcast (drilling-tier accounts) |
696
+ | `message` | `StreamMessage` | Every decoded channel message (incl. unknown types) |
697
+ | `reconnecting` | `{ attempt, delay }` | A reconnect attempt has been scheduled |
698
+ | `disconnected` | `{ code, reason }` | The transport closed |
699
+ | `error` | `Error` | Transport error, rejected subscription, or retries out |
700
+ | `close` | — | The subscription was closed via `.close()` |
701
+
702
+ **Options** (`StreamPricesOptions`): `commodities`, `autoReconnect`,
703
+ `reconnectDelay`, `maxReconnectDelay`, `maxReconnectAttempts`.
704
+
705
+ See [`examples/streaming.ts`](./examples/streaming.ts) for a complete runnable example.
706
+
513
707
  ### Advanced Configuration
514
708
 
515
709
  ```typescript
@@ -551,11 +745,7 @@ try {
551
745
  if (error instanceof AuthenticationError) {
552
746
  console.error("Invalid API key:", error.message);
553
747
  } else if (error instanceof RateLimitError) {
554
- console.error(
555
- "Rate limit exceeded. Retry after:",
556
- error.retryAfter,
557
- "seconds",
558
- );
748
+ console.error("Rate limit exceeded. Retry after:", error.retryAfter, "seconds");
559
749
  } else if (error instanceof TimeoutError) {
560
750
  console.error("Request timed out:", error.message);
561
751
  } else if (error instanceof ServerError) {
@@ -706,7 +896,7 @@ new OilPriceAPI(config: OilPriceAPIConfig)
706
896
 
707
897
  **Parameters:**
708
898
 
709
- - `config.apiKey` (string, required) - Your API key from https://www.oilpriceapi.com
899
+ - `config.apiKey` (string, required) - Your API key from https://www.oilpriceapi.com/signup
710
900
  - `config.baseUrl` (string, optional) - Custom API base URL (for testing)
711
901
 
712
902
  #### Methods
@@ -806,9 +996,7 @@ const result = await client.diesel.getStations({
806
996
  console.log(`Found ${result.stations.length} stations`);
807
997
  console.log(`Regional average: $${result.regional_average.price}/gallon`);
808
998
 
809
- const cheapest = result.stations.reduce((min, s) =>
810
- s.diesel_price < min.diesel_price ? s : min,
811
- );
999
+ const cheapest = result.stations.reduce((min, s) => (s.diesel_price < min.diesel_price ? s : min));
812
1000
  console.log(`Cheapest: ${cheapest.name} at ${cheapest.formatted_price}`);
813
1001
  ```
814
1002
 
@@ -928,7 +1116,7 @@ See the [full list of 79 commodities](https://www.oilpriceapi.com/commodities) i
928
1116
  - **Business**: 200,000 requests/month - $199/mo
929
1117
  - **Enterprise**: Custom limits - Contact us
930
1118
 
931
- Get started with a free API key at [oilpriceapi.com](https://www.oilpriceapi.com).
1119
+ 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).
932
1120
 
933
1121
  ## Requirements
934
1122
 
@@ -950,10 +1138,9 @@ We welcome contributions! Please see our [Contributing Guide](https://github.com
950
1138
 
951
1139
  ## Support
952
1140
 
953
- - 📧 Email: support@oilpriceapi.com
954
- - 🐛 Issues: [GitHub Issues](https://github.com/OilpriceAPI/oilpriceapi-node/issues)
955
- - 📚 Documentation: [oilpriceapi.com/docs](https://www.oilpriceapi.com/docs)
956
- - 💬 Discord: [Join our community](https://discord.gg/oilpriceapi)
1141
+ - Email: support@oilpriceapi.com
1142
+ - Issues: [GitHub Issues](https://github.com/OilpriceAPI/oilpriceapi-node/issues)
1143
+ - Docs: [Documentation](https://docs.oilpriceapi.com)
957
1144
 
958
1145
  ## License
959
1146
 
@@ -961,11 +1148,38 @@ MIT License - see [LICENSE](LICENSE) file for details.
961
1148
 
962
1149
  ## Links
963
1150
 
964
- - [Website](https://www.oilpriceapi.com)
965
- - [API Documentation](https://www.oilpriceapi.com/docs)
1151
+ - [OilPriceAPI Website](https://www.oilpriceapi.com)
1152
+ - [API Documentation](https://docs.oilpriceapi.com)
1153
+ - [Pricing](https://www.oilpriceapi.com/pricing?utm_source=npm&utm_medium=sdk&utm_campaign=pricing)
1154
+ - [Status Page](https://status.oilpriceapi.com)
966
1155
  - [GitHub Repository](https://github.com/OilpriceAPI/oilpriceapi-node)
967
1156
  - [npm Package](https://www.npmjs.com/package/oilpriceapi)
968
1157
 
969
1158
  ---
970
1159
 
971
- Made with ❤️ by the Oil Price API team
1160
+ ## Why OilPriceAPI?
1161
+
1162
+ [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.
1163
+
1164
+ ### Key Benefits
1165
+
1166
+ - **Real-time data** updated every 5 minutes
1167
+ - **Historical data** for trend analysis and backtesting
1168
+ - **99.9% uptime** with enterprise-grade reliability
1169
+ - **5-minute integration** with this Node.js SDK
1170
+ - **Free tier** with 100 requests to get started
1171
+
1172
+ **[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)**
1173
+
1174
+ ---
1175
+
1176
+ ## Also Available As
1177
+
1178
+ - **[Python SDK](https://pypi.org/project/oilpriceapi/)** - Python client with Pandas integration
1179
+ - **[Go SDK](https://github.com/OilpriceAPI/oilpriceapi-go)** - Idiomatic Go client
1180
+ - **[MCP Server](https://www.npmjs.com/package/oilpriceapi-mcp)** - Model Context Protocol server for Claude, Cursor, and VS Code
1181
+ - **[Google Sheets Add-on](https://github.com/OilpriceAPI/google-sheets-addin)** - Custom functions for spreadsheets
1182
+
1183
+ ---
1184
+
1185
+ Made with care by the OilPriceAPI Team