SDKs
Python SDK
Installation
pip install levelfourClient Setup
Sync Client
from levelfour import LevelFour
client = LevelFour(
api_key="l4_live_...",
base_url="https://api.levelfour.ai",
timeout=30.0,
max_retries=2,
)With environment variable auto-detection:
client = LevelFour()The client supports context manager usage:
with LevelFour() as client:
summary = client.recommendations.get_savings_by_provider()Async Client
import asyncio
from levelfour import AsyncLevelFour
async def main():
async with AsyncLevelFour() as client:
summary = await client.recommendations.get_savings_by_provider()
asyncio.run(main())The async client accepts httpx.AsyncClient via the http_client parameter.
Constructor Options
| Parameter | Type | Default |
|---|---|---|
api_key | str | None | LEVELFOUR_API_KEY env var |
base_url | str | https://api.levelfour.ai |
timeout | float | 30.0 |
max_retries | int | 2 |
http_client | httpx.Client | None | Built-in |
headers | dict[str, str] | None | None |
Cloning with Modified Options
read_only_client = client.with_options(timeout=60.0)Recommendations
summary = client.recommendations.get_savings_by_provider()
potential = client.recommendations.get_potential_savings()
overview = client.recommendations.get_overview()
processing = client.recommendations.list_in_progress()
detail = client.recommendations.get("rec_123")
page = client.recommendations.list(
page=1,
page_size=50,
sort_by="monthly_savings",
sort_order="desc",
)Recommendations Audit
summary = client.recommendations.audit.get_summary()
page = client.recommendations.audit.list(
page=1,
page_size=50,
sort_by="monthly_savings",
sort_order="desc",
start="2025-01-01",
end="2025-03-31",
preset="6M",
provider="aws",
service=["EC2", "RDS"],
environment=["production"],
account_id=["123456789012"],
)Costs
summary = client.costs.get_summary()
breakdown = client.costs.list(
format="table",
period="2025-03",
provider_id="aws",
page=1,
page_size=50,
sort_by="cost",
sort_order="desc",
)
daily = client.costs.get_daily_costs(
start="2025-03-01T00:00:00.000Z",
end="2025-03-31T00:00:00.000Z",
)
monthly = client.costs.get_monthly_costs()Providers
providers = client.providers.list()
top = client.providers.get_top_recommendations("aws")
recs = client.providers.list_recommendations(
"aws",
page=1,
page_size=50,
sort_by="monthly_savings",
sort_order="desc",
service=["EC2"],
display_status=["available", "pending"],
)
overview = client.providers.get_recommendations_overview("aws")
filters = client.providers.get_recommendation_filters("aws")
savings = client.providers.list_realized_savings(
"aws",
page=1,
page_size=50,
preset="6M",
)
savings_summary = client.providers.get_realized_savings_summary("aws")
spending = client.providers.get_costs_summary("aws")
spending_filters = client.providers.get_costs_filters(
"aws",
start="2025-01-01T00:00:00.000Z",
end="2025-03-31T00:00:00.000Z",
)
spending_list = client.providers.list_costs(
"aws",
format="table",
page=1,
page_size=50,
)
timeline = client.providers.get_costs_timeline(
"aws",
start="2025-01-01T00:00:00.000Z",
end="2025-03-31T00:00:00.000Z",
)
potential = client.providers.get_potential_savings_summary("aws")
potential_list = client.providers.list_potential_savings(
"aws",
page=1,
page_size=50,
)API Keys
keys = client.api_keys.list()
new_key = client.api_keys.create(name="CI Pipeline", scope="read")
client.api_keys.revoke("key_123")
rotated = client.api_keys.rotate("key_123")Webhooks
endpoints = client.webhooks.list()
endpoint = client.webhooks.register(
url="https://example.com/webhook",
event_types=["recommendation.accepted", "optimization.completed"],
description="Production webhook",
)
client.webhooks.delete("ep_123")Auth
me = client.auth.get_whoami()Pagination
Methods that return paginated results return a SyncPager (or AsyncPager for the async client). You can iterate items automatically, iterate pages, or navigate manually.
Auto-iterate all items
for rec in client.recommendations.list(page_size=50):
print(rec.recommendation_id)Async auto-iterate
async for rec in await async_client.recommendations.list(page_size=50):
print(rec.recommendation_id)Iterate pages
for page in client.recommendations.list(page_size=50).iter_pages():
print(f"Page has {len(page.items)} items")Manual pagination
page = client.recommendations.list(page_size=50)
while page:
for item in page.items:
print(item)
page = page.next_page()See Pagination for more details.
Error Handling
from levelfour import LevelFour, NotFoundError, RateLimitError, LevelFourError
client = LevelFour()
try:
detail = client.recommendations.get("rec_nonexistent")
except NotFoundError as e:
print(f"Not found: {e.message}")
except RateLimitError as e:
print(f"Rate limited. Retry after: {e.retry_after}")
except LevelFourError as e:
print(f"API error {e.status_code}: {e.message}")All exceptions inherit from LevelFourError and expose status_code, code, message, and details attributes.
See Error Handling for the full exception hierarchy.
Webhook Verification
from levelfour.webhooks.verifier import WebhookVerifier, WebhookVerificationError
verifier = WebhookVerifier("whsec_your_signing_secret")
try:
payload = verifier.verify(
payload=request_body,
headers={
"webhook-id": headers["webhook-id"],
"webhook-timestamp": headers["webhook-timestamp"],
"webhook-signature": headers["webhook-signature"],
},
)
print(f"Verified event: {payload['type']}")
except WebhookVerificationError as e:
print(f"Verification failed: {e}")Custom timestamp tolerance (default is 300 seconds):
payload = verifier.verify(payload=body, headers=hdrs, tolerance_seconds=600)See Webhooks for event types and payload details.
Request Options
Override client defaults on a per-request basis:
from levelfour.core.request_options import RequestOptions
opts: RequestOptions = {
"timeout_in_seconds": 60,
"max_retries": 5,
"additional_headers": {"X-Request-Id": "abc123"},
}
summary = client.recommendations.get_savings_by_provider(request_options=opts)| Option | Type | Description |
|---|---|---|
timeout_in_seconds | int | Override request timeout |
max_retries | int | Override max retry attempts |
additional_headers | dict[str, Any] | Extra headers for this request |
additional_query_parameters | dict[str, Any] | Extra query parameters |
additional_body_parameters | dict[str, Any] | Extra body parameters |