coolipy
The (un)official, fully-typed Python client for the Coolify API.
coolipy wraps the complete token-gated Coolify REST API in a single package with
two clients — a synchronous :class:Coolipy and an asynchronous :class:AsyncCoolipy —
both backed by a dependency-injected httpx transport.
Every request body and every response body is a pydantic model:
there is no raw JSON to build or parse by hand.
Install
pip install coolipy
# or
uv add coolipy
Requires Python 3.10+.
Quick start
Synchronous:
from coolipy import Coolipy
with Coolipy("YOUR_API_TOKEN", "your-coolify-instance.com") as client:
print(client.health().data) # 'OK'
print(client.version().data) # '4.3.17'
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.projects.list()
print(resp.data)
asyncio.run(main())
Example — deploy an application
from coolipy import Coolipy
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",
)
with Coolipy("YOUR_API_TOKEN", "your-coolify-instance.com") as client:
resp = client.applications.create(app)
print(resp.data) # UUIDResponse(uuid='6zacuhbss0pnxtjihzmxolds')
Example — provision a database
from coolipy import Coolipy
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",
)
with Coolipy("YOUR_API_TOKEN", "your-coolify-instance.com") as client:
resp = client.databases.create(db)
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 |
System endpoints live on the client directly: version(), health(), enable_api(),
disable_api(), enable_mcp(), disable_mcp().
Responses
Every method returns a CoolipyAPIResponse[T] with three fields: status_code, validated
data, and headers. Non-2xx responses raise CoolipyHTTPError, which carries the API's
error details — see CoolipyError, CoolipyConfigError and CoolipyValidationError for the
client-side failures.
See the full guide for copy-paste examples of every resource, in both sync and async flavours.
Sub-modules
coolipy.async_client-
Asynchronous coolipy client.
coolipy.client-
Synchronous coolipy client.
coolipy.enums-
Enums mirroring the string-constrained fields of the Coolify API …
coolipy.exceptions-
Exceptions raised by coolipy.
coolipy.models-
Data models for coolipy.
coolipy.resources-
Resource clients for the Coolify API.
Classes
class AsyncCoolipy (coolify_api_key: str,
coolify_endpoint: str,
coolify_port: int = 8000,
omit_port: bool = False,
http_protocol: str = 'http',
timeout: float = 30.0,
transport: httpx.AsyncBaseTransport | None = None)-
Expand source code
class AsyncCoolipy: """Asynchronous client for the Coolify API. Args: coolify_api_key: Bearer token used to authenticate with the Coolify API. coolify_endpoint: Hostname or IP of the Coolify instance. coolify_port: Port of the Coolify instance (ignored when ``omit_port``). omit_port: When ``True``, build the base URL without a port. http_protocol: ``"http"`` or ``"https"``. timeout: Request timeout in seconds. transport: Optional httpx async transport override (mainly for testing). """ def __init__( self, coolify_api_key: str, coolify_endpoint: str, coolify_port: int = 8000, omit_port: bool = False, http_protocol: str = "http", timeout: float = 30.0, transport: httpx.AsyncBaseTransport | None = None, ) -> None: if not coolify_api_key: raise CoolipyConfigError("coolify_api_key must be a non-empty string.") base_url = build_base_url(http_protocol, coolify_endpoint, coolify_port, omit_port) self._transport = AsyncTransport( base_url, coolify_api_key, timeout=timeout, transport=transport ) self.applications = AsyncApplications(self._transport) self.databases = AsyncDatabases(self._transport) self.services = AsyncServices(self._transport) self.servers = AsyncServers(self._transport) self.projects = AsyncProjects(self._transport) self.teams = AsyncTeams(self._transport) self.deployments = AsyncDeployments(self._transport) self.tags = AsyncTags(self._transport) self.s3_storages = AsyncS3Storages(self._transport) self.security = AsyncSecurity(self._transport) async def version(self) -> CoolipyAPIResponse[str]: """Get the Coolify version.""" return parse_response(await self._transport.request("GET", "/version"), str) async def health(self) -> CoolipyAPIResponse[str]: """Run the Coolify healthcheck.""" return parse_response(await self._transport.request("GET", "/health"), str) async def enable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify API (requires root permissions).""" return parse_response(await self._transport.request("POST", "/enable"), SystemMessage) async def disable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify API (requires root permissions).""" return parse_response(await self._transport.request("POST", "/disable"), SystemMessage) async def enable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify MCP server (requires root permissions).""" return parse_response(await self._transport.request("POST", "/mcp/enable"), SystemMessage) async def disable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify MCP server (requires root permissions).""" return parse_response(await self._transport.request("POST", "/mcp/disable"), SystemMessage) async def close(self) -> None: """Close the underlying HTTP client.""" await self._transport.close() async def __aenter__(self) -> AsyncCoolipy: return self async def __aexit__(self, *exc: object) -> None: await self.close()Asynchronous client for the Coolify API.
- Args
- -----=
coolify_api_key- Bearer token used to authenticate with the Coolify API.
coolify_endpoint- Hostname or IP of the Coolify instance.
coolify_port- Port of the Coolify instance (ignored when
omit_port). omit_port- When
True, build the base URL without a port. http_protocol"http"or"https".timeout- Request timeout in seconds.
transport- Optional httpx async transport override (mainly for testing).
Methods
async def close(self) ‑> None-
Expand source code
async def close(self) -> None: """Close the underlying HTTP client.""" await self._transport.close()Close the underlying HTTP client.
async def disable_api(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
async def disable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify API (requires root permissions).""" return parse_response(await self._transport.request("POST", "/disable"), SystemMessage)Disable the Coolify API (requires root permissions).
async def disable_mcp(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
async def disable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify MCP server (requires root permissions).""" return parse_response(await self._transport.request("POST", "/mcp/disable"), SystemMessage)Disable the Coolify MCP server (requires root permissions).
async def enable_api(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
async def enable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify API (requires root permissions).""" return parse_response(await self._transport.request("POST", "/enable"), SystemMessage)Enable the Coolify API (requires root permissions).
async def enable_mcp(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
async def enable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify MCP server (requires root permissions).""" return parse_response(await self._transport.request("POST", "/mcp/enable"), SystemMessage)Enable the Coolify MCP server (requires root permissions).
async def health(self) ‑> coolipy._response.CoolipyAPIResponse[str]-
Expand source code
async def health(self) -> CoolipyAPIResponse[str]: """Run the Coolify healthcheck.""" return parse_response(await self._transport.request("GET", "/health"), str)Run the Coolify healthcheck.
async def version(self) ‑> coolipy._response.CoolipyAPIResponse[str]-
Expand source code
async def version(self) -> CoolipyAPIResponse[str]: """Get the Coolify version.""" return parse_response(await self._transport.request("GET", "/version"), str)Get the Coolify version.
class Coolipy (coolify_api_key: str,
coolify_endpoint: str,
coolify_port: int = 8000,
omit_port: bool = False,
http_protocol: str = 'http',
timeout: float = 30.0,
transport: httpx.BaseTransport | None = None)-
Expand source code
class Coolipy: """Synchronous client for the Coolify API. Args: coolify_api_key: Bearer token used to authenticate with the Coolify API. coolify_endpoint: Hostname or IP of the Coolify instance. coolify_port: Port of the Coolify instance (ignored when ``omit_port``). omit_port: When ``True``, build the base URL without a port. http_protocol: ``"http"`` or ``"https"``. timeout: Request timeout in seconds. transport: Optional httpx transport override (mainly for testing). """ def __init__( self, coolify_api_key: str, coolify_endpoint: str, coolify_port: int = 8000, omit_port: bool = False, http_protocol: str = "http", timeout: float = 30.0, transport: httpx.BaseTransport | None = None, ) -> None: if not coolify_api_key: raise CoolipyConfigError("coolify_api_key must be a non-empty string.") base_url = build_base_url(http_protocol, coolify_endpoint, coolify_port, omit_port) self._transport = SyncTransport( base_url, coolify_api_key, timeout=timeout, transport=transport ) self.applications = Applications(self._transport) self.databases = Databases(self._transport) self.services = Services(self._transport) self.servers = Servers(self._transport) self.projects = Projects(self._transport) self.teams = Teams(self._transport) self.deployments = Deployments(self._transport) self.tags = Tags(self._transport) self.s3_storages = S3Storages(self._transport) self.security = Security(self._transport) def version(self) -> CoolipyAPIResponse[str]: """Get the Coolify version.""" return parse_response(self._transport.request("GET", "/version"), str) def health(self) -> CoolipyAPIResponse[str]: """Run the Coolify healthcheck.""" return parse_response(self._transport.request("GET", "/health"), str) def enable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify API (requires root permissions).""" return parse_response(self._transport.request("POST", "/enable"), SystemMessage) def disable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify API (requires root permissions).""" return parse_response(self._transport.request("POST", "/disable"), SystemMessage) def enable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify MCP server (requires root permissions).""" return parse_response(self._transport.request("POST", "/mcp/enable"), SystemMessage) def disable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify MCP server (requires root permissions).""" return parse_response(self._transport.request("POST", "/mcp/disable"), SystemMessage) def close(self) -> None: """Close the underlying HTTP client.""" self._transport.close() def __enter__(self) -> Coolipy: return self def __exit__(self, *exc: object) -> None: self.close()Synchronous client for the Coolify API.
- Args
- -----=
coolify_api_key- Bearer token used to authenticate with the Coolify API.
coolify_endpoint- Hostname or IP of the Coolify instance.
coolify_port- Port of the Coolify instance (ignored when
omit_port). omit_port- When
True, build the base URL without a port. http_protocol"http"or"https".timeout- Request timeout in seconds.
transport- Optional httpx transport override (mainly for testing).
Methods
def close(self) ‑> None-
Expand source code
def close(self) -> None: """Close the underlying HTTP client.""" self._transport.close()Close the underlying HTTP client.
def disable_api(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
def disable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify API (requires root permissions).""" return parse_response(self._transport.request("POST", "/disable"), SystemMessage)Disable the Coolify API (requires root permissions).
def disable_mcp(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
def disable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Disable the Coolify MCP server (requires root permissions).""" return parse_response(self._transport.request("POST", "/mcp/disable"), SystemMessage)Disable the Coolify MCP server (requires root permissions).
def enable_api(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
def enable_api(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify API (requires root permissions).""" return parse_response(self._transport.request("POST", "/enable"), SystemMessage)Enable the Coolify API (requires root permissions).
def enable_mcp(self) ‑> coolipy._response.CoolipyAPIResponse[SystemMessage]-
Expand source code
def enable_mcp(self) -> CoolipyAPIResponse[SystemMessage]: """Enable the Coolify MCP server (requires root permissions).""" return parse_response(self._transport.request("POST", "/mcp/enable"), SystemMessage)Enable the Coolify MCP server (requires root permissions).
def health(self) ‑> coolipy._response.CoolipyAPIResponse[str]-
Expand source code
def health(self) -> CoolipyAPIResponse[str]: """Run the Coolify healthcheck.""" return parse_response(self._transport.request("GET", "/health"), str)Run the Coolify healthcheck.
def version(self) ‑> coolipy._response.CoolipyAPIResponse[str]-
Expand source code
def version(self) -> CoolipyAPIResponse[str]: """Get the Coolify version.""" return parse_response(self._transport.request("GET", "/version"), str)Get the Coolify version.
class CoolipyAPIResponse (status_code: int, data: T, headers: dict[str, str] = <factory>)-
Expand source code
@dataclass class CoolipyAPIResponse(Generic[T]): """A parsed Coolify API response. Attributes: status_code: The HTTP status code returned by the API. data: The parsed (and, when a model is provided, validated) response body. headers: The response headers as a plain string mapping. """ status_code: int data: T headers: dict[str, str] = field(default_factory=dict)A parsed Coolify API response.
- Attributes
- -----=
status_code- The HTTP status code returned by the API.
data- The parsed (and, when a model is provided, validated) response body.
headers- The response headers as a plain string mapping.
Ancestors
- typing.Generic
Instance variables
var data : ~Tvar headers : dict[str, str]var status_code : int
class CoolipyBaseModel (**data: Any)-
Expand source code
class CoolipyBaseModel(BaseModel): """Base class for every coolipy request and response model. Unknown fields are ignored so that responses carrying fields coolipy does not model yet still validate. """ model_config = ConfigDict(extra="ignore")Base class for every coolipy request and response model.
Unknown fields are ignored so that responses carrying fields coolipy does not model yet still validate.
Create a new model by parsing and validating input data from keyword arguments.
Raises [
ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.selfis explicitly positional-only to allowselfas a field name.Ancestors
- pydantic.main.BaseModel
Subclasses
- ApplicationBaseModel
- ApplicationModel
- ApplicationSetting
- DockerComposeDomain
- BulkEnvsUpdate
- DeploymentQueuedResponse
- Destination
- DestinationCreate
- EnvironmentVariable
- EnvironmentVariableCreate
- EnvironmentVariableUpdate
- Logs
- MessageResponse
- ScheduledTask
- ScheduledTaskCreate
- ScheduledTaskExecution
- ScheduledTaskUpdate
- StorageCreate
- StorageUpdate
- Tag
- TagCreate
- TagUpdate
- TagsCreate
- UUIDResponse
- VolumeBackupScheduleRequest
- VolumeBackupScheduleResponse
- DatabaseBackupCreate
- DatabaseBaseModel
- DeployResponse
- DeploymentEntry
- DeploymentModel
- EnvironmentCreateModel
- EnvironmentModel
- EnvironmentUpdateModel
- ProjectCreateModel
- ProjectModel
- ProjectUpdateModel
- S3StorageCreateModel
- S3StorageModel
- S3StorageUpdateModel
- PrivateKeyCreateModel
- PrivateKeyModel
- PrivateKeyUpdateModel
- ServerCreateModel
- ServerModel
- ServerSetting
- ServerUpdateModel
- ServiceCreateModel
- ServiceModel
- ServiceURL
- ServiceUpdateModel
- SystemMessage
- TeamModel
- UserModel
Class variables
var model_config
class CoolipyConfigError (*args, **kwargs)-
Expand source code
class CoolipyConfigError(CoolipyError): """Raised when the client is misconfigured (e.g. missing API key)."""Raised when the client is misconfigured (e.g. missing API key).
Ancestors
- CoolipyError
- builtins.Exception
- builtins.BaseException
class CoolipyError (*args, **kwargs)-
Expand source code
class CoolipyError(Exception): """Base class for every exception raised by coolipy."""Base class for every exception raised by coolipy.
Ancestors
- builtins.Exception
- builtins.BaseException
Subclasses
class CoolipyHTTPError (status_code: int,
message: str,
*,
errors: Mapping[str, Any] | None = None,
response: Any = None)-
Expand source code
class CoolipyHTTPError(CoolipyError): """Raised when the Coolify API responds with a non-2xx status code. Attributes: status_code: The HTTP status code returned by the API. message: The human-readable ``message`` from the error response body. errors: Field-level validation errors, populated for ``422`` responses. response: The raw parsed response body, when available. """ def __init__( self, status_code: int, message: str, *, errors: Mapping[str, Any] | None = None, response: Any = None, ) -> None: super().__init__(message) self.status_code = status_code self.message = message self.errors = errors self.response = response def __str__(self) -> str: return f"{self.status_code}: {self.message}"Raised when the Coolify API responds with a non-2xx status code.
- Attributes
- -----=
status_code- The HTTP status code returned by the API.
message- The human-readable
messagefrom the error response body. errors- Field-level validation errors, populated for
422responses. response- The raw parsed response body, when available.
Ancestors
- CoolipyError
- builtins.Exception
- builtins.BaseException
class CoolipyValidationError (*args, **kwargs)-
Expand source code
class CoolipyValidationError(CoolipyError): """Raised when a request model fails client-side validation."""Raised when a request model fails client-side validation.
Ancestors
- CoolipyError
- builtins.Exception
- builtins.BaseException