Skip to main content

Python client for the CPSMS.dk SMS Gateway API

Project description

CPSMS-client

PyPI version Python Versions License: MIT

A Python client for the CPSMS.dk SMS Gateway API with both synchronous and asynchronous support.

Features

  • ✅ Full API coverage (SMS, Groups, Contacts, Logs)
  • ✅ Both sync and async clients
  • ✅ Type hints throughout
  • ✅ Dataclasses for all response objects
  • ✅ Custom exceptions for error handling
  • ✅ Context manager support

Installation

pip install cpsms-client

Quick Start

Synchronous Usage

from cpsms import CPSMSClient

with CPSMSClient(username="your_username", api_key="your_api_key") as client:
    # Send an SMS
    result = client.send_sms(
        to="4512345678",
        message="Hello from Python!",
        from_="MyApp"
    )
    print(f"Sent! Cost: {result.success[0].cost} points")

    # Check your credit balance
    credit = client.get_credit()
    print(f"Remaining credit: {credit}")

Asynchronous Usage

import asyncio
from cpsms import AsyncCPSMSClient

async def main():
    async with AsyncCPSMSClient(username="your_username", api_key="your_api_key") as client:
        result = await client.send_sms(
            to="4512345678",
            message="Hello from async Python!",
            from_="MyApp"
        )
        print(f"Sent! Cost: {result.success[0].cost} points")

asyncio.run(main())

Getting Your API Credentials

  1. Create an account at cpsms.dk (you get 10 free SMS points)
  2. Log in to your dashboard at cpsms.dk/login
  3. Navigate to INDSTILLINGER → API
  4. Generate your API key

API Reference

Sending SMS

from cpsms import CPSMSClient, SMSFormat
from datetime import datetime, timedelta

with CPSMSClient(username="user", api_key="key") as client:
    # Simple send
    result = client.send_sms(
        to="4512345678",
        message="Hello!",
        from_="MyApp"
    )

    # Send to multiple recipients
    result = client.send_sms(
        to=["4512345678", "4587654321"],
        message="Bulk message!",
        from_="MyApp"
    )

    # Schedule for later
    result = client.send_sms(
        to="4512345678",
        message="This arrives in 1 hour",
        from_="MyApp",
        timestamp=datetime.now() + timedelta(hours=1),
        reference="my-ref-123"  # Required if you want to cancel later
    )

    # Send with delivery report webhook
    result = client.send_sms(
        to="4512345678",
        message="Track me!",
        from_="MyApp",
        dlr_url="https://myserver.com/webhook"
    )

    # Send Unicode (for emojis, Chinese characters, etc.)
    result = client.send_sms(
        to="4512345678",
        message="你好 🎉",
        from_="MyApp",
        format_=SMSFormat.UNICODE
    )

    # Send flash SMS (appears directly on screen)
    result = client.send_sms(
        to="4512345678",
        message="URGENT!",
        from_="MyApp",
        flash=True
    )

Managing Groups

with CPSMSClient(username="user", api_key="key") as client:
    # Create a group
    group = client.create_group("VIP Customers")
    print(f"Created group ID: {group.group_id}")

    # List all groups
    groups = client.list_groups()
    for g in groups:
        print(f"{g.group_name} (ID: {g.group_id})")

    # Update group name
    client.update_group(group_id=12345, group_name="Premium Customers")

    # Delete group (must be empty)
    client.delete_group(group_id=12345)

    # Send SMS to entire group
    result = client.send_to_group(
        to_group=12345,
        message="Hello VIP customers!",
        from_="MyStore"
    )

Managing Contacts

with CPSMSClient(username="user", api_key="key") as client:
    # Add contact to a group
    client.create_contact(
        group_id=12345,
        phone_number="4512345678",
        contact_name="John Doe"
    )

    # List contacts in a group
    contacts = client.list_contacts(group_id=12345)
    for contact in contacts:
        print(f"{contact.contact_name}: {contact.phone_number}")

    # Update contact name
    client.update_contact(
        group_id=12345,
        phone_number="4512345678",
        contact_name="John Smith"
    )

    # Find which groups a contact belongs to
    groups = client.list_group_membership("4512345678")
    print(f"Contact is in {len(groups)} groups")

    # Remove contact from group
    client.delete_contact(group_id=12345, phone_number="4512345678")

Viewing Logs

from datetime import datetime, timedelta

with CPSMSClient(username="user", api_key="key") as client:
    # Get recent log entries (up to 3 months back)
    log = client.get_log()
    for entry in log:
        print(f"{entry.time_sent}: To {entry.to} - Status: {entry.dlr_status_text}")

    # Filter by recipient
    log = client.get_log(to="4512345678")

    # Filter by date range
    log = client.get_log(
        from_date=datetime.now() - timedelta(days=7),
        to_date=datetime.now()
    )

Account Management

