Skip to main content

HTTP Client Configuration

If you call api.basistheory.com with your own HTTP client, configure its connection reuse, timeouts, and retries as described on this page. These settings matter most for clients that call the API at volume. If you use a Basis Theory SDK, its default HTTP client already stays within the bounds the edge allows and needs no customization; the SDK section covers the cases where you want to change it.

Connection reuse

Keep one HTTP client, and therefore one connection pool, for the lifetime of your process. Creating a client per request pays a TCP and TLS handshake every time and defeats the pool.

Bound how long a pooled connection may sit idle and how long it may live in total:

  1. Set a maximum idle time for pooled connections. For a client you configure yourself, 30 seconds is a safe starting value. The SDK defaults are already inside the edge's idle window and do not need to be lowered.
  2. If the client offers a maximum total connection lifetime, set one. Start with 5 minutes. Clients without the setting rely on the idle bound and the retry below.

Requests to api.basistheory.com are handled by the Basis Theory edge before reaching the API. Traffic is encrypted in transit at every hop. The edge manages the keepalive session for each client connection and closes idle connections on its own schedule. That schedule is not part of the API contract: Basis Theory is responsible for the availability of the edge and the API, and your client is responsible for the health of its own connection pool. The values above are how it meets that responsibility. They are guidance rather than a connection-lifetime contract, so monitor connection errors and keep your client's idle window comfortably below the edge's observed idle timeout.

The SDKs' default HTTP clients retire idle connections after anywhere from a few seconds to a few minutes depending on the language, all inside the edge's idle window. To shorten the idle window, pass a configured client into the SDK as shown in Configuring a Basis Theory SDK.

Stale connection errors

If a client pool selects a connection after the edge has closed it, the next read can return an unexpected EOF, and the request might never reach the API. OpenSSL reports this as UNEXPECTED_EOF_WHILE_READING. Higher request volume makes this timing race more likely to appear. It does not indicate that an API response was truncated or that the API returned an error.

Timeouts

Set a connect timeout and a per-request timeout deliberately rather than relying on defaults. A connect timeout of 5 seconds separates a network problem from a slow response. Choose a request timeout that matches how long your caller can wait, and remember that a timed-out request may still have been processed. Use an idempotency key on requests you might repeat.

Each SDK exposes a request timeout option. The connect timeout belongs to the underlying HTTP client, which you can pass into the SDK as shown in Configuring a Basis Theory SDK.

Retries

The SDKs retry responses with status codes 408, 429, and 5xx with exponential backoff, honoring Retry-After on rate limited responses. Each exposes an option to change the retry count.

A request that fails before any response arrives, such as a stale connection EOF, has no status code. The Node, .NET, and Go SDKs do not retry it. The Python SDK retries connection and protocol errors up to twice, and the Java SDK's OkHttp client transparently retries a request that fails on a stale pooled connection. If you handle these failures yourself, retry once for idempotent requests, retry a non-idempotent request only when it carries an idempotency key, and record both attempts under the same operation so persistent failures stay visible.

Configuring your own HTTP client

If you call the API without a Basis Theory SDK, apply the same settings to your own HTTP client. Preserve a shared pool instead of creating a new client for every request.

var handler = new SocketsHttpHandler
{
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30),
PooledConnectionLifetime = TimeSpan.FromMinutes(5),
ConnectTimeout = TimeSpan.FromSeconds(5),
};

var client = new HttpClient(handler)
{
BaseAddress = new Uri("https://api.basistheory.com"),
Timeout = TimeSpan.FromSeconds(30),
};

PooledConnectionIdleTimeout bounds idle time, and PooledConnectionLifetime bounds the total age of a connection. Reuse the HttpClient for the lifetime of the application.

Configuring a Basis Theory SDK

The Basis Theory SDKs use default HTTP clients that keep idle connections inside the bounds the edge allows, so customization is not typically required. If you do need to customize HTTP client configuration, each SDK accepts a preconfigured HTTP client, or a custom fetcher in the case of Node, alongside its timeout and retry options. The examples below apply the same idle and timeout values as above for illustrative purposes.

using BasisTheory.Client;

var handler = new SocketsHttpHandler
{
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30),
PooledConnectionLifetime = TimeSpan.FromMinutes(5),
ConnectTimeout = TimeSpan.FromSeconds(5),
};

var client = new BasisTheory(
"<API_KEY>",
clientOptions: new ClientOptions
{
HttpClient = new HttpClient(handler),
Timeout = TimeSpan.FromSeconds(30),
MaxRetries = 2,
});

Reuse the BasisTheory instance for the lifetime of the application.