Skip to content

.NET SDK — How‑to: Authentication

Authenticate to AIForged using:

  • API key (recommended for backend and service integrations)
  • Credentials (username/password) for first‑party, trusted apps

Production API base URL: https://portal.aiforged.com
NuGet: AIForged.SDK


TL;DR — which should I use?

  • Server‑to‑server/backends: API key via the X‑Api‑Key header.
  • First‑party trusted apps: credentials (username/password) using the SDK’s built‑in helpers.

One method per Context

Don’t mix API key and credentials/bearer on the same Config/Context. If you need both in one process, create separate Context instances.


Environment variables - AIFORGED_BASE_URL: https://portal.aiforged.com - AIFORGED_API_KEY: your key

PowerShell

$env:AIFORGED_BASE_URL = "https://portal.aiforged.com"
$env:AIFORGED_API_KEY  = "•••"

Bash/zsh

export AIFORGED_BASE_URL="https://portal.aiforged.com"
export AIFORGED_API_KEY="•••"

Minimal console snippet

using AIForged.API;

var baseUrl = Environment.GetEnvironmentVariable("AIFORGED_BASE_URL") ?? "https://portal.aiforged.com";
var apiKey  = Environment.GetEnvironmentVariable("AIFORGED_API_KEY")  ?? throw new Exception("AIFORGED_API_KEY not set.");

var cfg = new Config { BaseUrl = baseUrl, Timeout = TimeSpan.FromMinutes(5) };
await cfg.Init();

cfg.HttpClient.DefaultRequestHeaders.Add("X-Api-Key", apiKey);

var ctx = new Context(cfg);
var me  = await ctx.GetCurrentUserAsync();
Console.WriteLine($"Connected as: {me?.Email ?? me?.UserName} ({me?.Id})");

ASP.NET Core DI pattern

using AIForged.API;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSingleton<Config>(sp =>
{
    var baseUrl = Environment.GetEnvironmentVariable("AIFORGED_BASE_URL") ?? "https://portal.aiforged.com";
    var apiKey  = Environment.GetEnvironmentVariable("AIFORGED_API_KEY")  ?? throw new Exception("AIFORGED_API_KEY not set.");

    var cfg = new Config { BaseUrl = baseUrl, Timeout = TimeSpan.FromMinutes(5) };
    cfg.Init().GetAwaiter().GetResult();
    cfg.HttpClient.DefaultRequestHeaders.Add("X-Api-Key", apiKey);
    return cfg;
});

builder.Services.AddSingleton<Context>();

var app = builder.Build();
app.MapGet("/me", async (Context ctx) =>
{
    var me = await ctx.GetCurrentUserAsync();
    return Results.Ok(new { me?.Id, me?.Email, me?.UserName });
});
app.Run();

Rotate the API key at runtime

void UpdateApiKey(Config cfg, string newKey)
{
    var headers = cfg.HttpClient.DefaultRequestHeaders;
    if (headers.Contains("X-Api-Key")) headers.Remove("X-Api-Key");
    headers.Add("X-Api-Key", newKey);
}

Best practices

  • Load keys from a secret store (Key Vault, AWS Secrets, etc.).
  • Use IOptionsMonitor/IOptionsSnapshot or a background refresher to call UpdateApiKey when keys rotate.

Option 2 (optional): Credentials‑based sign‑in (username/password)

For trusted, first‑party applications, the SDK can sign in with user credentials and manage access/refresh tokens internally.

Environment variables (example)

  • AIFORGED_BASE_URL
  • AIFORGED_USERNAME
  • AIFORGED_PASSWORD
  • AIFORGED_CLIENT_ID
  • AIFORGED_CLIENT_SECRET
  • AIFORGED_SCOPES (e.g., openid profile api)

Example

using AIForged.API;

