> ## Documentation Index
> Fetch the complete documentation index at: https://ekso.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Your first authenticated call against the Ekso API. Five minutes from new project to listing items.

## What you'll build

A console app that authenticates with an API key against your Ekso install, lists the first page of items, and prints their keys. Five minutes start to finish.

## 1. New project

```bash theme={null}
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:

```bash theme={null}
ekso api-key create --name "sdk-sample" --url https://ekso.acme.com
```

The response includes a `rawKey` field — capture the value (`ek_live_...`) once. The backend never returns it again. Set it on your shell:

```bash theme={null}
export EKSO_API_KEY=ek_live_xxx
export EKSO_URL=https://ekso.acme.com
```

## 3. Write the program

Replace `Program.cs`:

```csharp theme={null}
using Ekso.Sdk;
using Ekso.Sdk.Authentication;
using Ekso.Sdk.Exceptions;
using Ekso.Sdk.Generated.Models;

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

var client = new EksoClient(new EksoClientOptions
{
    BaseUrl = url,
    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 '{url}'. {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

```bash theme={null}
dotnet run
```

Expected output:

```
Connected to 'https://ekso.acme.com'. 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 your install URL 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](/sdk/error-handling) for the full hierarchy.

## Next ideas

Now that you have a working client, try:

```csharp theme={null}
// 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 install */ "...",
    ContainerId = /* an id from your install */ "...",
};
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](/api-reference/introduction). 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

* **[Authentication](/sdk/authentication)** — `ApiKeyAuth` vs `RefreshableBearerAuth`.
* **[Error handling](/sdk/error-handling)** — exception hierarchy + retry strategies.
* **[CLI/SDK marker](/sdk/cli-sdk-marker)** — operations that are gated for SDK callers.
