# API Quickstart

> Install a LevelFour SDK for Python, TypeScript or Go, point it at an API key, and make your first call.

Source: https://docs.levelfour.ai/api-quickstart


LevelFour publishes official SDKs for Python, TypeScript and Go, all generated from the same OpenAPI spec. Install one, give it an API key, and your code reads the same cloud spend and savings backlog the dashboard shows.

## Prerequisites

* A LevelFour account with API access enabled.
* An API key, created in the dashboard under **Settings > API Keys**. [Authentication](/authentication) has the key formats and what each scope reaches.

## Set up

### Install an SDK

**Python**

```bash
pip install levelfour
```

**TypeScript**

```bash
npm install levelfour
```

**Go**

```bash
go get github.com/LevelFourAI/levelfour-go
```

### Set your API key

Export the key as an environment variable. All SDKs auto-detect it:

```bash
export LEVELFOUR_API_KEY="l4_live_your_key_here"
```

> **Tip**
>
> Keep the key out of anything you commit. An `l4_live_` key reaches production data, and an `l4_test_` key is the one to experiment with. [Authentication](/authentication#security-best-practices) covers keeping a key out of your source.

### Make your first request

Call the `whoami` endpoint:

**Python**

```python
from levelfour import LevelFour

client = LevelFour()

me = client.auth.get_whoami()
print(me)
```

**TypeScript**

```typescript
import { LevelFourClient } from "levelfour";

const client = new LevelFourClient();

const me = await client.auth.getWhoami();
console.log(me);
```

**Go**

```go
package main

import (
	"context"
	"fmt"
	"log"

	"github.com/LevelFourAI/levelfour-go/levelfour"
)

func main() {
	client, err := levelfour.NewClient("")
	if err != nil {
		log.Fatal(err)
	}

	me, err := client.Auth.GetWhoami(context.Background())
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(me)
}
```

> **Success**
>
> That response is the proof: the SDK found your key and the API accepted it.

> **Error**
>
> A `401` back from that call means the API rejected the key. Re-check the export, then confirm the key is still active under **Settings > API Keys**. [Error handling](/error-handling) maps each status code to a typed error class.

## Read your data

Neither of these calls depends on the other, so run whichever you need.

### Savings by provider

One call totals the potential savings LevelFour has found, split by cloud provider:

**Python**

```python
summary = client.recommendations.get_savings_by_provider()
print(summary)
```

**TypeScript**

```typescript
const summary = await client.recommendations.getSavingsByProvider();
console.log(summary);
```

**Go**

```go
summary, err := client.Recommendations.GetSavingsByProvider(context.Background())
if err != nil {
    log.Fatal(err)
}

fmt.Println(summary)
```

### List recommendations

The list method pages itself, so one loop walks every recommendation:

**Python**

```python
page = client.recommendations.list(page_size=10)

for rec in page:
    print(f"{rec.service}: ${rec.monthly_savings}/mo")
```

**TypeScript**

```typescript
for await (const rec of await client.recommendations.list({ page_size: 10 })) {
    console.log(`${rec.service}: $${rec.monthly_savings}/mo`);
}
```

**Go**

```go
page, err := client.Recommendations.List(
    context.Background(),
    &levelfour.ListRecommendationsRequest{PageSize: levelfour.Int(10)},
)
if err != nil {
    log.Fatal(err)
}

iter := page.Iterator()
for iter.Next(context.Background()) {
    rec := iter.Current()
    fmt.Printf("%s: $%.2f/mo\n", rec.Service, rec.MonthlySavings)
}
if err := iter.Err(); err != nil {
    log.Fatal(err)
}
```

Every method, parameter and response shape lives in [Recommendations](/resources/recommendations). [Pagination](/pagination) covers the response envelope and taking page control by hand.

## Next

* [Authentication](/authentication) covers key scopes, rotation, and what to do when a key leaks
* [SDKs](/sdks) is the per-language reference, with constructor options and sub-clients
* [Resources](/resources) is every method, grouped by the resource it reads
* [Error handling](/error-handling) maps each status code to a typed error class, and names what the SDKs retry before you see it
* [Pagination](/pagination) is the response envelope and manual page control when the auto-iterator is not what you want
* [CLI](/cli) is the same data from the terminal, where `l4 whoami` stands in for this page
* [MCP](/mcp) puts the same data in Claude Code, Claude, Cursor, VS Code or Windsurf
* [Quickstart](/quickstart) connects the cloud accounts these numbers come from
