A Python SDK for Clever Cloud.
You can add it to your project using pip or uv:
pip install clevercloud-sdk
uv add clevercloud-sdkfrom clever_cloud import CleverCloudClient, ApiTokenCredentials
async with CleverCloudClient(ApiTokenCredentials(token="...")) as client:
profile = await client.get_profile()
# name is optional on the API side, hence the fallback
print(f"Hello, {profile.name or profile.email}!")You can also use OAuth credentials:
from clever_cloud import OAuthCredentials
credentials = OAuthCredentials(
consumer_key="...",
consumer_secret="...",
token="...",
secret="...",
)
async with CleverCloudClient(credentials) as client:
...Every OAuth request is signed with HMAC-SHA512 over its method, URL, query
string and form body, with a timestamp, a nonce and the OAuth version, so an
intercepted Authorization header cannot be replayed. To talk to a deployment
that still requires the legacy format, select the compatibility mode explicitly:
from clever_cloud import SignatureMethod
credentials = OAuthCredentials(..., signature_method=SignatureMethod.PLAINTEXT)The browser flow is the supported way to obtain credentials:
import webbrowser
from clever_cloud import OAuthConsumer, OAuthDance
with OAuthDance(OAuthConsumer(key="...", secret="..."),
callback_url="https://my-app.example/callback") as dance:
request_token = dance.get_request_token()
webbrowser.open(dance.get_authorization_url(request_token))
# ... your callback receives the redirect; pass its full URL back:
verifier = dance.parse_callback_url(callback_url, request_token)
credentials = dance.get_access_token(request_token, verifier)parse_callback_url() checks that the callback carries the token this dance
requested before accepting the verifier. OAuthDance.login() remains available
for browser-less automation, but it drives the console's internal session
endpoints with the account password and is not a supported OAuth flow.
All errors derive from CleverCloudError:
| Exception | Raised when |
|---|---|
AuthenticationError |
HTTP 401: credentials missing or invalid |
AuthorizationError |
HTTP 403: credentials valid, access denied |
NotFoundError |
HTTP 404 |
RateLimitError |
HTTP 429, exposes retry_after |
HttpError |
Any other HTTP error status |
TransportError |
Network, timeout or TLS failure |
InvalidResponseError |
Undecodable body, unexpected redirect, or a payload that does not match the endpoint's contract |
OAuthError |
Failure during the OAuth dance, with its step |
Response bodies attached to exceptions are truncated, so a large or sensitive error payload does not end up whole in your logs.
Idempotent requests (GET, HEAD, OPTIONS, PUT, DELETE) are retried on HTTP 429,
502, 503, 504 and on network errors, using exponential backoff with jitter and
honouring Retry-After. Each attempt is signed again with a fresh nonce.
async with CleverCloudClient(credentials, max_retries=0) as client: # opt out
...The client accepts a custom CA bundle and a client certificate for mutual TLS, useful when targeting an API behind a private PKI or requiring client authentication:
async with CleverCloudClient(
credentials,
ca_bundle="/path/to/ca-bundle.pem",
client_cert=("/path/to/client.crt", "/path/to/client.key"),
) as client:
...Both are loaded into an ssl.SSLContext, so no deprecated HTTPX argument is
used. verify_ssl=False disables server certificate verification entirely (not
recommended outside of local testing).
A clear-text http:// base URL is refused by default, because credentials
would travel unencrypted; pass allow_insecure_http=True to override it against
a local development server.
Models are parsed strictly: a response missing a field the endpoint is
documented to return raises InvalidResponseError rather than producing a model
filled with empty strings, zeroes or a fabricated timestamp. Optional fields are
typed | None, dates are timezone-aware UTC datetimes, and collections are
tuples, so frozen=True models are immutable all the way down.
This SDK is still a work in progress, but it already provides the following features:
- Get user profile
- List instance types (cached per client)
- Create application
- Redeploy application
- Create TCP redirection
- List domains
- Get primary domain
- Custom CA bundle and mTLS client certificate support
- Automatic retries with backoff on transient failures
- NetworkGroups: create / get / delete / search, manage members, peers and external peers
Attach an application as a member of an existing NetworkGroup:
from clever_cloud import MemberKind
await client.create_networkgroup_member(
owner_id="orga_xxx",
ng_id="ng_xxx",
member_id="app_xxx",
domain_name="my-app.m.ng_xxx.members",
kind=MemberKind.APPLICATION,
label="my-app",
)uv sync --extra dev
uv run pytest # test suite, no network access
uv run ruff check . # lint
uv run mypy # strict type checkingSee CHANGELOG.md for release notes, including breaking changes, and RELEASING.md for how a new version is published.
Apache 2.0 - See LICENSE for details.