Skip to main content

Zammad CTI Client (Python)

A lightweight, typed Python client for interacting with Zammad’s Generic CTI API. This module allows telephony systems (PBX, SIP servers, dialers, etc.) to notify Zammad about call lifecycle events such as new calls, answers, and hangups.

📖 Official Zammad CTI documentation: https://docs.zammad.org/en/latest/api/generic-cti/index.html


Features

  • Simple and clean API for Zammad CTI events
  • Fully typed (using typing and custom type aliases)
  • Automatic environment-based configuration via ENVMod
  • Structured logging via logwrap
  • Minimal dependencies
  • Explicit control over SSL verification
  • Designed for backend / PBX integrations

Installation

pip install py-zammad-cti

This module also depends on:

  • classmods
  • requests
  • python-dotenv (Optional)

Make sure those are available in your environment.


Basic Usage

from zammad_cti import CTIClient

client = CTIClient(
    url="https://zammad.example.com/api/v1/cti/<TOKEN>",
    verify_ssl=False,
)

Once initialized, you can send CTI events to Zammad.


Environment Configuration (ENVMod)

The CTIClient constructor is registered with ENVMod:

@ENVMod.register(section_name='ZammadCTI')

This allows configuration via environment variables or .env files (depending on your ENVMod setup), for example:

ZammadCTI_URL=https://zammad.example.com/api/v1/cti/<TOKEN>
ZammadCTI_VERIFY_SSL=false

This makes the client easy to configure in containerized or production environments.

Later you can load env with python-dotenv and classmod easily:

from zammad_cti import CTIClient
from classmods import ENVMod

client = CTIClient(**ENVmod.load_args(CTIClient.__init__))

Read classmods documentations for more info and usage:

📖 Official classmods documentation: https://github.com/hmohammad2520-org/classmods


Call Lifecycle Methods

1. New Call

Notify Zammad that a new call has started.

client.new_call(
    _from="+491234567",
    to="+498765432",
    direction='in',
    call_id="call-uuid-123",
    user="John Doe",
    queue="Support",
)

Parameters

Name Type Description
_from str Caller number
to str Destination number
direction CallDirection Call direction (in / out)
call_id str Unique call identifier
user `Optional[str List[str]]` Related user(s)
queue Optional[str] Queue name

2. Answer Call

Notify Zammad that a call has been answered.

client.answer(
    _from="+491234567",
    to="+498765432",
    direction='in',
    call_id="call-uuid-123",
    answering_number="+498765432",
    user="Agent Smith",
)

Parameters

Name Type Description
_from str Caller number
to str Destination number
direction CallDirection Call direction
call_id str Unique call ID
answering_number Optional[str] Number used to identify the answering user
user `Optional[str List[str]]` User(s) involved

3. Hangup Call

Notify Zammad that a call has ended.

client.hangup(
    _from="+491234567",
    to="+498765432",
    direction='in',
    call_id="call-uuid-123",
    cause='normalClearing',
    answering_number="+498765432",
)

Parameters

Name Type Description
_from str Caller number
to str Destination number
direction CallDirection Call direction
call_id str Unique call ID
cause HangupCause Reason for hangup
answering_number Optional[str] User lookup hint

Zammad uses the hangup cause to determine missed calls, answered calls, etc.


Logging

This module uses logwrap decorators to automatically log:

  • Outgoing HTTP requests
  • Call lifecycle transitions
  • Returned results

Example logged message:

Changed call state to hangup: {...}, result: {...}

Logging behavior can be controlled centrally via logwrap.


HTTP Behavior

  • Uses a persistent requests.Session
  • Sends data as application/json
  • Automatically removes None values from payloads
  • Raises exceptions on HTTP errors (response.raise_for_status())

Most CTI responses are empty unless the call is rejected or blocked in Zammad. Read Zammad CTI system documentation for more info.


Type Safety

The client relies on explicit type aliases:

  • CallDirection
  • HangupCause

This helps prevent invalid CTI payloads and improves IDE autocomplete and static analysis.


Typical Use Case

This client is ideal for:

  • PBX → Zammad integrations
  • SIP servers (Asterisk, FreeSWITCH, Kamailio)
  • Custom softphones
  • Call monitoring services
  • Telephony middleware

Error Handling

  • All HTTP errors raise requests.HTTPError
  • Validation is delegated to Zammad
  • Invalid payloads will be rejected server-side

You should wrap calls in your own retry / error-handling logic if required.


License

MIT (or your preferred license)

Metadata

Release files for py-zammad-cti 0.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-zammad-cti 0.0.2
File Size Uploaded
py_zammad_cti-0.0.2.tar.gz 6.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-zammad-cti 0.0.2
File Interpreter ABI Platform
py_zammad_cti-0.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 14.7 kB

Release files / py_zammad_cti-0.0.2.tar.gz

Download URL py_zammad_cti-0.0.2.tar.gz
Size 6.8 kB
Tags Source
SHA-256 checksum
How to use checksums
04ad9161fb3166ae95252876c630d7bd92a5ca4dc10d116eb828583de7ed0dd3
BLAKE2b-256 checksum
How to use checksums
902ff660123a16e805a977412b65e39df7827d6a19d881f7b0899b81dc3f8272
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 30, 2026.

Transparency log

Release files / py_zammad_cti-0.0.2-py3-none-any.whl

Download URL py_zammad_cti-0.0.2-py3-none-any.whl
Size 7.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3994349942f13540c1fdedd2d7699f273747bc84368b62522ae6446b02b18290
BLAKE2b-256 checksum
How to use checksums
9db298e311dcf15847ec58095df98938c271d4e1aae7eeabfad9a9bbf062374a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jan 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.0.2 This release

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page