> For the complete documentation index, see [llms.txt](https://docs.pal.aic.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.pal.aic.io/using-pal.net/advanced-transport.md).

# Advanced transport

Most applications should use the generated clients or a higher-level façade. This chapter explains the shared transport behavior and the extension points used by advanced integrations and test harnesses.

## Buffered versus streaming

Use buffered operations for bounded JSON responses. The runtime returns `PalantirTransportResponse` with status, safe headers, body bytes, diagnostic ID, attempt count, and retry exhaustion state.

Use streaming operations for binary data, event responses, table results, SQL results, and large payloads. `PalantirStreamingResponse` owns the underlying `HttpResponseMessage`, stream, and diagnostic scope. Dispose it with `using` or `await using`.

The buffered limit is controlled by `MaxBufferedResponseBytes`. A response that exceeds it raises `PalantirResponseTooLargeException`; it must be requested through a streaming operation instead.

## Requests and replayable bodies

`PalantirRequest` contains the operation ID, method, relative path, API version, body, media type, safe headers, scopes, idempotency, and documented errors. It rejects absolute URLs, restricted headers, conflicting body forms, and invalid scopes.

Use `PalantirRequestBody` for uploads:

```csharp
var body = PalantirRequestBody.FromFile(
    "./payload.ndjson",
    "application/x-ndjson");

var request = new PalantirRequest
{
    OperationId = "custom.upload",
    Method = HttpMethod.Post,
    PathAndQuery = "/api/v2/files",
    StreamBody = body,
    ContentType = body.ContentType,
    IsIdempotent = false,
    Scopes = ["api:write"]
};
```

`FromFile` creates a fresh stream for every transport attempt and is replayable. `FromStream` transfers ownership of an already-open stream and is non-replayable. A stream factory can explicitly declare replayability. Never mark a body replayable when repeating it could duplicate a side effect or produce different content.

## Retry behavior

Retries are bounded by `MaxRetries` and are considered only when the request is safe to replay. The policy uses upstream `Retry-After` metadata when present, otherwise bounded exponential backoff with optional jitter. A non-idempotent request or a non-replayable body is not retried merely because the status is transient.

Typical retryable conditions include transport interruption, 408, 429, and selected 5xx responses. The policy respects caller cancellation and never sleeps after cancellation has been requested.

For mutations, make idempotency explicit in the generated descriptor or custom request and supply a replayable body only when upstream semantics guarantee safe repetition.

## Pagination

Generated paginated operations expose the upstream continuation contract. The Ontology façade offers both a page method and `IAsyncEnumerable<T>` enumeration. Lazy enumeration:

* fetches one page at a time;
* yields items as they arrive;
* forwards cancellation to each request;
* detects repeated page tokens;
* does not materialize the complete result set.

Keep explicit page tokens when a job needs durable checkpoints or resumability.

## Long-running operations

`PalantirOperationPoller` accepts a state getter and terminal predicate. Configure `PalantirPollingOptions.Interval` and `Timeout`; do not create an unbounded polling loop. A timeout is reported as `PalantirPollingTimeoutException`, while caller cancellation remains distinguishable.

## Error mapping

Failed buffered operations throw `PalantirApiException`. The exception contains safe operation and classification metadata, HTTP status, diagnostic ID, retry exhaustion, safe upstream error name/code, parameter names, and the matched documented error contract. It does not retain arbitrary upstream parameter values.

Status mapping is:

| Status                  | Classification |
| ----------------------- | -------------- |
| 401                     | Authentication |
| 403                     | Authorisation  |
| 404                     | NotFound       |
| 400 or 422              | Validation     |
| 429                     | Throttled      |
| 408, 500, 502, 503, 504 | Transient      |
| Other                   | Upstream       |

Catch specific exceptions at the application boundary and translate them to the host's problem, retry, or job-failure model. Do not retry `PalantirApiException` blindly; inspect classification, operation id, and idempotency.
