C# / .NET Integration Guide
Integrate OilPriceAPI into your .NET applications to access the latest available 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.
.NET package availability
This is a direct REST integration guide. There is no official OilPriceAPI C# SDK or NuGet package. The examples use .NET's built-in HttpClient and System.Text.Json APIs.
Requirements
- A currently supported .NET release
- Built-in HttpClient and System.Text.Json APIs
HTTP and JSON Dependencies
HttpClient and System.Text.Json are built in to supported modern .NET releases, so the quick start needs no OilPriceAPI package. Newtonsoft.Json is an optional third-party alternative:
dotnet add package Newtonsoft.Json
For a legacy .NET Framework project, install System.Text.Json from NuGet and adapt the project syntax for that target. The examples below target supported modern .NET releases.
Quick Start
using System;
using System.Net.Http;
using System.Text.Json;
var apiKey = Environment.GetEnvironmentVariable("OILPRICEAPI_KEY");
if (string.IsNullOrWhiteSpace(apiKey))
throw new InvalidOperationException("OILPRICEAPI_KEY is required");
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"
);
response.EnsureSuccessStatusCode();
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
Complete API Client Class
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
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; } = string.Empty;
[JsonPropertyName("currency")]
public string Currency { get; set; } = string.Empty;
[JsonPropertyName("code")]
public string Code { get; set; } = string.Empty;
[JsonPropertyName("created_at")]
public DateTime CreatedAt { get; set; }
}
public class PriceResponse
{
[JsonPropertyName("status")]
public string Status { get; set; } = string.Empty;
// A single-commodity request (by_code=WTI_USD) returns a flat object at `data`.
[JsonPropertyName("data")]
public PriceData Data { get; set; } = new();
}
public class HistoricalData
{
[JsonPropertyName("prices")]
public List<PriceData> Prices { get; set; } = new();
}
public class HistoricalResponse
{
[JsonPropertyName("status")]
public string Status { get; set; } = string.Empty;
[JsonPropertyName("data")]
public HistoricalData Data { get; set; } = new();
}
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 interface IOilPriceClient
{
Task<PriceResponse> GetLatestPriceAsync(string code);
Task<HistoricalResponse> GetPastWeekPricesAsync(string code);
}
public class OilPriceClient : IOilPriceClient, 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("OILPRICEAPI_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}";
}
using 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)
?? throw new OilPriceAPIException("API returned an empty JSON payload");
}
public async Task<PriceResponse> GetLatestPriceAsync(string code)
{
var parameters = new Dictionary<string, string>
{
{ "by_code", code }
};
return await RequestAsync<PriceResponse>("/prices/latest", parameters);
}
public async Task<HistoricalResponse> GetPastWeekPricesAsync(string code)
{
var parameters = new Dictionary<string, string>
{
{ "by_code", code }
};
return await RequestAsync<HistoricalResponse>("/prices/past_week", parameters);
}
public void Dispose()
{
_httpClient?.Dispose();
}
}
}
Usage Examples
Fetch Multiple Commodities
using OilPriceAPI;
using var client = new OilPriceClient();
// Get several oil prices (one request per commodity)
var codes = new[] { "WTI_USD", "BRENT_CRUDE_USD", "NATURAL_GAS_USD" };
foreach (var code in codes)
{
var response = await client.GetLatestPriceAsync(code);
Console.WriteLine($"{response.Data.Code}: {response.Data.Formatted}");
}
Historical Price Analysis
using OilPriceAPI;
using var client = new OilPriceClient();
// Get past week of WTI prices
var history = await client.GetPastWeekPricesAsync("WTI_USD");
Console.WriteLine("WTI Price History:");
foreach (var point in history.Data.Prices)
{
Console.WriteLine($" {point.CreatedAt:yyyy-MM-dd}: ${point.Price:F2}");
}
// Calculate statistics
var prices = history.Data.Prices.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
var oilPriceApiKey = Environment.GetEnvironmentVariable("OILPRICEAPI_KEY");
if (string.IsNullOrWhiteSpace(oilPriceApiKey))
throw new InvalidOperationException("OILPRICEAPI_KEY is required");
builder.Services.AddSingleton(_ => new OilPriceClient(oilPriceApiKey));
// 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> GetCurrentPriceAsync(string code)
{
var cacheKey = $"oil_price_{code}";
return await _cache.GetOrCreateAsync(cacheKey, async entry =>
{
entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
return await _client.GetLatestPriceAsync(code);
});
}
}
// 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 code = "WTI_USD")
{
try
{
var price = await _oilService.GetCurrentPriceAsync(code);
return Ok(price);
}
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(code => client.GetLatestPriceAsync(code));
var results = await Task.WhenAll(tasks);
foreach (var response in results)
{
Console.WriteLine($"{response.Data.Code}: {response.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 data in _prices)
{
<tr>
<td>@data.Code</td>
<td>@data.Formatted</td>
</tr>
}
</tbody>
</table>
}
@code {
private List<PriceData> _prices;
private bool _loading = true;
private string _error;
protected override async Task OnInitializedAsync()
{
try
{
var codes = new[] { "WTI_USD", "BRENT_CRUDE_USD", "NATURAL_GAS_USD" };
var list = new List<PriceData>();
foreach (var code in codes)
{
var response = await OilClient.GetLatestPriceAsync(code);
list.Add(response.Data);
}
_prices = list;
}
catch (Exception ex)
{
_error = ex.Message;
}
finally
{
_loading = false;
}
}
}
Error Handling
using System;
using System.Threading.Tasks;
using OilPriceAPI;
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 ?? new OilPriceAPIException("Request failed without an error response");
}
}
public static class RetryExample
{
public static Task<PriceResponse> FetchLatestAsync(OilPriceClient client) =>
RetryHelper.ExecuteWithRetryAsync(
() => client.GetLatestPriceAsync("WTI_USD")
);
}
Best Practices
Configuration with IOptions
public class OilPriceApiOptions
{
public string ApiKey { get; set; } = string.Empty;
public int TimeoutSeconds { get; set; } = 30;
public int CacheMinutes { get; set; } = 5;
}
// appsettings.json
{
"OilPriceApi": {
"TimeoutSeconds": 30,
"CacheMinutes": 5
}
}
// Program.cs
builder.Services
.AddOptions<OilPriceApiOptions>()
.Bind(builder.Configuration.GetSection("OilPriceApi"))
.PostConfigure(options =>
{
options.ApiKey = Environment.GetEnvironmentVariable("OILPRICEAPI_KEY")
?? throw new InvalidOperationException("OILPRICEAPI_KEY is required");
});
Dependency Injection
// OilPriceClient implements IOilPriceClient in the complete client above.
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#?
No. There is no official OilPriceAPI C# SDK or NuGet package. Use the direct REST examples above 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