Note
We are trialing a Discord server for developers building with Chargebee. Limited spots are open on a first-come basis. Join here if interested.
This is the official Python library for integrating with Chargebee.
- 📘 For a complete reference of available APIs, check out our API Documentation.
- 🧪 To explore and test API capabilities interactively, head over to our API Explorer.
If you're upgrading from an older version please refer to the Migration Guide
- Python 3.11+
Install the latest version of the library with pip:
pip install chargebeeInstall from source with:
python setup.py installSee our Python API Reference.
The package needs to be configured with your site's API key, which is available under Configure Chargebee Section. Refer here for more details.
fromchargebeeimportChargebeecb_client=Chargebee(api_key="", site="")fromchargebeeimportChargebeecb_client=Chargebee(api_key="api_key", site="site")
cb_client.update_read_timeout_secs(3000)
cb_client.update_connect_timeout_secs(5000)fromchargebeeimportChargebeecb_client=Chargebee(api_key="api_key", site="site")
cb_client.update_export_retry_delay_ms(3000)
cb_client.update_time_travel_retry_delay_ms(5000)# Create a Customerresponse=cb_client.Customer.create(
cb_client.Customer.CreateParams(
first_name="John",
last_name="Doe",
email="john@test.com",
locale="fr-CA",
billing_address=cb_client.Customer.BillingAddress(
first_name="John",
last_name=" Doe",
line1="PO Box 9999",
city="Walnut",
state="California",
zip="91789",
country="US",
),
)
)
customer=response.customercard=response.cardStarting with version 3.9.0, the Chargebee Python SDK can optionally be configured to use an asynchronous HTTP client which uses asyncio to perform non-blocking requests. This can be enabled by passing the use_async_client=True argument to the constructor:
cb_client=Chargebee(api_key="api_key", site="site", use_async_client=True)When configured to use the async client, all model methods return a coroutine, which will have to be awaited to get the response:
asyncdefget_customers():
response=awaitcb_client.Customer.list(
cb_client.Customer.ListParams(first_name=Filters.StringFilter(IS="John"))
)
returnresponseNote: The async methods will have to be wrapped in an event loop during invocation. For example, the asyncio.run method can be used to run the above example:
importasyncioresponse=asyncio.run(get_customers())For pagination, offset is the parameter that is being used. The value used for this parameter must be the value returned in next_offset parameter from the previous API call.
fromchargebeeimportFiltersresponse=cb_client.Customer.list(
cb_client.Customer.ListParams(first_name=Filters.StringFilter(IS="John"))
)
offset=response.next_offsetprint(offset)There are two variants of enums in chargebee,
- Global enums - These are defined globally and can be accessed across resources.
- Resource specific enums - These are defined within a resource and can be accessed using the resource class name.
# Global Enumimportchargebeeresponse=cb_client.Customer.create(
cb_client.Customer.CreateParams(
first_name="John",
auto_collection=chargebee.AutoCollection.ON, # global enum
)
)
print(response.customer)# Resource Specific Enumresponse=cb_client.Customer.change_billing_date(
cb_client.Customer.ChangeBillingDateParams(
first_name="John",
billing_day_of_week=cb_client.Customer.BillingDayOfWeek.MONDAY, # resource specific enum
)
)
print(response.customer)response=cb_client.Customer.create(
cb_client.Customer.CreateParams(
first_name="John",
cf_host_url="https://john.com", # `cf_host_url` is a custom field in Customer object
)
)
print(response.customer.cf_host_url)Idempotency keys are passed along with request headers to allow a safe retry of POST requests.
response=cb_client.Customer.create(
cb_client.Customer.CreateParams(
first_name="John",
last_name="Doe",
email="john@test.com",
locale="fr-CA",
billing_address=cb_client.Customer.BillingAddress(
first_name="John",
last_name=" Doe",
line1="PO Box 9999",
city="Walnut",
state="California",
zip="91789",
country="US",
),
),
None,
{"chargebee-idempotency-key": "<<UUID>>"}, # Replace <<UUID>> with a unique string
)
customer=response.customercard=response.cardresponseHeaders=response.headers# Retrieves response headersprint(responseHeaders)
idempotencyReplayedValue= (
response.is_idempotency_replayed
) # Retrieves Idempotency replayed header valueprint(idempotencyReplayedValue)The response from the previous API call must be passed as an argument for wait_for_export_completion() or wait_for_time_travel_completion()
# Wait For Export CompletionfromchargebeeimportFiltersresponse=cb_client.Export.customers(
cb_client.Export.CustomersParams(
customer=cb_client.Export.CustomersCustomerParams(
first_name=Filters.StringFilter(IS="John")
)
)
)
print(cb_client.Export.wait_for_export_completion(response.export))Chargebee's SDK includes built-in retry logic to handle temporary network issues and server-side errors. This feature is disabled by default but can be enabled when needed.
- Automatic retries for specific HTTP status codes: Retries are automatically triggered for status codes
500,502,503, and504. - Exponential backoff: Retry delays increase exponentially to prevent overwhelming the server.
- Rate limit management: If a
429 Too Many Requestsresponse is received with aRetry-Afterheader, the SDK waits for the specified duration before retrying.Note: Exponential backoff and max retries do not apply in this case.
- Customizable retry behavior: Retry logic can be configured using the
retryConfigparameter in the environment configuration.
You can enable and configure the retry logic by passing a retryConfig object when initializing the Chargebee environment:
fromchargebeeimportChargebeefromchargebee.retry_configimportRetryConfigretry_config=RetryConfig(enabled=True, max_retries=5, delay_ms=1000, retry_on=[500])
cb_client=Chargebee(api_key="api_key", site="site")
cb_client.update_retry_config(retry_config)
# ... your Chargebee API operations ...You can enable and configure the retry logic for rate-limit by passing a retryConfig object when initializing the Chargebee environment:
fromchargebeeimportChargebeefromchargebee.retry_configimportRetryConfigretry_config=RetryConfig(enabled=True, max_retries=5, delay_ms=1000, retry_on=[429])
cb_client=Chargebee(api_key="api_key", site="site")
cb_client.update_retry_config(retry_config)
# ... your Chargebee API operations ...Optional add-on. Existing integrations do not need any changes — if you never set a telemetry adapter, API calls behave exactly as before.
Pass a telemetry_adapter when you want Chargebee API calls traced in your observability stack (Datadog, Splunk, Honeycomb, Jaeger, etc.). OpenTelemetry is not bundled with chargebee — install and configure OTel (or your APM SDK) in your application, implement TelemetryAdapter, and wire it on the client.
The SDK builds standardized span attributes (context.start_attributes, result.end_attributes) following stable OpenTelemetry HTTP semantic conventions (url.full, http.request.method, http.response.status_code, server.address, error.type) plus Chargebee-specific chargebee.* attributes (see chargebee.telemetry.TelemetryAttributeKeys).
Span names follow chargebee.{resource}.{operation} (e.g. chargebee.subscription.create). One span is created per SDK API call; retries reuse the same span. Adapter failures are logged and never affect the underlying API request.
Pass telemetry_adapter when constructing Chargebee, or call update_telemetry_adapter() on an existing client. Each new Chargebee(...) instance gets its own environment — set the adapter on every client you use for telemetry.
To pass custom chargebee-* headers (promoted to http.request.header.chargebee-* span attributes), include them in the headers argument on resource methods.
pip install chargebee opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp-proto-grpcConfigure OpenTelemetry at app startup, then pass your adapter:
# App startup — configure oncefromopentelemetryimporttracefromopentelemetry.exporter.otlp.proto.grpc.trace_exporterimportOTLPSpanExporterfromopentelemetry.sdk.resourcesimportResourcefromopentelemetry.sdk.traceimportTracerProviderfromopentelemetry.sdk.trace.exportimportBatchSpanProcessorprovider=TracerProvider(resource=Resource.create({"service.name": "billing-service"}))
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(provider)fromchargebeeimport (
Chargebee,
RequestTelemetryContext,
RequestTelemetryResult,
TelemetryAdapter,
)
fromopentelemetryimporttracefromopentelemetry.traceimportSpanKind, Status, StatusCodeclassOtelTelemetryAdapter:
def__init__(self, tracer):
self._tracer=tracerdefon_request_start(self, context: RequestTelemetryContext, request_headers: dict):
span=self._tracer.start_span(
context.span_name,
kind=SpanKind.CLIENT,
attributes=dict(context.start_attributes),
)
# Inject W3C trace context into outbound headersfromopentelemetry.propagateimportinjectfromopentelemetry.traceimportset_span_in_contextinject(request_headers, context=set_span_in_context(span))
returnspandefon_request_end(self, handle, result: RequestTelemetryResult):
ifhandleisNone:
returnspan=handleforkey, valueinresult.end_attributes.items():
span.set_attribute(key, value)
ifresult.error:
span.set_status(Status(StatusCode.ERROR, result.error.message))
else:
span.set_status(Status(StatusCode.OK))
span.end()
cb_client=Chargebee(
api_key="{{api-key}}",
site="{{site}}",
telemetry_adapter=OtelTelemetryAdapter(trace.get_tracer("chargebee-python")),
)Spans are exported by your own OpenTelemetry setup, so they flow to whatever backend you've configured (Datadog, Splunk, Honeycomb, Jaeger, etc.). The Chargebee config above stays the same regardless of backend — refer to your APM vendor's OpenTelemetry/OTLP documentation for exporter endpoints.
If you find any bugs or have any feedback, open an issue in this repository or email it to dx@chargebee.com
See the LICENSE file.