C# / .NET¶
Practical .NET client for Estia API: token caching, auto refresh, one place for authenticated requests.
You'll probably adapt naming, logging, resilience, and DI to your own codebase — but as a starting point, it works.
Full example¶
using System.Net.Http.Headers;
using System.Net.Http.Json;
public sealed class EstiaApiClient
{
private readonly HttpClient _http;
private readonly string _clientId;
private readonly string _clientSecret;
private string? _token;
private DateTimeOffset _tokenExpiresAt;
private readonly SemaphoreSlim _tokenLock = new(1, 1);
public EstiaApiClient(string clientId, string clientSecret,
string apiBaseUrl = "https://api.insurancegateway.gr")
{
_http = new HttpClient { BaseAddress = new Uri(apiBaseUrl) };
_clientId = clientId;
_clientSecret = clientSecret;
}
private async Task<string> GetTokenAsync(CancellationToken ct = default)
{
if (_token is not null && DateTimeOffset.UtcNow < _tokenExpiresAt.AddMinutes(-5))
return _token;
await _tokenLock.WaitAsync(ct);
try
{
if (_token is not null && DateTimeOffset.UtcNow < _tokenExpiresAt.AddMinutes(-5))
return _token;
using var auth = new HttpClient();
var resp = await auth.PostAsync(
"https://auth.insurancegateway.gr/realms/estia/protocol/openid-connect/token",
new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["client_id"] = _clientId,
["client_secret"] = _clientSecret,
}), ct);
resp.EnsureSuccessStatusCode();
var json = await resp.Content.ReadFromJsonAsync<TokenResponse>(ct);
_token = json!.access_token;
_tokenExpiresAt = DateTimeOffset.UtcNow.AddSeconds(json.expires_in);
return _token;
}
finally
{
_tokenLock.Release();
}
}
public async Task<T?> GetAsync<T>(string path, CancellationToken ct = default)
{
var token = await GetTokenAsync(ct);
using var req = new HttpRequestMessage(HttpMethod.Get, path);
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var resp = await _http.SendAsync(req, ct);
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadFromJsonAsync<T>(ct);
}
public async Task<T?> PostAsync<T>(string path, object body, CancellationToken ct = default)
{
var token = await GetTokenAsync(ct);
using var req = new HttpRequestMessage(HttpMethod.Post, path)
{
Content = JsonContent.Create(body)
};
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
var resp = await _http.SendAsync(req, ct);
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadFromJsonAsync<T>(ct);
}
private record TokenResponse(string access_token, int expires_in, string token_type);
}
Example usage¶
var client = new EstiaApiClient(
clientId: Environment.GetEnvironmentVariable("ESTIA_CLIENT_ID")!,
clientSecret: Environment.GetEnvironmentVariable("ESTIA_CLIENT_SECRET")!);
var brands = await client.GetAsync<List<Brand>>("/intersalonica/auto/brands");
Typical DI registration¶
builder.Services.AddSingleton(sp => new EstiaApiClient(
clientId: builder.Configuration["Estia:ClientId"]!,
clientSecret: builder.Configuration["Estia:ClientSecret"]!));
For heavier production traffic
Pair with IHttpClientFactory and resilience policies (retries, timeouts,
circuit breakers), especially for scheduled or high-volume workloads.