Metadata-Version: 2.4
Name: wioclinic
Version: 0.1.1
Summary: Official Python SDK for the WioClinic Developer API
Project-URL: Homepage, https://wioclinic.services
Project-URL: Documentation, https://developer.wioclinic.services/
Project-URL: Repository, https://github.com/WioClinic/wioclinic-python
Project-URL: Bug Tracker, https://github.com/WioClinic/wioclinic-python/issues
Author-email: WioClinic <hello@wioclinic.com>
License: MIT
License-File: LICENSE
Keywords: api,clinic,healthcare,sdk,wioclinic
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx>=0.25.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-httpx>=0.22; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# WioClinic Python SDK

Official Python SDK for the [WioClinic Developer API](https://developer.wioclinic.services/).

[![PyPI version](https://badge.fury.io/py/wioclinic.svg)](https://pypi.org/project/wioclinic/)
[![Python Versions](https://img.shields.io/pypi/pyversions/wioclinic.svg)](https://pypi.org/project/wioclinic/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## Requirements

- Python 3.9+
- `httpx` ≥ 0.25

## Installation

```bash
pip install wioclinic
```

## Authentication

Generate an API key from the WioClinic Developer Portal (`Settings → API Keys`). You will receive:

- **Key ID** — starts with `pk_live_` (public, safe to log)
- **Secret** — starts with `wcs_live_` (treat like a password)

## Quick Start

```python
from wioclinic import WioClinic

client = WioClinic(
    key_id="pk_live_your_key_id",
    secret="wcs_live_your_secret",
)

# List patients
page = client.patients.list(limit=10)
print(f"Found {page.total} patients")
for patient in page:
    print(patient["full_name"])

# Get a single patient
patient = client.patients.get("patient-uuid")

# Create a patient
new_patient = client.patients.create(
    first_name="Jane",
    last_name="Smith",
    date_of_birth="1985-06-15",
    gender="female",
    phone_number="+14155550100",
    email_address="jane.smith@example.com",
)
```

## Patients

```python
# List with filters
page = client.patients.list(
    page=1,
    limit=20,
    search="smith",      # Searches name, phone, email, national ID
    is_active=True,
)

# CRUD
patient = client.patients.get(patient_id)
patient = client.patients.create(first_name="Jane", last_name="Smith")
patient = client.patients.update(patient_id, phone_number="+14155550199")
client.patients.deactivate(patient_id)
```

## Appointments

```python
# List appointments (date range max 31 days)
page = client.appointments.list(
    date_from="2026-06-01",
    date_to="2026-06-30",
    patient_id="patient-uuid",   # optional
    status="scheduled",          # optional
)

# Get / create / update
appt = client.appointments.get(appointment_id)
appt = client.appointments.create(
    patient_id="patient-uuid",
    doctor_id="doctor-uuid",
    appointment_date="2026-07-01",
    start_time="10:00",
    end_time="10:30",
)
appt = client.appointments.update(appointment_id, start_time="11:00")

# Lifecycle transitions
client.appointments.confirm(appointment_id)
client.appointments.check_in(appointment_id)
client.appointments.complete(appointment_id)
client.appointments.cancel(appointment_id, reason="Patient request")
client.appointments.no_show(appointment_id)
```

## Availability

```python
result = client.availability.check(
    doctor_id="doctor-uuid",
    date="2026-07-01",
    duration=30,   # minutes, optional
)

for slot in result["available_slots"]:
    print(slot["start"], "–", slot["end"])
```

## Clinic

```python
clinic      = client.clinic.get()
doctors     = client.clinic.doctors()
depts       = client.clinic.departments()
rooms       = client.clinic.rooms()
treatments  = client.clinic.treatments()
price_lists = client.clinic.price_lists()
```

## Finance

```python
# Invoices
page    = client.finance.list_invoices(status="paid", from_date="2026-01-01")
invoice = client.finance.get_invoice(invoice_id)
pmts    = client.finance.invoice_payments(invoice_id)

# Payments
page = client.finance.list_payments(from_date="2026-01-01", to_date="2026-12-31")

# Shortcuts: client.invoices / client.payments also work
page = client.invoices.list_invoices(limit=5)
```

## Messages (SMS / Email)

```python
# Send SMS
client.messages.send(
    patient_id="patient-uuid",
    channel="sms",
    message="Your appointment is tomorrow at 10:00.",
)

# Send email
client.messages.send(
    patient_id="patient-uuid",
    channel="email",
    subject="Appointment Reminder",
    message="<p>Your appointment is tomorrow at 10:00.</p>",
)

# List sent messages
page = client.messages.list(channel="sms")
```

## Webhooks

```python
# List webhooks
hooks = client.webhooks.list()

# Create
hook = client.webhooks.create(
    target_url="https://example.com/wio-events",
    subscribed_events=["appointment.created", "patient.created"],
    signing_secret="my-hmac-secret",
)

# Update
client.webhooks.update(hook["id"], subscribed_events=["appointment.cancelled"])

# Test connectivity
client.webhooks.test(hook["id"])

# View recent deliveries
deliveries = client.webhooks.deliveries(hook["id"])

# Replay a failed delivery
client.webhooks.replay_delivery(hook["id"], delivery_id)

# Delete
client.webhooks.delete(hook["id"])
```

## Pagination

List methods return a `Page` object:

```python
page = client.patients.list(page=1, limit=20)

page.data        # list of result dicts
page.total       # total record count
page.page        # current page number
page.limit       # records per page
page.has_more    # True if there are additional pages

# Iterate directly
for patient in page:
    print(patient["full_name"])

# Fetch all pages manually
all_patients = []
p = 1
while True:
    page = client.patients.list(page=p, limit=100)
    all_patients.extend(page.data)
    if not page.has_more:
        break
    p += 1
```

## Error Handling

```python
from wioclinic import (
    WioClinicError,           # base class
    AuthenticationError,      # 401 — bad key/secret
    PermissionDeniedError,    # 403
    NotFoundError,            # 404
    UnprocessableEntityError, # 422 — validation errors
    RateLimitError,           # 429
    InternalServerError,      # 5xx
    APIConnectionError,       # network issues
)

try:
    patient = client.patients.get("some-id")
except NotFoundError as e:
    print(f"Patient not found (request_id={e.request_id})")
except AuthenticationError:
    print("Check your API key and secret")
except WioClinicError as e:
    print(f"API error {e.status_code}: {e.message}")
```

## Advanced: Custom HTTP Client

Pass a custom `httpx.Client` for proxy support, custom TLS, etc.:

```python
import httpx
from wioclinic import WioClinic

transport = httpx.HTTPTransport(proxy="http://my-proxy:8080")
http = httpx.Client(transport=transport, timeout=60)

client = WioClinic(key_id="pk_live_your_key_id", secret="wcs_live_your_secret", http_client=http)
```

## Context Manager

```python
with WioClinic(key_id="pk_live_your_key_id", secret="wcs_live_your_secret") as client:
    doctors = client.clinic.doctors()
# connection pool is automatically closed
```

## Supported Events (Webhooks)

| Event | Triggered when |
|-------|---------------|
| `appointment.created` | New appointment is booked |
| `appointment.updated` | Appointment details change |
| `appointment.cancelled` | Appointment is cancelled |
| `appointment.completed` | Appointment is marked complete |
| `patient.created` | New patient is registered |
| `patient.updated` | Patient profile is updated |
| `invoice.created` | Invoice is generated |
| `invoice.paid` | Invoice is fully paid |
| `payment.received` | Payment transaction recorded |

## Support

- Documentation: [developer.wioclinic.services](https://developer.wioclinic.services/)
- Email: hello@wioclinic.com
- Issues: [GitHub Issues](https://github.com/WioClinic/wioclinic-python/issues)

## License

MIT
