Metadata-Version: 2.4
Name: dikidi-api
Version: 0.1.1
Summary: Unofficial Python library for Dikidi (beauty salon booking platform API). Based on reverse-engineered real browser requests.
Project-URL: Homepage, https://github.com/asbevz/dikidi-api
Project-URL: Source, https://github.com/asbevz/dikidi-api
Author-email: Aleksandr Bevz <as-bivz@yandex.ru>
License: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Office/Business :: Scheduling
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: httpx>=0.28
Description-Content-Type: text/markdown

<div align="center">

# 📅 dikidi-api

**Unofficial Dikidi API Client**

[![PyPI - Version](https://img.shields.io/pypi/v/dikidi-api?color=blue&style=flat-square)](https://pypi.org/project/dikidi-api/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dikidi-api?color=blue&style=flat-square)](https://pypi.org/project/dikidi-api/)
[![GitHub License](https://img.shields.io/github/license/asbevz/dikidi-api?style=flat-square)](LICENSE)
[![CI](https://github.com/asbevz/dikidi-api/actions/workflows/ci.yml/badge.svg?style=flat-square)](https://github.com/asbevz/dikidi-api/actions/workflows/ci.yml)

🐍 Async + Sync Python client for [Dikidi](https://dikidi.ru) — beauty salon booking platform.

Get appointments, clients, services, schedules, finances, marketing data and more.

> Based on reverse-engineered real browser AJAX requests. Built on `httpx`.

</div>

---

## 📦 Installation

```bash
pip install dikidi-api
```

Requires **Python 3.11+**.

---

## 🚀 Quick Start

### Sync

```python
from dikidi_api import SyncDikidiClient

with SyncDikidiClient("+79991234567", "password", company_id=12345) as client:
    client.auth()

    journal = client.journal.get_api_data("2026-06-01", "2026-06-07")
    for section in ("masters", "resources"):
        info = journal.get(section, {}).get("info", {})
        records = journal.get(section, {}).get("records", {}).get("data", {})
        for mid in info.get("ids", []):
            name = info.get("data", {}).get(mid, {}).get("title", f"ID {mid}")
            count = sum(len(v) for v in records.get(mid, {}).values())
            if count:
                print(f"{name}: {count} appointments")

    clients = client.clients.find("Иван")
    for c in clients:
        print(f"{c['name']} — {c['phone']}")
```

### Async

```python
import asyncio
from dikidi_api import AsyncDikidiClient


async def main():
    async with AsyncDikidiClient("+79991234567", "password", company_id=12345) as client:
        await client.auth()
        journal = await client.journal.get_api_data("2026-06-01", "2026-06-07")
        print(journal)


asyncio.run(main())
```

---

## 📖 API Reference

### Clients

Both clients share the same endpoint interface. The only difference is `await` on async calls.

| Client | Import | HTTP Engine | Methods |
|--------|--------|-------------|---------|
| `AsyncDikidiClient` | `from dikidi_api import AsyncDikidiClient` | `httpx.AsyncClient` | `async` |
| `SyncDikidiClient` | `from dikidi_api import SyncDikidiClient` | `httpx.Client` | sync |

```python
client = SyncDikidiClient(login, password, company_id)
client.auth()
client.close()

# or
with SyncDikidiClient(login, password, company_id) as client:
    client.auth()
```

```python
client = AsyncDikidiClient(login, password, company_id)
await client.auth()
await client.close()

# or
async with AsyncDikidiClient(login, password, company_id) as client:
    await client.auth()
```

### Journal

| Method | Description |
|--------|-------------|
| `get_api_data(date_from, date_to, ...)` | Full journal: masters, resources, records, schedules |
| `get_page()` | Journal page data |
| `get_appointments(start, end, ...)` | Filtered appointment list |
| `get_filters_data()` | Filter data |
| `get_finance_widget_data()` | Finance summary |
| `get_appointment_config()` | Booking config |

### Clients

| Method | Description |
|--------|-------------|
| `get_filter()` | Client list page |
| `find(query)` | Search by name/phone |
| `get_data_on_load(clients_ids, ...)` | Extended client data |

### Schedule

| Method | Description |
|--------|-------------|
| `get_page()` | Schedule page |

### Services

| Method | Description |
|--------|-------------|
| `get_filter()` | Service list |
| `get_masters()` | Master list |

### Finance

| Method | Description |
|--------|-------------|
| `get_bonuses()` | Loyalty program |
| `get_payment_filter()` | Payments |
| `get_payroll()` | Payroll |
| `get_salary_settlements()` | Salary settlements |
| `get_salary_sheets()` | Salary sheets |
| `get_salary_schemes()` | Salary schemes |

### Marketing

| Method | Description |
|--------|-------------|
| `get_mailing()` | Mailing campaigns |
| `get_reviews()` | Reviews |
| `get_retention()` | Client retention |
| `get_season_tickets()` | Season tickets |
| `get_certificates()` | Gift certificates |
| `get_tips()` | Tips |
| `get_fines()` | Fines |
| `get_ats()` | Phone system (ATS) |
| `get_sms_ready_messages()` | Ready SMS messages |

### Company

| Method | Description |
|--------|-------------|
| `get_profile()` | Company profile |
| `get_permissions()` | Permissions |
| `get_notifications()` | Notifications |
| `get_alerts()` | Alerts |
| `get_chat_page()` | Chat page |
| `get_chat_unread()` | Unread chat dialogs |
| `get_online_record_properties()` | Online booking settings |
| `get_resources()` | Resources |

---

## 🛠 Development

```bash
uv sync                        # Install all dependencies
uv run pytest -v               # Run unit tests (no .env required)
uv run pytest -v -m integration  # Run integration tests (requires .env)
uv build                       # Build sdist + wheel
uv publish                     # Publish to PyPI
```

### Test Suite

| Type | Count | Command |
|------|-------|---------|
| 🔬 Unit (mocked) | 14 | `uv run pytest` |
| 🌐 Integration (live API) | 14 | `uv run pytest -m integration` |

Integration tests require `.env` in project root with `LOGIN_DIKIDI`, `PASSWORD_DIKIDI`, `COMPANY_DIKIDI`. Without it they skip automatically.

---

## 🔗 Links

- **Dikidi:** [dikidi.ru](https://dikidi.ru)
- **PyPI:** [dikidi-api](https://pypi.org/project/dikidi-api/)

---

## ☕ Donate

If this library saves you time or helps your business, consider supporting its development:

| Crypto | Address |
|--------|---------|
| ₿ Bitcoin (BTC) | `bc1q98gg278ywqdfhmxpfttuvsyskdxxmg0ac4sg5a` |
| ◉ USDT (TRC-20) | `TFf8jHqaoTWEEx6XzHTdRpLkMcYcwwRd17` |
| ◎ USDT (Solana) | `8SZc4jQoMKQeedJMe9VS5bnrWF8PCKvDjwixz3Zg4p2W` |

Your support keeps the project alive and up to date ❤️

---

## 📄 License

[MIT](LICENSE)

© 2026 [Aleksandr Bevz](https://github.com/asbevz)

---

<div align="center">
<small>Not affiliated with Dikidi.</small>
</div>
