Skip to main content

3CX Python SDK

A typed Python SDK for the 3CX XAPI (/xapi/v1), built on httpx and Pydantic v2.

Features

  • OAuth2 client-credentials authentication with automatic token refresh
  • OData v4 query builder ($filter, $select, $expand, $orderby, $top, $skip, $count)
  • Automatic pagination — iterate over all pages with a single generator call
  • Full coverage — 37 typed services covering every resource group in the 3CX XAPI swagger spec
  • Auto-generated models — every Pydantic model is generated from swagger.yaml, giving you full IDE autocomplete on every field of every entity (User has 60+ typed fields, Queue has 50+, etc.)
  • Reporting helpers for call log, queue performance, extension statistics, activity log, and more
  • Context-manager support for clean resource management
  • Escape hatches (client.get() / client.post()) for raw access to any endpoint

Installation

pip install 3cx-xapi-python-sdk

Quick start

from threecx import ThreeCXClient, ODataQuery

client = ThreeCXClient(
    base_url="https://pbx.example.com",
    client_id="<service-principal-client-id>",
    client_secret="<service-principal-secret>",
)

# ── Active calls ─────────────────────────────────────────────────────────────
for call in client.active_calls.list():
    print(f"{call.caller} → {call.callee}  ({call.status} since {call.established_at})")

# Drop a specific call
client.active_calls.drop(call_id=42)

# ── Users ─────────────────────────────────────────────────────────────────────
# List first 50 enabled users, sorted by extension number
q = ODataQuery().filter("Enabled eq true").order_by("Number").top(50)
for user in client.users.list(q):
    print(user.number, user.full_name, user.email_address)

# Get a single user and update their e-mail
user = client.users.get(101)
client.users.update(101, {"EmailAddress": "new@example.com"})

# Create a user
from threecx.models import User
new_user = client.users.create(User(
    Number="200",
    FirstName="Alice",
    LastName="Smith",
    EmailAddress="alice@example.com",
))

# ── Queues ────────────────────────────────────────────────────────────────────
for queue in client.queues.list():
    agents = client.queues.get_agents(queue.id)
    print(f"Queue {queue.name}: {len(agents)} agents")

# ── Call history ──────────────────────────────────────────────────────────────
q = ODataQuery().filter("SrcExternal eq true").order_by("SegmentStartTime desc").top(100)
for entry in client.call_history.iterate(q):
    print(entry.segment_start_time, entry.src_caller_number, "→", entry.dst_caller_number, entry.call_answered)

# ── Reports ───────────────────────────────────────────────────────────────────
from datetime import datetime, timedelta, timezone

end = datetime.now(timezone.utc)
start = end - timedelta(days=7)
rows = client.reports.get_call_log(start, end)
print(f"{len(rows)} call-log entries for the last 7 days")

# ── System status ─────────────────────────────────────────────────────────────
status = client.system.get_status()
print(f"PBX {status.version}  calls: {status.calls_active}  disk: {status.disk_usage}%")

# ── Context manager ───────────────────────────────────────────────────────────
with ThreeCXClient(base_url="https://pbx.example.com",
                   client_id="...", client_secret="...") as c:
    print(c.system.get_license())

OData query builder

from threecx import ODataQuery

q = (
    ODataQuery()
    .filter("LastName eq 'Smith'")
    .select("Id", "Number", "FirstName", "LastName", "Email")
    .expand("Groups")
    .order_by("Number")
    .top(25)
    .skip(0)
    .count()
)

All query parameters map directly to OData v4 syntax. Refer to the 3CX XAPI swagger for supported fields per endpoint.

Every method whose endpoint documents query options takes query=, including single-entity and settings getters ($select/$expand), e.g. client.settings.get_mail_settings(query=ODataQuery().select("MailServer")). list() methods return the items of one page; read $count with client.call_history.count(q), or through the escape hatch: client.get("/Users", params=ODataQuery().count().top(0).to_params())["@odata.count"].

Calling actions

3CX actions (POST …/Pbx.Name) take named parameters, and the SDK methods take the same parameters as arguments. Pass the object itself; the method posts it under the parameter name 3CX expects (InstallUpdates wants {"install": {...}}, SetUpdateSettings wants {"settings": {...}}, and so on).

from threecx.models import InstallUpdates, XServiceManageOptions

# Install every available update
available = client.updates.get_updates()
client.updates.install_updates(InstallUpdates(
    key=available["Key"],
    entries=[item["Guid"] for item in available["Entries"]],
))

# Restart a PBX service
client.pbx_services.restart(XServiceManageOptions(service_names=["3CXQueueManager"]))

# A dict with the API's PascalCase keys works wherever a model does
client.pbx_services.stop({"ServiceNames": ["3CXQueueManager"]})

Object arguments accept the model from threecx.models or a plain dict; enum arguments accept the enum or its string value. Actions without parameters take no body argument: client.recordings.archive().

