Skip to main content

What you’ll build

A console app that authenticates with an API key, lists the first page of items in a tenant, and prints their keys. Five minutes start to finish.

1. New project

mkdir ekso-sample && cd ekso-sample
dotnet new console
dotnet add package Ekso.Sdk

2. Provision an API key

If you don’t already have one, mint one via the CLI:
ekso api-key create --name "sdk-sample" --tenant acme
The response includes a rawKey field — capture the value (ek_live_...) once. The backend never returns it again. Set it on your shell:
export EKSO_API_KEY=ek_live_xxx
export EKSO_TENANT=acme

3. Write the program

Replace Program.cs:
using Ekso.Sdk;
using Ekso.Sdk.Authentication;
using Ekso.Sdk.Exceptions;
using Ekso.Sdk.Generated.Models;

var tenant = Environment.GetEnvironmentVariable("EKSO_TENANT")
    ?? throw new InvalidOperationException("Set EKSO_TENANT first.");
var apiKey = Environment.GetEnvironmentVariable("EKSO_API_KEY")
    ?? throw new InvalidOperationException("Set EKSO_API_KEY first.");

var client = new EksoClient(new EksoClientOptions
{
    Tenant = tenant,
    Auth = new ApiKeyAuth(apiKey),
});

try
{
    // First call — list the field collection. Cheap, validates auth + connectivity.
    var fields = await client.Api.Field.GetAsync();
    var coreCount = (fields?.TypeText?.Count ?? 0)
                  + (fields?.TypeList?.Count ?? 0)
                  + (fields?.TypePicker?.Count ?? 0);
    Console.WriteLine($"Connected to '{tenant}'. {coreCount} fields configured.");

    // Now list a first page of items
    var page = await client.Api.Item.List.PostAsync(new ItemListRequest());
    Console.WriteLine($"\nFirst {page?.Data?.Count ?? 0} items:");
    foreach (var item in page?.Data ?? [])
    {
        Console.WriteLine($"  {item.Key}: {item.Name}");
    }
}
catch (EksoAuthException ex)
{
    Console.Error.WriteLine($"Auth failed ({ex.Reason}): {ex.Message}");
    Environment.Exit(3);
}
catch (EksoApiException ex)
{
    Console.Error.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
    Environment.Exit(1);
}

4. Run

dotnet run
Expected output:
Connected to 'acme'. 14 fields configured.

First 25 items:
  PRD-1: Set up CI/CD pipeline
  PRD-2: Database migration plan
  HELP-1: Customer escalation: missing invoice
  ...

What just happened

  • EksoClient was constructed against https://acme.ekso.app with bearer-token auth.
  • client.Api.Field.GetAsync() issued a GET /api/field and deserialized the response into a typed FieldCollection.
  • client.Api.Item.List.PostAsync(...) issued a POST /api/item/list with an ItemListRequest body and deserialized into a typed ItemListResponse.
  • The EksoAuthException and EksoApiException catches surface specific failure shapes — see Error handling for the full hierarchy.

Next ideas

Now that you have a working client, try:
// Create a custom field
var field = new DataFieldText
{
    Name = "Customer Reference",
    Description = "Internal reference id",
    ContentType = "ContentText",
    Maximum = 64,
};
await client.Api.Field.Text.PostAsync(field);

// Create an item
var item = new DataItem
{
    Name = "Onboard new customer",
    ProcessId = /* an id from your tenant */ "...",
    ContainerId = /* an id from your tenant */ "...",
};
var created = await client.Api.Item.PostAsync(item);
Console.WriteLine($"Created {created!.Key}");
The full surface — every typed method on client.Api.* — maps 1-to-1 to the operations in the API Reference. Auto-completion in your IDE is the fastest discovery path.

Production hardening

  • Don’t hard-code keys. Read from a secrets manager, not from environment variables on a developer’s laptop.
  • Catch the right exceptions. EksoRateLimitException.RetryAfter tells you exactly how long to back off; EksoNetworkException is the only one you should reflexively retry without thought.
  • Set a sensible HTTP timeout. The SDK uses Kiota’s default — wrap calls in CancellationToken if you need tighter bounds.
  • Use RefreshableBearerAuth if you’re acting on behalf of a user — token rotation is the right model. ApiKeyAuth is for service identities.

Next steps