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

# Configuration

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

## Options

**Client.java**

```
OpenEmail client = OpenEmail.builder()
    .apiKey(System.getenv("OPENEMAIL_API_KEY"))
    .baseUrl("https://api.openemail.uk")
    .timeout(Duration.ofSeconds(30))
    .maxRetries(2)
    .header("X-Team", "billing")
    .build();

System.out.println(client.mode());
```

| Option | What it does |
| --- | --- |
| `apiKey` | The workspace API key, beginning `oe_live_` or `oe_test_`. On a call, it acts with another key for that call only. |
| `accessToken` | An OAuth access token, for an app a person connected. Pass a key or a token, not both. |
| `accessToken(Supplier<String>)` | A function that returns the access token. It runs before every request, so it is the place to renew a token. |
| `baseUrl` | The API origin. A bare host such as `localhost:2222` gets its scheme added. |
| `httpClient` | Your own `java.net.http.HttpClient`, for a proxy, a custom `SSLContext` or an executor. |
| `timeout` | How long one attempt may take. The default is 30 seconds, zero turns it off, and uploads wait at least ten minutes. |
| `maxRetries` | How many times a failed request is tried again. The default is 2, and 0 sends once. |
| `userAgent` | Replaces the `User-Agent` header, which is `openemail-java/` and the version. |
| `header`, `headers` | Adds a header to every request. |
| `disableUpdateNotice` | Turns off the one line on standard error that says a newer version is out. `OPENEMAIL_DISABLE_UPDATE_NOTICE=1` does the same. |

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.

## Options on a call

Query parameters and call settings go in a `RequestOptions`, passed after the arguments. It has a method for `apiKey`, `idempotencyKey`, `timeout`, `limit` and `cursor`, and `set` takes any other option under the name the API uses. Each method accepts the options its reference entry lists, and an option that does not apply is refused before anything is sent.

**AnotherWorkspace.java**

```
RequestOptions options = RequestOptions.of("folder", "inbox")
    .apiKey(System.getenv("OPENEMAIL_API_KEY"))
    .timeout(Duration.ofSeconds(5))
    .limit(50);

Page threads = client.threads().list(options);

System.out.println(threads.size());
```

A `RequestOptions` is immutable: every method returns a new one, so a shared value can never be changed by the code that adds to it. Interrupting the thread stops a call that is waiting.

## 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 never follows one, so a credential never travels to another host.

> Printing a client, a `RequestOptions` or an exception never shows a credential. The key, the token and the values of custom headers are kept out of `toString()` and out of every message the client writes.

## An endpoint without a method

`client.raw().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.

**RawRequest.java**

```
Object label = client.raw().request("POST", "/labels", Body.of("name", "Invoices"));

System.out.println(label);
```
