> For the complete documentation index, see [llms.txt](/llms.txt)

# Java

The Java SDK is an idiomatic, buildable Java library emitted from the same `GlottoIR` as every
other target. It ships with Gson models and an SDK-managed, Jetty-backed HTTP
transport. Existing `java.net.http.HttpClient` injection remains supported.
Add the artifact, construct a `Client`, and call methods — no checked exceptions to wrap.

## Quickstart

```gradle
implementation 'com.your-org:petstore:1.0.0'
```

```java
import com.your_org.petstore.Client;

Client client = new Client(System.getenv("PETSTORE_TOKEN"));

// resources are reached through an accessor call
var pet = client.pets().createPet(newPet);

// paging is a Stream — bind it, then drain
var pets = client.pets().listPets();
pets.forEach(System.out::println);
```

## Resource sub-clients

Operations hang off resource accessors rather than a flat method list:
`client.pets().get(id)`, `client.pets().photos().add(...)` — the same service-accessor shape the
other engines emit — and each method carries Javadoc generated from the operation prose in the spec.

## Unchecked errors

Non-2xx responses throw `ApiError`, an unchecked `RuntimeException` carrying the parsed, typed
error body, so callers narrow with `instanceof` rather than being forced into `try/catch` for a
checked `IOException`. See [Errors](/docs/errors).

## Async twins

Every buffered operation has a `CompletableFuture` async twin alongside its blocking form, so the
SDK fits both a synchronous caller and a non-blocking pipeline without a second client.

## Pagination

List methods return a lazy walker over the API's pagination strategy (cursor, page, offset, or
link-header), fetching each page as you iterate. See [Pagination](/docs/pagination).

## Retries & backoff

Transient failures (`5xx`, `429`, transport errors) retry with exponential backoff and jitter,
configurable per client. Discriminated-union response bodies resolve to the right concrete type.
See [Retries & timeouts](/docs/retries), [Streaming](/docs/streaming), and
[Authentication](/docs/authentication).

## Unknown response fields

Your API can add a response field without it being a breaking change — but a generated record has no component to put it in, and Gson discards what it does not recognize. The generated
models keep it instead: a field the SDK wasn't generated from is retained on decode, readable
through an accessor, and written back out when the model is re-serialized.

```java
Pet pet = client.pets().createPet(body);

// A field your API started returning after this SDK was generated.
JsonElement species = pet.extraFields().get("species");

// Re-encoding preserves it — a read-modify-write never silently drops it.
String json = client.gson().toJson(pet);
```

`extraFields()` is the record's own accessor and returns an immutable `Map<String, JsonElement>`,
so nested objects and arrays survive intact, and retention is recursive.

Your existing construction still compiles: the models keep a constructor over their original
component list, so `new Pet(id, name, tag, status, photoUrls)` is unchanged.

The retained fields are read-only by design. To *send* a field your spec doesn't model yet, use the
per-call extra-body escape hatch rather than writing to the retained bag.

## Pages, request controls, and files

Paginated methods also expose [manual pages](/docs/pagination#fetch-one-page),
so you can inspect one response and request its successor explicitly. Request
overrides apply to the initial call and to each requested next page; see
[Retries & timeouts](/docs/retries) for precedence and cancellation.

[Binary downloads](/docs/file-transfers) return an owned byte response with
metadata, a bounded read helper, and incremental consumption. Close the response
when you stop early. Your generated README demonstrates these operations with
your API's names and the language's native calling conventions.
