C# / .NET Integration Guide
Integrate OilPriceAPI into your .NET applications to access real-time crude oil prices, Brent crude data, natural gas rates, and commodity market information for enterprise energy applications.
Requirements
- .NET 6.0 or higher (also compatible with .NET Framework 4.7.2+)
- System.Text.Json or Newtonsoft.Json
Installation
Using NuGet Package Manager:
dotnet add package System.Text.Json
# Optional: for more flexible JSON handling
dotnet add package Newtonsoft.Json
Quick Start
using System.Net.Http;
using System.Text.Json;
var apiKey = Environment.GetEnvironmentVariable("OILPRICE_API_KEY");
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Token {apiKey}");
var response = await client.GetAsync(
"https://api.oilpriceapi.com/v1/prices/latest?by_code=WTI_USD"
);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Complete API Client Class
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace OilPriceAPI
{
public class PriceData
{
[JsonPropertyName("price")]
public decimal Price { get; set; }
[JsonPropertyName("formatted")]
public string Formatted { get; set; }
[JsonPropertyName("currency")]
public string Currency { get; set; }
[JsonPropertyName("code")]
public string Code { get; set; }
[JsonPropertyName("created_at")]
public DateTime CreatedAt { get; set; }
}
public class PriceResponse
{
[JsonPropertyName("status")]
public string Status { get; set; }
[JsonPropertyName("data")]
public Dictionary<string, PriceData> Data { get; set; }
}
public class HistoricalResponse
{
[JsonPropertyName("status")]
public string Status { get; set; }
[JsonPropertyName("data")]
public List<PriceData> Data { get; set; }
}
public class OilPriceAPIException : Exception
{
public int StatusCode { get; }
public OilPriceAPIException(string message, int statusCode = 0)
: base(message)
{
StatusCode = statusCode;
}
}
public class RateLimitException : OilPriceAPIException
{
public RateLimitException() : base("Rate limit exceeded", 429) { }
}
public class AuthenticationException : OilPriceAPIException
{
public AuthenticationException() : base("Invalid API key", 401) { }
}
public class OilPriceClient : IDisposable
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl = "https://api.oilpriceapi.com/v1";
private readonly JsonSerializerOptions _jsonOptions;
public OilPriceClient(string apiKey = null)
{
apiKey ??= Environment.GetEnvironmentVariable("OILPRICE_API_KEY");
if (string.IsNullOrEmpty(apiKey))
throw new ArgumentException("API key is required");
_httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Token {apiKey}");
_httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
_jsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
}
private async Task<T> RequestAsync<T>(string endpoint, Dictionary<string, string> parameters = null)
{
var url = $"{_baseUrl}{endpoint}";
if (parameters?.Count > 0)
{
var queryString = string.Join("&",
parameters.Select(p => $"{p.Key}={Uri.EscapeDataString(p.Value)}"));
url = $"{url}?{queryString}";
}
var response = await _httpClient.GetAsync(url);
switch ((int)response.StatusCode)
{
case 401:
throw new AuthenticationException();
case 429:
throw new RateLimitException();
case int code when code >= 400:
throw new OilPriceAPIException($"API error: {response.StatusCode}", code);
}
var content = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<T>(content, _jsonOptions);
}
public async Task<PriceResponse> GetLatestPricesAsync(params string[] codes)
{
var parameters = new Dictionary<string, string>
{
{ "by_code", string.Join(",", codes) }
};
return await RequestAsync<PriceResponse>("/prices/latest", parameters);
}
public async Task<HistoricalResponse> GetHistoricalPricesAsync(string code, int days = 7)
{
var parameters = new Dictionary<string, string>
{
{ "by_code", code }
};
return await RequestAsync<HistoricalResponse>($"/prices/past_{days}_days", parameters);
}
public void Dispose()
{
_httpClient?.Dispose();
}
}
}
Usage Examples
Fetch Multiple Commodities
using OilPriceAPI;
using var client = new OilPriceClient();
// Get multiple oil prices
var prices = await client.GetLatestPricesAsync(
"WTI_USD", "BRENT_CRUDE_USD", "NATURAL_GAS_USD"
);
foreach (var (code, data) in prices.Data)
{
Console.WriteLine($"{code}: {data.Formatted}");
}
Historical Price Analysis
using OilPriceAPI;
using var client = new OilPriceClient();
// Get past week of WTI prices
var history = await client.GetHistoricalPricesAsync("WTI_USD", days: 7);
Console.WriteLine("WTI Price History:");
foreach (var point in history.Data)
{
Console.WriteLine($" {point.CreatedAt:yyyy-MM-dd}: ${point.Price:F2}");
}
// Calculate statistics
var prices = history.Data.Select(p => p.Price).ToList();
var average = prices.Average();
var min = prices.Min();
var max = prices.Max();
Console.WriteLine($"\nStatistics:");
Console.WriteLine($" Average: ${average:F2}");
Console.WriteLine($" Range: ${min:F2} - ${max:F2}");
ASP.NET Core Integration
// Program.cs
builder.Services.AddSingleton<OilPriceClient>(sp =>
new OilPriceClient(builder.Configuration["OilPriceAPI:ApiKey"])
);
// appsettings.json
{
"OilPriceAPI": {
"ApiKey": "${OILPRICE_API_KEY}"
}
}
// Services/OilPriceService.cs
public class OilPriceService
{
private readonly OilPriceClient _client;
private readonly IMemoryCache _cache;
public OilPriceService(OilPriceClient client, IMemoryCache cache)
{
_client = client;
_cache = cache;
}
public async Task<PriceResponse> GetCurrentPricesAsync(params string[] codes)
{
var cacheKey = $"oil_prices_{string.Join("_", codes.OrderBy(c => c))}";
return await _cache.GetOrCreateAsync(cacheKey, async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
return await _client.GetLatestPricesAsync(codes);
});
}
}
// Controllers/PricesController.cs
[ApiController]
[Route("api/[controller]")]
public class PricesController : ControllerBase
{
private readonly OilPriceService _oilService;
public PricesController(OilPriceService oilService)
{
_oilService = oilService;
}
[HttpGet]
public async Task<IActionResult> GetPrices([FromQuery] string codes = "WTI_USD")
{
try
{
var codeArray = codes.Split(',');
var prices = await _oilService.GetCurrentPricesAsync(codeArray);
return Ok(prices);
}
catch (OilPriceAPIException ex)
{
return StatusCode(ex.StatusCode, new { error = ex.Message });
}
}
}
Concurrent Requests
using OilPriceAPI;
using var client = new OilPriceClient();
var commodities = new[] { "WTI_USD", "BRENT_CRUDE_USD", "NATURAL_GAS_USD", "HEATING_OIL_USD" };
// Fetch all prices concurrently
var tasks = commodities.Select(async code =>
{
var price = await client.GetLatestPricesAsync(code);
return (code, price);
});
var results = await Task.WhenAll(tasks);
foreach (var (code, response) in results)
{
if (response.Data.TryGetValue(code, out var data))
{
Console.WriteLine($"{code}: {data.Formatted}");
}
}
Blazor Component
@page "/prices"
@inject OilPriceClient OilClient
<h3>Current Oil Prices</h3>
@if (_loading)
{
<p>Loading prices...</p>
}
else if (_error != null)
{
<p class="text-danger">@_error</p>
}
else if (_prices != null)
{
<table class="table">
<thead>
<tr>
<th>Commodity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
@foreach (var (code, data) in _prices.Data)
{
<tr>
<td>@code</td>
<td>@data.Formatted</td>
</tr>
}
</tbody>
</table>
}
@code {
private PriceResponse _prices;
private bool _loading = true;
private string _error;
protected override async Task OnInitializedAsync()
{
try
{
_prices = await OilClient.GetLatestPricesAsync(
"WTI_USD", "BRENT_CRUDE_USD", "NATURAL_GAS_USD"
);
}
catch (Exception ex)
{
_error = ex.Message;
}
finally
{
_loading = false;
}
}
}
Error Handling
public static class RetryHelper
{
public static async Task<T> ExecuteWithRetryAsync<T>(
Func<Task<T>> operation,
int maxRetries = 3,
int baseDelayMs = 1000)
{
Exception lastException = null;
for (int attempt = 0; attempt <= maxRetries; attempt++)
{
try
{
return await operation();
}
catch (RateLimitException ex)
{
lastException = ex;
if (attempt < maxRetries)
{
var delay = baseDelayMs * (int)Math.Pow(2, attempt);
Console.WriteLine($"Rate limited, waiting {delay}ms (attempt {attempt + 1}/{maxRetries})");
await Task.Delay(delay);
}
}
catch (AuthenticationException)
{
throw; // Don't retry auth errors
}
catch (OilPriceAPIException ex)
{
lastException = ex;
if (attempt < maxRetries)
{
await Task.Delay(baseDelayMs);
}
}
}
throw lastException;
}
}
// Usage
var prices = await RetryHelper.ExecuteWithRetryAsync(
() => client.GetLatestPricesAsync("WTI_USD")
);
Best Practices
Configuration with IOptions
public class OilPriceApiOptions
{
public string ApiKey { get; set; }
public int TimeoutSeconds { get; set; } = 30;
public int CacheMinutes { get; set; } = 5;
}
// appsettings.json
{
"OilPriceApi": {
"ApiKey": "${OILPRICE_API_KEY}",
"TimeoutSeconds": 30,
"CacheMinutes": 5
}
}
// Program.cs
builder.Services.Configure<OilPriceApiOptions>(
builder.Configuration.GetSection("OilPriceApi")
);
Dependency Injection
public interface IOilPriceClient
{
Task<PriceResponse> GetLatestPricesAsync(params string[] codes);
Task<HistoricalResponse> GetHistoricalPricesAsync(string code, int days = 7);
}
// Register in DI container
builder.Services.AddSingleton<IOilPriceClient, OilPriceClient>();
Common Commodity Codes
| Code | Description |
|---|---|
WTI_USD | West Texas Intermediate Crude Oil |
BRENT_CRUDE_USD | Brent Crude Oil |
NATURAL_GAS_USD | Natural Gas (Henry Hub) |
HEATING_OIL_USD | Heating Oil No. 2 |
DIESEL_USD | Ultra Low Sulfur Diesel |
Next Steps
- Authentication Guide - API key management
- API Reference - Complete endpoint documentation
- Historical Data - Time-series queries
- Rate Limiting - Usage limits and best practices