skebby-sdk 1.0.0
A comprehensive Python SDK for the Skebby SMS API
License: MIT
Requires Python: >=3.6
Keywords: skebby, sms, api, sdk, messaging, two-factor, 2fa

# Skebby SDK for Python

A comprehensive, production-ready Python SDK for the [Skebby SMS API](https://www.skebby.com/). This library provides a clean, intuitive interface to all Skebby REST API endpoints with full support for authentication, SMS operations, contacts management, templates, subaccounts, and more.

[![Python Version](https://img.shields.io/badge/python-3.6%2B-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

---

## 🚀 Features

### Complete API Coverage (100%)
- ✅ **Authentication** - Session key & access token authentication
- ✅ **User API** - Account status, credits, and service information
- ✅ **SMS Send API** - Send SMS, parametric SMS, group SMS, scheduled messages
- ✅ **SMS History API** - Retrieve sent message history and statistics
- ✅ **SMS Blacklist API** - Dedicated SMS blacklist management
- ✅ **Received SMS API** - Get incoming messages (MO messages)
- ✅ **Contacts API** - Full CRUD operations for contacts
- ✅ **Contact Groups API** - Create and manage contact groups
- ✅ **TPOA API** - Sender ID (alias) management
- ✅ **SMS Templates API** - Create and manage message templates
- ✅ **Landing Pages API** - List published landing pages
- ✅ **Subaccounts API** - Complete subaccount management
- ✅ **Subaccount Profiles API** - Manage subaccount profiles and services
- ✅ **Two-Factor Authentication API** - Send and verify 2FA PINs

### Developer-Friendly
- 🎯 **Intuitive API** - Clean, Pythonic interface
- 📝 **Comprehensive Documentation** - Detailed docstrings for all methods
- 🛡️ **Robust Error Handling** - Specific exceptions for different error types
- 🔒 **Type Safety** - Full type hints support
- ⚡ **Production Ready** - Thoroughly tested and aligned with official API

---

## 📦 Installation

```bash
pip install skebby-sdk
```

**Install from source:**
```bash
git clone https://github.com/valeriyglavatskyy/skebby-sdk.git
cd skebby-sdk
pip install -e .
```

---

## 🎯 Quick Start

```python
from skebby_sdk import SkebbyClient

# Initialize with username/password (auto-login)
client = SkebbyClient(
    username="your_email@example.com",
    password="your_password"
)

# Send an SMS
response = client.sms.send_sms(
    phone_number="+393471234567",
    message="Hello from Skebby SDK!",
    sender="MyApp"
)
print(f"SMS sent! Order ID: {response['order_id']}")

# Check account status
status = client.user.get_status()
print(f"SMS Credits: {status['sms']}")
```

---

## 📋 API Modules Quick Reference

The SDK provides 11 comprehensive API modules:

| Module | Access | Description |
|--------|--------|-------------|
| **Authentication** | `client.auth` | Session key & access token authentication |
| **User** | `client.user` | Account status, credits, service info |
| **SMS** | `client.sms` | Send SMS, parametric SMS, group SMS, scheduling |
| **Received** | `client.received` | Get incoming messages (MO messages) |
| **Contacts** | `client.contacts` | Manage contacts and contact groups |
| **Blacklist** | `client.blacklist` | SMS blacklist management |
| **TPOA** | `client.tpoa` | Sender ID (alias) management |
| **Templates** | `client.templates` | SMS template management |
| **Landing Pages** | `client.landing_pages` | List published landing pages |
| **Subaccounts** | `client.subaccounts` | Subaccount and profile management |
| **Two Factor** | `client.two_factor` | 2FA PIN operations |

---

## 🔐 Authentication

The SDK supports multiple authentication methods:

### 1. Username/Password (Recommended)
Automatically obtains and manages access token:
```python
client = SkebbyClient(
    username="your_email@example.com",
    password="your_password"
)
```

### 2. Session Key
```python
# Get session key
user_key, session_key = client.auth.login("username", "password")

# Use session key
client = SkebbyClient(
    user_key=user_key,
    session_key=session_key
)
```

### 3. Access Token
```python
# Get access token
user_key, access_token = client.auth.get_token("username", "password")

# Use access token
client = SkebbyClient(
    user_key=user_key,
    access_token=access_token
)
```

---

## 📚 API Documentation

### User API

Get account information, SMS credits, and service status.

```python
# Get account status
status = client.user.get_status()
print(f"SMS Credits: {status['sms']}")
print(f"Email Service: {status['email']}")

# Get status with money balance
status = client.user.get_status(get_money=True)
print(f"Balance: €{status['money']}")
```

---

### SMS Send API

Send SMS messages with various options.

#### Send Simple SMS
```python
response = client.sms.send_sms(
    phone_number="+393471234567",
    message="Hello World!",
    sender="MyApp",
    message_type="GP"  # GP, TI, SI, or AD
)
```

#### Send Parametric SMS (Template)
```python
response = client.sms.send_parametric_sms(
    recipients=[
        {"phoneNumber": "+393471234567", "parameters": {"NAME": "John"}},
        {"phoneNumber": "+393479876543", "parameters": {"NAME": "Jane"}}
    ],
    text="Hello {NAME}, welcome!",
    sender="MyApp"
)
```

#### Send SMS to Group
```python
response = client.sms.send_sms_to_group(
    group_ids=[123, 456],
    message="Group announcement!",
    sender="MyApp"
)
```

#### Schedule SMS
```python
from datetime import datetime, timedelta

send_time = datetime.now() + timedelta(hours=2)
response = client.sms.send_sms(
    phone_number="+393471234567",
    message="Scheduled message",
    sender="MyApp",
    scheduled_delivery_time=send_time.isoformat()
)
```

#### Delete Scheduled Message
```python
# Delete specific message
client.sms.delete_scheduled_sms(order_id="12345")

# Delete all scheduled messages
client.sms.delete_all_scheduled_sms()
```

---

### SMS History API

Retrieve sent message history and statistics.

```python
# Get SMS history
history = client.sms.get_sms_history(
    from_date="2024-01-01",
    to_date="2024-12-31",
    page_number=1,
    page_size=50
)

# Get SMS to specific recipient
messages = client.sms.get_sms_to_recipient(
    recipient="+393471234567",
    from_date="2024-01-01"
)

# Get Rich SMS statistics
stats = client.sms.get_rich_sms_statistics(order_id="12345")
```

---

### Received SMS API

Get incoming messages (MO - Mobile Originated).

```python
# Get new received messages
new_messages = client.received.get_new_messages()
for msg in new_messages:
    print(f"From: {msg['phoneNumber']}, Text: {msg['text']}")

# Get all received messages with pagination
messages = client.received.get_received_messages(
    page_number=1,
    page_size=50
)

# Get messages after a specific message ID
messages = client.received.get_messages_after(message_id="12345")

# Get MO messages with filters
mo_messages = client.received.get_mo_messages(
    from_date="2024-01-01",
    to_date="2024-12-31"
)
```

---

### Contacts API

Manage your contacts and contact groups.

#### Contacts
```python
# Add a contact
contact = client.contacts.add_contact(
    phone_number="+393471234567",
    name="John",
    surname="Doe",
    email="john.doe@example.com",
    group_ids=[123, 456]
)

# Add multiple contacts
contacts = client.contacts.add_multiple_contacts(
    contacts=[
        {"phoneNumber": "+393471234567", "name": "John"},
        {"phoneNumber": "+393479876543", "name": "Jane"}
    ]
)

# Get a contact
contact = client.contacts.get_contact(contact_id=123)

# Get all contacts
contacts = client.contacts.get_contacts(
    page_number=1,
    page_size=50
)

# Get custom fields
fields = client.contacts.get_custom_fields()
```

#### Contact Groups
```python
# Create a group
group = client.contacts.create_group(
    name="VIP Customers",
    description="Our most valued customers"
)

# Update a group
client.contacts.update_group(
    group_id=123,
    name="Premium Customers",
    description="Updated description"
)

# Get all groups
groups = client.contacts.get_groups(page_number=1, page_size=50)

# Add contact to group
client.contacts.add_contact_to_group(
    group_id=123,
    phone_number="+393471234567"
)

# Remove contact from group
client.contacts.remove_contact_from_group(
    group_id=123,
    phone_number="+393471234567"
)

# Delete a group
client.contacts.delete_group(group_id=123)
```

---

### SMS Blacklist API

Manage the SMS blacklist with the dedicated blacklist API.

```python
# Add single phone number to blacklist
response = client.blacklist.add_phone_number("+393471234567")
print(f"Added to blacklist: {response['result']}")

# Add multiple phone numbers to blacklist
response = client.blacklist.add_multiple_phone_numbers([
    "+393471234567",
    "+393479876543",
    "+393451111111"
])
print(f"Added {response['added']} numbers to blacklist")

# Get blacklist with pagination
blacklist = client.blacklist.get_blacklist(
    page_number=1,
    page_size=50
)

for entry in blacklist['blacklist']:
    print(f"Phone: {entry['phoneNumber']}, Added: {entry['addedDate']}")

# Get blacklist with date filtering
blacklist = client.blacklist.get_blacklist(
    from_date="20240101000000",
    to_date="20241231235959",
    page_number=1,
    page_size=100
)

# Contact-based blacklist operations (via Contacts API)
client.contacts.add_contact_to_blacklist_by_id(contact_id=123)
client.contacts.add_multiple_contacts_to_blacklist(contact_ids=[123, 456, 789])
```

---

### TPOA API (Sender ID / Alias)

Manage sender aliases for your SMS messages.

```python
# Create an alias
alias = client.tpoa.create_alias(
    alias="MyCompany",
    company_name="My Company Ltd",
    contact_name="John",
    contact_surname="Doe",
    cod_fiscale="12345678901",
    vat_number="12345678901",
    contact_address="123 Main St",
    contact_city="Rome",
    contact_pcode="00100",
    contact_type="WEB",
    contact_info="www.mycompany.com"
)

# Get all aliases
aliases = client.tpoa.get_aliases(
    page_number=1,
    page_size=50,
    hide_not_approved=True
)

# Get specific alias
alias = client.tpoa.get_alias(alias_id=123)

# Delete an alias
client.tpoa.delete_alias(alias_id=123)
```

---

### SMS Templates API

Create and manage SMS templates.

```python
# Create a template
template = client.templates.create_template(
    name="Welcome Message",
    text="Welcome {NAME} to our service!",
    encoding="UTF-8",
    sender="MyApp"
)

# Get all templates
templates = client.templates.get_templates()

# Get specific template
template = client.templates.get_template(template_id=123)

# Modify a template (JSON Patch format)
operations = [
    {"op": "replace", "path": "/text", "value": "Updated text"},
    {"op": "replace", "path": "/name", "value": "New Name"}
]
client.templates.modify_template(template_id=123, operations=operations)

# Delete a template
client.templates.delete_template(template_id=123)
```

---

### Landing Pages API

List published landing pages.

```python
# Get all published landing pages
pages = client.landing_pages.get_landing_pages()

for page in pages:
    print(f"ID: {page['id']}")
    print(f"Name: {page['name']}")
    print(f"URL: {page['url']}")
    print(f"Status: {page['status']}")
```

---

### Subaccounts API

Manage subaccounts and their resources.

```python
# Get all subaccounts
subaccounts = client.subaccounts.get_subaccounts()

# Create a subaccount
subaccount = client.subaccounts.create_subaccount(
    login="subuser1",
    password="SecurePass123",
    company="Sub Company",
    phone_number="+393471234567",
    email="sub@example.com"
)

# Get subaccount details
details = client.subaccounts.get_subaccount(username="subuser1")

# Update subaccount
client.subaccounts.update_subaccount(
    username="subuser1",
    email="newemail@example.com",
    lock_subaccount=False
)

# Change passwords
client.subaccounts.change_subaccount_webapp_password(
    username="subuser1",
    new_password="NewPass123"
)

client.subaccounts.change_subaccount_api_password(
    username="subuser1",
    new_password="NewApiPass123"
)

# Get subaccount credits
credits = client.subaccounts.get_subaccount_credits(username="subuser1")

# Manage purchases
purchases = client.subaccounts.get_subaccount_purchases(username="subuser1")

purchase = client.subaccounts.create_subaccount_purchase(
    username="subuser1",
    quantity=1000,
    type="GP"
)

client.subaccounts.delete_subaccount_purchase(
    username="subuser1",
    purchase_id=123
)
```

---

### Subaccount Profiles API

Manage subaccount profiles and services.

```python
# Create a profile
profile = client.subaccounts.create_subaccount_profile(
    name="Basic Profile",
    isDefault=False,
    sharedGroups=[123, 456]
)

# Update a profile
client.subaccounts.update_subaccount_profile(
    profile_id=123,
    name="Updated Profile"
)

# Get all profiles
profiles = client.subaccounts.get_subaccount_profiles()

# Get specific profile
profile = client.subaccounts.get_subaccount_profile(profile_id=123)

# Get activable services
services = client.subaccounts.get_activable_services()

# Remove a profile
client.subaccounts.remove_subaccount_profile(profile_id=123)
```

---

### Two-Factor Authentication API

Send and verify 2FA PIN codes.

```python
# Request a PIN
result = client.two_factor.request_pin(
    recipient="+393471234567",
    sender="MyApp",
    message_type="GP"
)

# Request PIN with custom message
result = client.two_factor.request_pin(
    recipient="+393471234567",
    text="Your verification code is: {pin}"
)

# Verify a PIN
result = client.two_factor.verify_pin(
    recipient="+393471234567",
    pin="123456"
)

if result.get('result') == 'success':
    print("PIN verified successfully!")
else:
    print("Invalid PIN")
```

---

## 🛡️ Error Handling

The SDK provides specific exception classes for different error scenarios:

```python
from skebby_sdk import (
    SkebbyException,
    SkebbyAuthException,
    SkebbyValidationException,
    SkebbyNotFoundException,
    SkebbyRateLimitException,
    SkebbyServerException,
    SkebbyRequestException
)

try:
    response = client.sms.send_sms(
        phone_number="+393471234567",
        message="Test message"
    )
except SkebbyValidationException as e:
    print(f"Validation error: {e}")
except SkebbyAuthException as e:
    print(f"Authentication failed: {e}")
except SkebbyNotFoundException as e:
    print(f"Resource not found: {e}")
except SkebbyRateLimitException as e:
    print(f"Rate limit exceeded: {e}")
except SkebbyServerException as e:
    print(f"Server error: {e}")
except SkebbyRequestException as e:
    print(f"Request failed: {e}")
except SkebbyException as e:
    print(f"General error: {e}")
```

### Exception Hierarchy

- `SkebbyException` - Base exception for all SDK errors
  - `SkebbyAuthException` - Authentication errors (401)
  - `SkebbyRequestException` - Request/network errors
    - `SkebbyValidationException` - Validation errors (400)
    - `SkebbyNotFoundException` - Resource not found (404)
    - `SkebbyRateLimitException` - Rate limit exceeded (429)
    - `SkebbyServerException` - Server errors (5xx)

---

## 🧪 Testing

Run the test suite:

```bash
# Run all tests
python -m unittest discover

# Run specific test file
python -m unittest tests.test_sms

# Run with coverage
pip install coverage
coverage run -m unittest discover
coverage report
```

---

## 📖 API Reference

For complete API documentation, visit the [official Skebby API documentation](https://developers.skebby.it/).

---

## 🤝 Contributing

Contributions are welcome! Please follow these steps:

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

### Development Setup

```bash
# Clone the repository
git clone https://github.com/valeriyglavatskyy/skebby-sdk.git
cd skebby-sdk

# Install in development mode
pip install -e .

# Install development dependencies
pip install -r requirements-dev.txt

# Run tests
python -m unittest discover
```

---

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

---

## 🔗 Links

- [Skebby Website](https://www.skebby.com/)
- [Official API Documentation](https://developers.skebby.it/)
- [GitHub Repository](https://github.com/valeriyglavatskyy/skebby-sdk)
- [Issue Tracker](https://github.com/valeriyglavatskyy/skebby-sdk/issues)

---

## 📝 Changelog

### Version 1.0.0 (2025-11-25)
- ✅ Complete implementation of all 11 Skebby API modules
- ✅ Full alignment with official API documentation (https://developers.skebby.it/?python#)
- ✅ New dedicated BlacklistApi module for SMS blacklist management
- ✅ Fixed subaccount password change endpoints
- ✅ Comprehensive error handling
- ✅ Complete type hints support (100% coverage)
- ✅ Extensive documentation and examples
- ✅ Verified against 368+ documentation sections

---

**Made with ❤️ for the Skebby community**