var cfg = new Config
{
    BaseUrl      = Environment.GetEnvironmentVariable("AIFORGED_BASE_URL") ?? "https://portal.aiforged.com",
    UserName     = Environment.GetEnvironmentVariable("AIFORGED_USERNAME"),
    Password     = Environment.GetEnvironmentVariable("AIFORGED_PASSWORD"),
    ClientId     = Environment.GetEnvironmentVariable("AIFORGED_CLIENT_ID"),
    ClientSecret = Environment.GetEnvironmentVariable("AIFORGED_CLIENT_SECRET"),
    Scopes       = Environment.GetEnvironmentVariable("AIFORGED_SCOPES") ?? "openid profile api"
};

await cfg.Init();
var ctx = new Context(cfg);

// Sign in with credentials; the SDK handles the underlying token exchange.
var currentUser = await ctx.LoginAsync();
Console.WriteLine($"Logged in as: {currentUser?.Email ?? currentUser?.UserName} ({currentUser?.Id})");

// Use the SDK normally…
var projects = await ctx.ProjectClient.GetByUserAsync(ctx.CurrentUserId, includeBalance: true);
Console.WriteLine($"Projects: {projects?.Result?.Count}");

// Refresh tokens later when needed
var refreshedUser = await ctx.RefreshLoginAsync();
Console.WriteLine($"Token refreshed. Expires: {cfg.Expiry}");

Notes

  • The SDK sets and maintains bearer tokens on the underlying HttpClient.
  • Do not add X‑Api‑Key when using credentials on the same Context.

Per‑environment setup

  • Environment variables per environment (dev/staging/prod).
  • appsettings.{Environment}.json + secret store (preferred in production).
  • Single Context per process (or per tenant) that is reused.

Example config binding

{
  "AIForged": {
    "BaseUrl": "https://portal.aiforged.com",
    "ApiKey": "use-env-or-secret-store"
  }
}

var aiforged = builder.Configuration.GetSection("AIForged").Get<AIForgedOptions>();

builder.Services.AddSingleton(sp =>
{
    var cfg = new Config { BaseUrl = aiforged.BaseUrl, Timeout = TimeSpan.FromMinutes(5) };
    cfg.Init().GetAwaiter().GetResult();
    cfg.HttpClient.DefaultRequestHeaders.Add("X-Api-Key", aiforged.ApiKey);
    return cfg;
});
builder.Services.AddSingleton<Context>();

public record AIForgedOptions
{
    public string BaseUrl { get; init; }
    public string ApiKey  { get; init; }
}

Security do’s and don’ts

Do

  • Keep secrets out of code; use env vars or a secret manager.
  • Use least‑privilege keys; rotate regularly.
  • Add structured logging (IDs, correlation) — but never log secrets.

Don’t

  • Commit keys or passwords to git.
  • Mix API key and credentials on the same Context/HttpClient.
  • Share one key across unrelated apps/tenants.

Header exactness

The header name must be exactly X-Api-Key.


Troubleshooting

401/403 Unauthorized/Forbidden

  • Missing/invalid API key or credentials.
  • Insufficient access to the target project/service.
  • BaseUrl points to the wrong environment.

404 Not Found

  • Wrong IDs (project/service/document) or stale references.

Credentials sign‑in fails

  • Check username/password, client id/secret, and scopes.
  • Ensure the account is active and not locked.

Key rotation didn’t apply

  • Update the existing HttpClient header or rebuild Context.

Example error handling

try
{
    var me = await ctx.GetCurrentUserAsync();
}
catch (AIForged.API.SwaggerException ex)
{
    Console.Error.WriteLine($"API error {(int)ex.StatusCode} {ex.StatusCode}: {ex.Message}");
    Console.Error.WriteLine($"Response: {ex.Response}");
}
catch (HttpRequestException ex)
{
    Console.Error.WriteLine($"Network error: {ex.Message}");
}


Multi‑tenant pattern

  • Keep one Context per tenant (each with its own API key or credentials).
  • Resolve tenant, pull the correct Context from a keyed cache, proceed.
  • When a tenant secret rotates, update the header or refresh the sign‑in accordingly.