datadog-api-client review
datadog-api-client 2.59.0 is Datadog's generated Python client for the public v1 and v2 APIs. It gives automation code typed models, endpoint classes, pagination helpers, retry controls, and synchronous, threaded, or optional asyncio transports. The 2.59.0 schema adds CI Visibility GitHub account calls, an LLM Observability alert monitor type, deployment-gate fields, and maintenance-update operations. It manages Datadog resources and sends API requests. It does not collect traces like ddtrace or run as the Datadog Agent. Our import check completed in 0.46 seconds, and the package ships py.typed metadata for type checkers.
datadog-api-client 2.59.0 installed in 1.5 seconds, occupied 46 MB across 6 packages, imported in 0.46 seconds, and produced 0 pip-audit findings in our sandbox. Install it for broad Python automation against Datadog's v1 and v2 APIs; use direct HTTP for a tiny integration or infrastructure as code when resource state matters more than imperative calls.
We installed it
| Install | ✓ · 1.5s | 6 packages on disk · 46 MB |
| Import | ✓ | import datadog_api_client in 0.46s · pure Python · py.typed · requires Python >=3.8 |
| Known vulns | 0 | (pip-audit) |
Answers from our run
Does datadog-api-client install cleanly?
Yes. In a fresh container with an empty cache, pip install datadog-api-client finished in 2 seconds, leaving 6 packages and 46 MB on disk. pip-audit reported no known vulnerabilities.
What does datadog-api-client need to run?
Python >=3.8, and nothing compiled: it is pure Python. In our run import datadog_api_client succeeded in 0.46s, and the package ships py.typed for type checkers.
datadog-api-client or datadog: which should you use?
datadog: Use the older datadogpy client when maintaining an existing integration built around its smaller API surface. datadog-api-client 2.59.0 installed in 1.5 seconds, occupied 46 MB across 6 packages, imported in 0.46 seconds, and produced 0 pip-audit findings in our sandbox.
When should you not use datadog-api-client?
You need application tracing or runtime instrumentation. This client calls Datadog APIs; ddtrace or OpenTelemetry handles traces and spans.
Use it if
- A Python job creates or audits Datadog monitors, dashboards, incidents, users, integrations, or other API resources.
- Generated request and response models are preferable to maintaining JSON payloads and authentication headers by hand.
- The job needs Datadog's pagination helpers, regional site selection, proxy settings, or explicit retry policies.
- One codebase needs blocking calls today and an asyncio or threaded transport for another workload.
- You need application tracing or runtime instrumentation. This client calls Datadog APIs; ddtrace or OpenTelemetry handles traces and spans.
- The script makes one small, stable HTTP call. Our install left 46 MB across 6 packages, so requests or httpx can be easier to inspect.
- Generated API churn is unacceptable. Version 2.59.0 adds operations and fields while removing a RUM rate-limit operation and documenting a Status Pages field deprecation.
- You cannot provision both credential types. The README loads DD_API_KEY and DD_APP_KEY, and endpoint access still depends on application-key scopes.
- The organization site cannot be configured explicitly. The README requires changing server_variables for non-default sites, or valid keys can be sent to the wrong Datadog host.
Setup reality
We installed datadog-api-client 2.59.0 in a fresh Python 3.12 Bookworm container. The install finished in 1.5 seconds and left 6 packages using 46 MB. pip-audit found 0 known vulnerabilities. The package is pure Python, declares 20 direct dependencies in our package inspection, requires Python 3.8 or newer, and includes py.typed. Importing datadog_api_client worked in 0.46 seconds.
Configuration reads DD_API_KEY and DD_APP_KEY by default. Keep both in a secret store and give the application key only the scopes its calls require. Organizations outside the default site must set configuration.server_variables['site'] before opening the client. Version 2.59.0 exposes both v1 and v2 namespaces, so copy the import path from the current endpoint example instead of guessing which generation owns a resource.
ApiClient is a context manager; reuse one client for a batch and let the context close its connection pool. Retry is off until enabled. The built-in switch targets HTTP 429 and defaults to 3 retries. A supplied urllib3 Retry object overrides enable_retry, retry_backoff_factor, and max_retries. Limit automatic retries of writes unless the endpoint has an idempotency contract. Debug logging can include request headers and bodies.
The base install is synchronous. AsyncApiClient requires the async extra and an async with block. ThreadedApiClient returns AsyncResult objects, so each call needs .get() to surface the response or exception. Pagination helpers make additional HTTP requests as iteration advances. Unstable operations refuse to run until their method name is enabled in configuration.unstable_operations, and their generated signatures can change in later releases.
Patterns
Check an API key validate-api-key
from datadog_api_client import ApiClient, Configuration
from datadog_api_client.v1.api.authentication_api import AuthenticationApi
with ApiClient(Configuration()) as client:
result = AuthenticationApi(client).validate()
print(result.valid)Configuration reads DD_API_KEY and DD_APP_KEY. A successful validation does not grant scopes that the application key lacks.
Send calls to the EU site choose-site
from datadog_api_client import ApiClient, Configuration
config = Configuration()
config.server_variables['site'] = 'datadoghq.eu'
with ApiClient(config) as client:
run_calls(client)server_variables must match the site assigned to the organization. The default host does not reach an EU account.
Read monitors page by page list-monitors
from datadog_api_client import ApiClient, Configuration
from datadog_api_client.v1.api.monitors_api import MonitorsApi
with ApiClient(Configuration()) as client:
api = MonitorsApi(client)
for monitor in api.list_monitors_with_pagination(
monitor_tags='service:checkout', page_size=100
):
print(monitor.id, monitor.name)The pagination iterator performs more HTTP requests as it is consumed. Breaking early avoids fetching later pages.
Create a log alert create-monitor
from datadog_api_client import ApiClient, Configuration
from datadog_api_client.v1.api.monitors_api import MonitorsApi
from datadog_api_client.v1.model.monitor import Monitor
from datadog_api_client.v1.model.monitor_type import MonitorType
body = Monitor(
name='Checkout errors',
type=MonitorType.LOG_ALERT,
query='logs("service:checkout status:error").index("main").rollup("count").last("5m") > 10',
message='Checkout errors exceeded the limit',
tags=['service:checkout', 'managed-by:python'],
)
with ApiClient(Configuration()) as client:
created = MonitorsApi(client).create_monitor(body=body)The model checks payload shape locally. Datadog still validates the query, permissions, and referenced indexes on the server.
Change an existing monitor update-monitor
from datadog_api_client.v1.api.monitors_api import MonitorsApi
from datadog_api_client.v1.model.monitor_update_request import MonitorUpdateRequest
body = MonitorUpdateRequest(
name='Checkout errors',
message='Page the checkout owner',
)
updated = MonitorsApi(client).update_monitor(monitor_id=monitor_id, body=body)update_monitor targets the v1 API and mutates a live resource. Read the existing monitor first if omitted fields must be preserved.
Retry HTTP 429 responses retry-rate-limits
from datadog_api_client import ApiClient, Configuration
config = Configuration()
config.enable_retry = True
config.max_retries = 5
with ApiClient(config) as client:
run_calls(client)The built-in retry switch covers HTTP 429. Five attempts can repeat a write, so check the operation's idempotency behavior first.
Restrict retries to reads set-retry-policy
import urllib3
from datadog_api_client import ApiClient, Configuration
policy = urllib3.util.Retry(
total=4,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=['GET'],
)
config = Configuration(retry_policy=policy)
with ApiClient(config) as client:
read_resources(client)retry_policy takes precedence over the three built-in retry settings. Restricting methods prevents automatic replay of POST and PATCH calls.
List dashboards with asyncio use-async-client
import asyncio
from datadog_api_client import AsyncApiClient, Configuration
from datadog_api_client.v1.api.dashboards_api import DashboardsApi
async def main():
async with AsyncApiClient(Configuration()) as client:
dashboards = await DashboardsApi(client).list_dashboards()
print(dashboards)
asyncio.run(main())AsyncApiClient needs the datadog-api-client[async] extra. The base installation does not include its async transport.
Resolve a threaded API call use-threaded-client
from datadog_api_client import Configuration, ThreadedApiClient
from datadog_api_client.v1.api.dashboards_api import DashboardsApi
with ThreadedApiClient(Configuration()) as client:
pending = DashboardsApi(client).list_dashboards()
dashboards = pending.get()Threaded calls return AsyncResult. The response and any request exception appear only when .get() is called.
Opt into an unstable call enable-unstable-operation
from datadog_api_client import ApiClient, Configuration
from datadog_api_client.v2.api.incidents_api import IncidentsApi
config = Configuration()
config.unstable_operations['list_incidents'] = True
with ApiClient(config) as client:
for incident in IncidentsApi(client).list_incidents_with_pagination():
print(incident.id)The dictionary key is the generated method name. Unstable signatures and models can change in a later package release.
Route traffic through a proxy configure-proxy
from datadog_api_client import ApiClient, Configuration
config = Configuration()
config.proxy = 'http://proxy.internal:8080'
with ApiClient(config) as client:
run_calls(client)Configuration accepts a proxy URL. Supply proxy credentials through approved secret handling rather than committing them in source.
Log a bounded API failure handle-api-error
from datadog_api_client.exceptions import ApiException
try:
run_calls(client)
except ApiException as error:
logger.error(
'Datadog API request failed',
extra={'status': error.status},
)
raiseApiException can include response headers and a parsed body. Avoid logging those fields until queries, user data, and tokens are redacted.
Alternatives
| Package | Registry | Pick it when |
|---|---|---|
| datadog | PyPI | Use the older datadogpy client when maintaining an existing integration built around its smaller API surface. |
| requests | PyPI | Use explicit HTTP for one or two stable endpoints when generated models add more code than they remove. |
| pulumi-datadog | PyPI | Use Pulumi when Datadog resources should be declarative, reviewed, and tracked in infrastructure state. |
More utils guides
lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →
How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.

