---
title: "Configuration"
description: "Every option of the client, what it reads from the environment, and what it refuses."
url: "https://openemail.uk/docs/go/configuration"
area: "Go"
category: "Getting started"
---

# Configuration

Every option of the client, what it reads from the environment, and what it refuses.

## Options

**client.go**

```
client := openemail.New(
	openemail.WithAPIKey(os.Getenv("OPENEMAIL_API_KEY")),
	openemail.WithBaseURL("https://api.openemail.uk"),
	openemail.WithTimeout(30*time.Second),
	openemail.WithMaxRetries(2),
	openemail.WithHeader("X-Team", "billing"),
)

if err := client.Err(); err != nil {
	return err
}

fmt.Println(client.Mode(), client.BaseURL())
```

| Option | What it does |
| --- | --- |
| `WithAPIKey` | The workspace API key, beginning `oe_live_` or `oe_test_`. On a call, it acts with another key for that call only. |
| `WithAccessToken` | An OAuth access token, for an app a person connected. Pass a key or a token, not both. |
| `WithAccessTokenFunc` | A function that returns the access token. It runs before every request, so it is the place to renew a token. |
| `WithBaseURL` | The API origin. A bare host such as `localhost:2222` gets its scheme added. |
| `WithHTTPClient` | An `*http.Client`, or anything with the same `Do` method. A test passes a fake here. |
| `WithTimeout` | How long one attempt may take. The default is 30 seconds, zero turns it off, and uploads wait at least ten minutes. |
| `WithMaxRetries` | How many times a failed request is tried again. The default is 2, and 0 sends once. |
| `WithUserAgent` | Replaces the `User-Agent` header, which is `openemail-go/` and the version. |
| `WithHeader` | Adds a header to every request. |

Anything you leave out is read from the environment: `OPENEMAIL_API_KEY`, then `OPENEMAIL_ACCESS_TOKEN`, and `OPENEMAIL_BASE_URL`. `client.Mode()` says whether the key is a `live` or a `test` key.

## Context and timeouts

Every method takes a `context.Context` first. Cancelling it stops the call at once, and its deadline bounds the whole call, retries included, while `WithTimeout` bounds each attempt. `WithTimeout` also works on a single call.

**deadline.go**

```
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()

thread, err := client.Threads.Get(ctx, "CAHk7pQ2x9LmZ4-mail.example.com", openemail.WithTimeout(5*time.Second))
if err != nil {
	return err
}

fmt.Println(thread.Int("messageCount"))
```

## Options on a call

Query parameters and call settings are functions passed after the arguments, such as `openemail.WithLimit`, `openemail.WithCursor` and `openemail.WithIdempotencyKey`. Each method accepts the options its reference entry lists, and an option that does not apply is refused before anything is sent.

**another_workspace.go**

```
page, err := client.Emails.List(ctx,
	openemail.WithStatus("failed", "bounced"),
	openemail.WithLimit(50),
	openemail.WithAPIKey(os.Getenv("OTHER_WORKSPACE_KEY")),
)
if err != nil {
	return err
}

fmt.Println(len(page.Items), page.HasMore)
```

## What the client refuses

- A key that does not begin `oe_live_` or `oe_test_`, and a key together with an access token.
- Sending a credential over plain `http:`, unless the server is on this machine at `localhost`, a `127.x.x.x` address or `::1`.
- A base URL on `0.0.0.0`, which is an address a server listens on. Use `127.0.0.1` with the same port.
- An empty id, or one made only of dots, which a URL parser would remove.
- Following a redirect. The default HTTP client returns it as an error, so a credential never travels to another host.

> Printing a client, an option or an error never shows a credential. The key, the token and the values of custom headers are kept out of `fmt`, `log/slog` and `encoding/json` output.

## An endpoint without a method

`client.Request` calls any path with the credential, base URL, timeout and retry policy of the client. The path must begin with a single `/`, and a path that leaves the origin of the base URL is refused.

**request.go**

```
label, err := client.Request(ctx, http.MethodPost, "/labels", openemail.Body{"name": "Invoices"})
if err != nil {
	return err
}

fmt.Println(label)
```