with CPSMSClient(username="user", api_key="key") as client:
    # Check credit balance
    credit = client.get_credit()
    print(f"Balance: {credit}")

    # Cancel a scheduled SMS (must be >10 min before send time)
    client.delete_sms(reference="my-ref-123")

Error Handling

from cpsms import (
    CPSMSClient,
    CPSMSError,
    AuthenticationError,
    InsufficientCreditError,
    BadRequestError,
)

with CPSMSClient(username="user", api_key="key") as client:
    try:
        result = client.send_sms(to="4512345678", message="Hello!", from_="App")
    except AuthenticationError:
        print("Invalid username or API key")
    except InsufficientCreditError:
        print("Not enough SMS credits - please top up!")
    except BadRequestError as e:
        print(f"Invalid request: {e.message}")
    except CPSMSError as e:
        print(f"API error {e.code}: {e.message}")

Exception Types

Exception HTTP Code Description
AuthenticationError 401 Invalid credentials
InsufficientCreditError 402 Not enough SMS credits
ForbiddenError 403 IP not whitelisted
NotFoundError 404 Resource not found
ConflictError 409 Operation conflict
BadRequestError 400 Invalid parameters
CPSMSError * Base exception for all API errors

Async Concurrent Requests

import asyncio
from cpsms import AsyncCPSMSClient

async def send_bulk():
    async with AsyncCPSMSClient(username="user", api_key="key") as client:
        # Send to multiple recipients concurrently
        tasks = [
            client.send_sms(to=num, message="Hello!", from_="MyApp")
            for num in ["4512345678", "4587654321", "4599887766"]
        ]
        results = await asyncio.gather(*tasks, return_exceptions=True)

        for result in results:
            if isinstance(result, Exception):
                print(f"Error: {result}")
            else:
                for sms in result.success:
                    print(f"Sent to {sms.to}")

asyncio.run(send_bulk())

Response Objects

SendResponse

result = client.send_sms(to=["4512345678", "invalid"], message="Hi", from_="App")

# Successful sends
for sms in result.success:
    print(f"To: {sms.to}, Cost: {sms.cost}, Segments: {sms.sms_amount}")

# Failed sends
for error in result.errors:
    print(f"To: {error.to}, Error: {error.message} (code: {error.code})")

Group

group = client.create_group("My Group")
print(f"ID: {group.group_id}, Name: {group.group_name}")

Contact

contacts = client.list_contacts(group_id=12345)
for c in contacts:
    print(f"Name: {c.contact_name}")
    print(f"Phone: {c.phone_number}")
    print(f"Added: {c.time_added}")  # datetime object

LogEntry

log = client.get_log()
for entry in log:
    print(f"To: {entry.to}")
    print(f"From: {entry.from_}")
    print(f"Segments: {entry.sms_amount}")
    print(f"Cost: {entry.point_price}")
    print(f"Reference: {entry.user_reference}")
    print(f"Status: {entry.dlr_status} - {entry.dlr_status_text}")
    print(f"Sent: {entry.time_sent}")  # datetime object

SMS Limits

Format Single SMS Multipart (per segment)
GSM 160 chars 153 chars
Unicode 70 chars 67 chars

Maximum message length: 1530 characters (10 SMS segments joined)

Development

# Clone the repository
git clone https://github.com/jetdk/cpsms-client.git
<<<<<<< HEAD
cd cpsms-client
=======
cd cpsms
>>>>>>> 8cc22b3acf8430a6d0279ed57bee173b41907922

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run type checking
mypy src/cpsms

# Run linting
ruff check src/cpsms-client

License

MIT License - see LICENSE for details.

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cpsms_client-1.0.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cpsms_client-1.0.0-py3-none-any.whl (12.8 kB view details)

Uploaded Python 3

File details

Details for the file cpsms_client-1.0.0.tar.gz.

File metadata

  • Download URL: cpsms_client-1.0.0.tar.gz
  • Upload date:
  • Size: 11.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for cpsms_client-1.0.0.tar.gz
Algorithm Hash digest
SHA256 971a0a2eb2b10d50e5230a0c125616d1f5b64d50a7998ed5568bdbdbe143719f
MD5 7cfe7803515cd486051196c146538946
BLAKE2b-256 9e581ef0d5279568d30515e578ace7dc71f89cffaededfa3c2f9a4deadfc8089

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpsms_client-1.0.0.tar.gz:

Publisher: release.yml on jetdk/cpsms-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cpsms_client-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: cpsms_client-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 12.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for cpsms_client-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bdd9df706ea6c79528a235bdee057e62b8cb7356a68f3c53cb4e1cc86e5a74c6
MD5 c133524049df82fd87e29758f118f3f0
BLAKE2b-256 978d750cf9aff041320848a9684cd31062722dd10fefe0dcc73dc00ef7ca8f20

See more details on using hashes here.

Provenance

The following attestation bundles were made for cpsms_client-1.0.0-py3-none-any.whl:

Publisher: release.yml on jetdk/cpsms-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page