# Response telemetry[](#response-telemetry)

> For the complete machine-readable documentation index, see [llms.txt](https://apidocs.chargebee.com/llms.txt).


Response telemetry tells you where the time went on a single API call. When you ask for it, Chargebee adds an `X-Chargebee-Telemetry` header to the response with a server-side breakdown of the request:

-   How long Chargebee took to process the request.
-   How much of that time was spent in third-party integrations that you've configured, such as your payment gateway or tax provider.
-   How long the request waited for a lock on a resource that another request was using.

Use it to tell latency caused by Chargebee apart from latency caused by your network, your own code, or a third-party provider, without instrumenting Chargebee yourself.

Response telemetry is **opt-in** and applies **per request**. Chargebee doesn't send the header unless the request asks for it. Chargebee can add namespaces and keys to the header over time, so write your parser to [ignore anything it doesn't recognize](#forward-compatibility).

## Quick start with response telemetry[](#quick-start-with-response-telemetry)

Add the `Prefer: chargebee-telemetry=include` header to an API request. The following example retrieves a customer and prints the response headers with `-i`:

The response includes the `X-Chargebee-Telemetry` header alongside the usual headers. With HTTP/2, status lines and header names may appear in lowercase (for example `HTTP/2 200` and `x-chargebee-telemetry`):

To learn what each part of this value means, see [Read an example header](#read-an-example-header).

## Request telemetry[](#request-telemetry)

Item

Value

Request header

`Prefer`

Header value

`chargebee-telemetry=include`

Scope

Only the request that carries the header. Send it on every request that you want telemetry for.

Response header

`X-Chargebee-Telemetry`

Without the request header

The response doesn't contain `X-Chargebee-Telemetry`.

If you use the Node.js or Java client library, the library can send the request header and parse the response header for you. See [Use the client libraries](#use-the-client-libraries). In any other integration, set the request header yourself and [parse the response header](#parse-the-header-yourself).

## Header format[](#header-format)

The value of `X-Chargebee-Telemetry` is a [List](https://www.rfc-editor.org/rfc/rfc9651#name-lists) as defined by [RFC 9651: Structured Field Values for HTTP](https://www.rfc-editor.org/rfc/rfc9651).

-   **Members** are separated by commas. Each member describes one category of telemetry, such as Chargebee's own processing or one third-party integration.
-   **Namespace:** the first item of each member is a token that identifies its category, for example `cb` or `tp-stripe`. See [Namespaces](#namespaces).
-   **Parameters:** the `key=value` pairs that follow the namespace, separated by semicolons, belong to that namespace only.

### Value types[](#value-types)

Parameter values use RFC 9651 types. The type is identified by how the value is written:

Type

Written as

Example

Integer

Digits, with an optional leading `-`

`time_ms=3800`

Decimal

Digits with a decimal point

`ratio=99.9`

Token

An unquoted word

`pm=card`

String

Text in double quotes, with `\"` and `\\` escapes

`desc="hello world"`

Boolean

`?1` for true, `?0` for false

`enabled=?1`

Date

`@` followed by seconds since the Unix epoch, in UTC

`start_time=@1781280400` (not used in current `cb` members; see `start_time_epoch`)

### Forward compatibility[](#forward-compatibility)

Chargebee can add namespaces and keys to this header over time. To keep your integration working when that happens:

-   Ignore namespaces and keys that you don't recognize.
-   Don't depend on the order of members or parameters.
-   Don't assume that a namespace or key is present on every response.

## Namespaces[](#namespaces)

### Chargebee metrics[](#chargebee-metrics)

The `cb` member describes how Chargebee processed the request.

Key

Type

Description

`start_time_epoch`

Integer (seconds since the Unix epoch, UTC)

When Chargebee started processing the request. The value is whole seconds; use it for correlation with your own timings, not for sub-second timeline alignment.

`time_ms`

Integer (milliseconds)

Overall time that Chargebee took to process the request.

`tp_time_ms`

Integer (milliseconds)

Overall time spent in third-party integrations during the request, across all [`tp-` members](#third-party-integrations).

`res_wait_time_ms`

Integer (milliseconds)

Time the request spent waiting for a lock on a resource, for example because another request was changing the same customer or subscription at the same time.

### Third-party integrations[](#third-party-integrations)

A `tp-<integration_name>` member reports time spent in a third-party integration that you've configured for your site, for example `tp-stripe`, `tp-braintree`, or `tp-avalara`. A request that uses more than one integration has more than one `tp-` member, as in the [example header](#read-an-example-header).

Stripe, Braintree, and Avalara are reported today. Chargebee will report more integrations in future releases.

Key

Type

Description

`time_ms`

Integer (milliseconds)

Time spent in this integration.

`pm`

Token

Present only on payment gateway integrations. The payment method involved, for example `card`. Uses the same values as [`payment_source.type`](/docs/api/payment_sources/payment-source-object#type).

## Read an example header[](#read-an-example-header)

Member

What it tells you

`cb;start_time_epoch=1781280400`

Chargebee started processing the request at 2026-06-12 16:06:40 UTC.

`cb;time_ms=3800`

Chargebee took 3,800 ms to process the request.

`cb;tp_time_ms=1350`

1,350 ms of the request was spent in third-party integrations.

`cb;res_wait_time_ms=90`

The request waited 90 ms for a lock on a resource.

`tp-avalara;time_ms=730`

730 ms was spent in Avalara, for example to calculate tax.

`tp-stripe;pm=card;time_ms=620`

620 ms was spent in Stripe, processing a card payment.

If your application measured a longer end-to-end time than `cb;time_ms`, the difference may include network latency, time in your own code, or Chargebee-side queue time before processing started.

## Use the client libraries[](#use-the-client-libraries)

The client library sends `Prefer: chargebee-telemetry=include` on every request when **both** of the following are true:

-   You've configured a [telemetry adapter](/docs/api/opentelemetry).
-   You've turned on `preferChargebeeTelemetry`. It's off by default.

Setting `preferChargebeeTelemetry` without a telemetry adapter has no effect.

Support for response telemetry is rolling out in the Node.js and Java SDKs. Install a release that includes `preferChargebeeTelemetry` before you use this feature; minimum versions will be documented here when those releases ship.

The library parses `X-Chargebee-Telemetry` on both successful and failed responses and passes the values to your adapter as span attributes. A malformed header never fails the API call; the library records only the raw value.

If you've set your own `Prefer` header on a request, the library leaves it unchanged and doesn't add the telemetry preference. For example, if you send `Prefer: respond-async`, merge `chargebee-telemetry=include` into that header yourself, for example `Prefer: respond-async, chargebee-telemetry=include`.

The library maps the header to the following span attributes:

Header part

Span attribute

Example

Raw header value

`http.response.header.x-chargebee-telemetry`

The full header string

`cb` parameters

`chargebee.telemetry.cb.<key>`

`chargebee.telemetry.cb.time_ms` = `3800`

`tp-<integration_name>` parameters

`chargebee.telemetry.tp.<integration_name>.<key>`

`chargebee.telemetry.tp.stripe.pm` = `"card"`

Timing values and `start_time_epoch` are numbers, so you can filter, average, and chart them in your observability backend directly. For adapter setup and the other span attributes, see [OpenTelemetry integration](/docs/api/opentelemetry).

With cURL, add the header with `-H` and print the response headers with `-i`, as shown in [Quick start with response telemetry](#quick-start). To see the Node.js or Java setup, switch the language selector at the top of the left navigation to **Node.js** or **Java**. In a narrow window, open the selector from the settings icon in the header.

This client library doesn't parse response telemetry yet. Set the `Prefer: chargebee-telemetry=include` header on the requests that you want telemetry for, read the `X-Chargebee-Telemetry` response header from the HTTP response, and [parse it yourself](#parse-the-header-yourself).

## Parse the header yourself[](#parse-the-header-yourself)

If you aren't using a client library that supports response telemetry, keep the following in mind:

-   **Use an RFC 9651 parser.** Most languages have a library for Structured Field Values. Don't split the value on `,` and `;` yourself: string values can contain both characters inside quotes.
-   **Look the header up case-insensitively.** HTTP header names are case-insensitive, and many HTTP clients return them in lowercase, for example `x-chargebee-telemetry`.
-   **Treat telemetry as optional.** If the header is missing or can't be parsed, log the raw value and carry on. Never fail or retry an API call because of this header.
-   **Follow the [forward compatibility](#forward-compatibility) rules.** Ignore namespaces and keys that you don't recognize.

In practice Chargebee emits a flat List of members with tokens and integer parameters. Strings and inner lists are uncommon today, but a standards-based parser keeps you safe if the format expands.

## Best practices[](#best-practices)

-   **Request telemetry when you need it.** For example, turn it on for a sample of requests, or while you investigate a latency issue.
-   **Record it next to your own timings.** Compare `cb;time_ms` with the latency your application measured alongside the [example interpretation](#read-an-example-header).
-   **Use it for diagnostics only.** Don't build business logic, such as billing or retry decisions, on telemetry values.
-   **Watch for lock waits.** Sustained high `res_wait_time_ms` values can mean that several requests are changing the same resource, such as the same subscription, at the same time. If those requests come from your integration, serialize them.