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. Build solutions for commodities trading, logistics, and fleet management systems.
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 |
Frequently Asked Questions
Is there an official SDK for C#?
Currently, OilPriceAPI provides code examples and integration patterns for C#/.NET. The examples above can be used directly in your project with HttpClient and System.Text.Json.
How do I handle rate limiting in C#?
Implement exponential backoff when you receive 429 (Too Many Requests) responses. Use Task.Delay() with increasing delays between retries:
var delay = baseDelayMs * (int)Math.Pow(2, attempt);
await Task.Delay(delay);
What's the recommended error handling approach?
Always check HTTP status codes before parsing responses. Handle network timeouts and implement proper retry logic for transient failures. Use custom exception classes like RateLimitException and AuthenticationException that inherit from a base OilPriceAPIException class.
Can I use async/concurrent requests?
Yes, C# has excellent async/await support. Use Task.WhenAll() to fetch multiple commodity prices concurrently. The HttpClient is designed for async operations, so always use the async methods like GetAsync() and ReadAsStringAsync() for optimal performance.
Related Resources
- Power BI Integration - No-code dashboards for .NET shops
- Tableau Integration - Visual analytics alternative
- Zapier Integration - Automate without coding
- Commodities Trading API - Trading platform integration
- Fleet Management API - Fleet cost tracking
- Logistics Fuel API - Supply chain applications
- Go Developer Guide - Alternative language guide
- Python Developer Guide - Data science integration
- Authentication Guide - API key management
- API Reference - Complete endpoint documentation
- Rate Limiting - Usage limits and best practices