Coolipy
The (un)official Python client for Coolify.
Coolipy wraps the Coolify REST API with typed models and ships synchronous and asynchronous clients in a single package. Every request body and every response body is a pydantic model — no raw dicts, no manual JSON.
- Lib docs: https://coolipydocs.gabrielbocchini.com.br/
- Coolify API docs: https://coolify.io/docs/api
Installation
pip install coolipy
# or
uv add coolipy
Requires Python 3.10+. Runtime dependencies: httpx and pydantic.
Features
- Sync and async clients in one package (
Coolipy/AsyncCoolipy). - Typed models for every request and response body.
- A single
CoolipyAPIResponse[T]envelope:status_code, validateddata, andheaders. - Typed exceptions that carry the API's validation errors.
- Built on
httpxwith a dependency-injected transport (easy to mock in tests).
Quick start
Synchronous
from coolipy import Coolipy
client = Coolipy(
coolify_api_key="YOUR_API_TOKEN",
coolify_endpoint="your-coolify-instance.com",
http_protocol="https",
coolify_port=8000,
)
resp = client.version()
print(resp.status_code) # 200
print(resp.data) # '4.3.17'
client.close()
Use it as a context manager to close automatically:
with Coolipy("YOUR_API_TOKEN", "your-coolify-instance.com") as client:
print(client.health().data) # 'OK'
Asynchronous
import asyncio
from coolipy import AsyncCoolipy
async def main() -> None:
async with AsyncCoolipy("YOUR_API_TOKEN", "your-coolify-instance.com") as client:
resp = await client.version()
print(resp.data)
asyncio.run(main())
Resources
Each resource is a sub-client on the client instance:
| Sub-client | What it manages |
|---|---|
client.projects |
Projects and environments |
client.servers |
Servers, destinations, resources, validation |
client.applications |
Applications (git / docker image / dockerfile), envs, storages, tags, scheduled tasks |
client.databases |
PostgreSQL, MySQL, MariaDB, MongoDB, Redis, ClickHouse, Dragonfly, KeyDB |
client.services |
Docker Compose services (incl. per-service apps and databases) |
client.deployments |
Deployments and deploy |
client.teams |
Teams, members, shared environment variables |
client.tags |
Global tags |
client.s3_storages |
S3 storage backends |
client.security |
Private keys |
Responses
Every method returns a CoolipyAPIResponse with three fields:
| Field | Type | Description |
|---|---|---|
status_code |
int |
HTTP status code. |
data |
T |
Parsed body, validated against a model. |
headers |
dict[str, str] |
Response headers. |
resp = client.enable_api()
print(resp.data) # SystemMessage(message='API enabled.')
print(resp.data.message) # 'API enabled.'
Models
Every request and response body is a pydantic model deriving from CoolipyBaseModel. Response models are tolerant: every field is optional and unknown fields are ignored, so they never fail against a live instance.
- Request models —
*Create/*Updateclasses you build and pass in (e.g.ProjectCreateModel,ApplicationDockerImageModelCreate,PostgreSQLModelCreate). Unset fields are omitted from the request body. - Response models —
*Modelclasses returned inresp.data(e.g.ProjectModel,ServerModel,ApplicationModel).
Enums mirror the API's string-constrained fields:
from coolipy.enums import BuildPack, ProxyType, ServiceType
BuildPack.NIXPACKS.value # 'nixpacks'
BuildPack.RAILPACK.value # 'railpack'
ProxyType.NONE.value # 'none'
Usage examples
All examples below were captured against a live Coolify instance (v4.3.17).
Projects
from coolipy.models.projects import ProjectCreateModel
resp = client.projects.create(
ProjectCreateModel(name="My Project", description="Created with Coolipy")
)
print(resp.status_code) # 201
print(resp.data) # UUIDResponse(uuid='og888os')
resp = client.projects.list()
print(resp.data)
# [
# ProjectModel(id=7, uuid='mawhjk3svlsd9v9dujlck4cq',
# name='coolipy-smoke-apps-async', description=''),
# ]
Servers
resp = client.servers.list()
server = resp.data[0]
print(server)
# ServerModel(
# uuid='g7jdko9weqgokkm7m9lhkzqb',
# name='localhost',
# ip='host.docker.internal',
# user='root',
# port=22,
# is_coolify_host=True,
# is_reachable=True,
# is_usable=True,
# proxy={'redirect_enabled': True},
# settings=ServerSetting(id=1, concurrent_builds=2, ...),
# )
Applications — from a ready-to-go Docker image
from coolipy.models.applications import ApplicationDockerImageModelCreate
app = ApplicationDockerImageModelCreate(
project_uuid="your_project_uuid",
server_uuid="your_server_uuid",
environment_name="production",
docker_registry_image_name="nginx",
docker_registry_image_tag="latest",
name="my-nginx",
ports_exposes="80",
)
resp = client.applications.create(app)
print(resp.data) # UUIDResponse(uuid='6zacuhbss0pnxtjihzmxolds')
resp = client.applications.list()
app = resp.data[0]
print(app.docker_registry_image_name, app.build_pack, app.fqdn)
# nginx dockerimage http://6zacuhbss0pnxtjihzmxolds.178.104.56.250.sslip.io
Applications can also be created from a public/private git repository, a deploy key, or a Dockerfile — ApplicationPublicModelCreate, ApplicationPrivateGHModelCreate, ApplicationPrivateDeployKeyModelCreate, ApplicationDockerfileModelCreate.
Databases
from coolipy.models.databases import PostgreSQLModelCreate
db = PostgreSQLModelCreate(
project_uuid="your_project_uuid",
server_uuid="your_server_uuid",
environment_name="production",
postgres_user="dbuser",
postgres_password="password",
postgres_db="mydatabase",
name="My PostgreSQL DB",
)
resp = client.databases.create(db)
print(resp.data) # UUIDResponse(uuid='...')
Eight database types are supported: PostgreSQLModelCreate, MySQLModelCreate, MariaDBModelCreate, MongoDBModelCreate, RedisModelCreate, ClickhouseModelCreate, DragonflyModelCreate, KeyDBModelCreate.
Services
from coolipy.models.services import ServiceCreateModel
service = ServiceCreateModel(
name="my-service",
project_uuid="your_project_uuid",
server_uuid="your_server_uuid",
environment_name="production",
docker_compose_raw="<base64 docker-compose.yml>",
)
resp = client.services.create(service)
Teams & members
resp = client.teams.current()
print(resp.data)
# TeamModel(id=0, name='Root Team', personal_team=True, ...)
resp = client.teams.current_members()
print(resp.data)
# [UserModel(id=0, name='Gabriel B. Bocchini', email='gabrielbocchini@gmail.com', ...)]
Tags, private keys, S3 storages
resp = client.tags.list()
print(resp.data) # [Tag(uuid='cz8op2sw7b0ysjvjq9ykeips', name='coolipy-smoke-tag', ...)]
resp = client.security.list()
print(resp.data) # [PrivateKeyModel(uuid='...', name="localhost's key", is_git_related=False, ...)]
resp = client.s3_storages.list()
print(resp.data) # []
Deployments
resp = client.deployments.deploy(tag="my-tag", force=True)
print(resp.data)
# DeployResponse(deployments=[DeploymentEntry(message='...', resource_uuid='...', deployment_uuid='...')])
Async
Every method has an async equivalent on AsyncCoolipy:
async with AsyncCoolipy("YOUR_API_TOKEN", "your-coolify-instance.com") as client:
resp = await client.projects.list()
print(resp.data)
Errors
Non-2xx responses raise CoolipyHTTPError, which carries the API's error details:
from coolipy.exceptions import CoolipyHTTPError
try:
client.version()
except CoolipyHTTPError as exc:
print(exc.status_code) # e.g. 401
print(exc.message) # e.g. "Unauthenticated."
print(exc.errors) # field-level messages for 422 responses
CoolipyError is the base class; CoolipyConfigError and CoolipyValidationError cover client-side problems.
Configuration
Both clients take the same arguments:
| Argument | Type | Default | Description |
|---|---|---|---|
coolify_api_key |
str |
— | Bearer token for the Coolify API. |
coolify_endpoint |
str |
— | Hostname/IP of the Coolify instance. |
coolify_port |
int |
8000 |
Port (ignored when omit_port=True). |
omit_port |
bool |
False |
Build the base URL without a port. |
http_protocol |
str |
"http" |
"http" or "https". |
timeout |
float |
30.0 |
Request timeout in seconds. |
Status
Coolipy 1.0.0 covers the full token-gated Coolify API surface — applications, databases, services, servers, projects, environments, teams, deployments, tags, S3 storages, private keys, shared envs, and the system endpoints — in both sync and async flavours. The suite is verified against a live Coolify instance via the smoke tests in tests/smoke/.
Development
uv sync --extra dev
uv run pytest
uv run ruff check . && uv run ruff format --check .
uv run mypy coolipy
Run the real-world smoke tests against a live instance (no secrets committed — provided via env vars):
COOLIPY_API_KEY=... COOLIPY_ENDPOINT=... uv run pytest -m smoke
Regenerate the API documentation (rendered with pdoc):
pdoc coolipy \
coolipy.async_client coolipy.client coolipy.enums coolipy.exceptions \
coolipy.models.applications coolipy.models.base coolipy.models.common \
coolipy.models.databases coolipy.models.deployments coolipy.models.projects \
coolipy.models.s3_storages coolipy.models.security coolipy.models.servers \
coolipy.models.services coolipy.models.system coolipy.models.teams \
coolipy.resources.applications coolipy.resources.databases coolipy.resources.deployments \
coolipy.resources.projects coolipy.resources.s3_storages coolipy.resources.security \
coolipy.resources.servers coolipy.resources.services coolipy.resources.tags \
coolipy.resources.teams \
-o html
Contributing
- Before opening a pull request or issue, check whether it belongs at this client level or the Coolify REST API.
- Fork this repo and submit a pull request.
- Respect Python PEPs and type inference.
- Ship unit tests with any change.
- No breaking changes unless required by the Coolify REST API.
License
Apache License 2.0 — see LICENSE.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file coolipy-1.0.0.tar.gz.
File metadata
- Download URL: coolipy-1.0.0.tar.gz
- Upload date:
- Size: 35.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47023a73cb18a5fb06f3503c5e95b99d6a70d51597d627f9f36095bfa5d657ba
|
|
| MD5 |
532eb94ae68a0c73592d18b319e2b95e
|
|
| BLAKE2b-256 |
fbfda5d89061408cfaf3a50f195aafec5b547b21e05105f93f3505a95d8560d3
|
File details
Details for the file coolipy-1.0.0-py3-none-any.whl.
File metadata
- Download URL: coolipy-1.0.0-py3-none-any.whl
- Upload date:
- Size: 43.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea21c3a545255cc750a89d08c2af38f7898d46053a11be6b3f7b3d8ab48cc320
|
|
| MD5 |
a8be988003a1e13460f14fdc1fdef49a
|
|
| BLAKE2b-256 |
d15fedfd079dfcf29ed17002b8e4b49c81e610d13c9232b9cbcabc8d192478ea
|