# Python SDK

Use the `cronitor` Python package to report job runs, heartbeats, and metrics to Cronitor.

## Install

```bash
pip install cronitor
```

## Configure

Set the `CRONITOR_API_KEY` environment variable to your SDK Integration key. Copy the key from Settings → API Keys at https://cronitor.io/app/settings/api. Keep the key in the environment or a secret store of the runtime. Do not commit it.

The SDK reads `CRONITOR_API_KEY` when you import `cronitor`, so you do not need configuration code. Set the variable before the process starts.

## Monitor a job

Add the `@cronitor.job` decorator to the main function of the job:

```python
import cronitor

@cronitor.job('send-invoices')
def send_invoices():
    ...  # the work of the job

send_invoices()
```

- Before the function starts, the SDK sends a `run` event.
- When the function returns, the SDK sends a `complete` event with the elapsed time as the `duration` metric.
- When the function raises an exception, the SDK sends a `fail` event with the exception message and the `duration` metric. Then it raises the exception again.
- The events go to the monitor with the key `send-invoices`. If no monitor has this key, Cronitor creates one on the first event.

The SDK sends the return value of the function as the message of the `complete` event. To not send it, use `@cronitor.job('send-invoices', log_output=False)`.

To send the events yourself, use a `Monitor`:

```python
monitor = cronitor.Monitor('send-invoices')
monitor.ping(state='run')
monitor.ping(state='complete')  # or state='fail'
```

## Send a heartbeat

Send a ping each time the process completes a unit of useful work:

```python
import cronitor

monitor = cronitor.Monitor('queue-worker')
monitor.ping(message='Alive!')
```

To attach metrics, give a `metrics` dict. The SDK sends each item as `metric=name:value`:

```python
monitor.ping(metrics={'count': 100, 'error_count': 3})
```

If you only want to record custom metrics, use a heartbeat monitor. See [Custom Metrics](https://cronitor.io/docs/custom-metrics.md).

## Verify

After one real run, check the state of the monitor. A successful telemetry response shows only that Cronitor received the request. It does not show that Cronitor stored the event or matched it to a monitor.

With the [MCP server](https://cronitor.io/docs/mcp-server.md):

```text
get_status({"key": "send-invoices"})
```

With [CronitorCLI](https://cronitor.io/docs/using-cronitor-cli.md):

```bash
cronitor status send-invoices
```

If `CRONITOR_API_KEY` is not set, the SDK logs `No API key detected` and sends no events. The job still runs.

## Reference

- [cronitor-python on GitHub](https://github.com/cronitorio/cronitor-python): the full README, including Celery and YAML configuration.
- [Telemetry API](https://cronitor.io/docs/telemetry-api.md): the events and parameters that the SDK sends.