Creating a service principal

  1. Log in to 3CX as admin.
  2. Navigate to Admin → Integrations → API.
  3. Create a new service principal and copy the Client ID and Client Secret.

Services reference

The SDK exposes 37 services as attributes of ThreeCXClient, covering every resource group in swagger.yaml.

Calls & telephony

client.<service> Resource
active_calls /ActiveCalls — list & drop live calls
call_history /CallHistoryView — paginated call log
recordings /Recordings, /RemoteArchivingSettings
voicemail /VoicemailSettings, /MusicOnHoldSettings
fax /Fax, /FaxServerSettings

Users, groups & directories

client.<service> Resource
users /Users — CRUD extensions/users + greetings, phones, provisioning
my_user /MyUser — current authenticated user
groups /Groups — full admin groups (members, rights, restrictions)
my_group /MyGroup — current user's primary group
contacts /Contacts — company phone book
parameters /TenantProperties, /DNProperties, directory info

Call routing & flow

client.<service> Resource
queues /Queues — CRUD call queues & agents
ring_groups /RingGroups — CRUD ring groups
inbound_rules /InboundRules — DID/inbound rules
outbound_rules /OutboundRules — outbound dial rules
receptionists /Receptionists — digital receptionists
holidays /Holidays, /OfficeHours
parkings /Parkings, /CallParkingSettings
call_flow /CallFlowApps, /CallFlowScripts

Trunks & PBX hardware

client.<service> Resource
trunks /Trunks, /TrunkTemplates, /Peers, /Sbcs
phones /PhoneTemplates, /SipDevices, /Fxs, /FxsTemplates, /DeviceInfos, /Firmwares

Communication

client.<service> Resource
chat /ChatHistoryView, /ChatMessagesHistoryView
prompts /PromptSets, /CustomPrompts, /Playlists
email /EmailTemplate

System administration

client.<service> Resource
system /SystemStatus, /LicenseStatus, /Parameters
settings /GeneralSettingsForPbx, /MailSettings, /CDRSettings, ~20 settings domains
pbx_services /Services — start/stop/enable/disable PBX services
backups /Backups, failover & restore settings
updates /GetUpdates(), /InstallUpdates, update settings, prompt set / CRM updates, purge
event_logs /EventLogs
security /SecurityTokens, /ServicePrincipals, /BlackListNumbers, /Blocklist, /AntiHackingSettings, /Firewall
emergency /EmergencyGeoLocations, /EmergencyNotificationsSettings
defs /Defs — codecs, timezones, gateway parameters, countries, DID numbers

Integrations

client.<service> Resource
integrations /Microsoft365Integration, /Microsoft365TeamsIntegration, /GoogleSettings, /AmazonIntegrationSettings, /DataConnectorSettings, /AISettings
crm /CrmIntegration, /CrmTemplates
website_links /WebsiteLinks

Reporting

client.<service> Resource
reports 30+ report endpoints: call log, queue & extension statistics, agent login, activity log, SLA breaches, audit, scheduled reports

Escape hatch

Any endpoint not covered by a typed service can be called directly:

data = client.get("/InboundRules", params={"$top": "10"})
client.post("/Backups/Pbx.Backup", json={"description": {"Name": "before-upgrade"}})

client.post() sends json exactly as given, so key an action's body by its parameter names yourself (look them up in swagger.yaml under the action's …RequestBody schema).

Metadata

Release files for 3cx-xapi-python-sdk 3.0.0

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

Source distribution (sdist)

Source distribution for 3cx-xapi-python-sdk 3.0.0
File Size Uploaded
3cx_xapi_python_sdk-3.0.0.tar.gz 101.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for 3cx-xapi-python-sdk 3.0.0
File Interpreter ABI Platform
3cx_xapi_python_sdk-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 204.4 kB

Release files / 3cx_xapi_python_sdk-3.0.0.tar.gz

Download URL 3cx_xapi_python_sdk-3.0.0.tar.gz
Size 101.6 kB
Tags Source
SHA-256 checksum
How to use checksums
898143456978fad89f57b20681e90c1e802e6c5231244f20e3ed88facb8d9966
BLAKE2b-256 checksum
How to use checksums
2084aebcdc9632272ddd5610096aaac4f7506a2d7878b50ad9b636fbf1776a40
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / 3cx_xapi_python_sdk-3.0.0-py3-none-any.whl

Download URL 3cx_xapi_python_sdk-3.0.0-py3-none-any.whl
Size 102.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a929d04c08239514f73c0dde3b309ec613fd3500ea982c9136246e054b917388
BLAKE2b-256 checksum
How to use checksums
ec8f88f28b90ebd96b7c32feac726ab5e3b85a674b698be019180a63dd769712
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.20 {"installer":{"name":"uv","version":"0.12.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

3.0.0 This release

2 release files

2.0.0

2 release files

1.1.0

2 release files

1.0.2

2 release files

1.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