Metadata-Version: 2.5
Name: hatang
Version: 0.1.1
Summary: Official Python SDK for Ha Tang (hatang.dev): customer support CRM and live chat, plans and in-app purchases, AI knowledge base, email API, VietQR payments and webhooks for Vietnam.
Project-URL: Homepage, https://hatang.dev
Project-URL: Documentation, https://hatang.dev/docs/guides/sdks/python
Project-URL: API reference, https://hatang.dev/docs/reference/api
Project-URL: Changelog, https://hatang.dev/docs/changelog
Project-URL: Issues, https://hatang.dev/contact
Author-email: Sota Labs <hello@hatang.dev>
License-Expression: MIT
License-File: LICENSE
Keywords: crm,customer support,email api,ha tang,hatang,helpdesk,in-app purchases,live chat,payments,transactional email,vietnam,vietqr,webhooks,zalo
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Communications :: Email
Classifier: Topic :: Office/Business
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx<1,>=0.25
Description-Content-Type: text/markdown

# hatang

<!-- hatang:badge:start -->
[![PyPI](https://img.shields.io/pypi/v/hatang)](https://pypi.org/project/hatang/)
<!-- hatang:badge:end -->

The official Python SDK for [Ha Tang](https://hatang.dev): customer support CRM and live chat, plans and purchases on the customer's profile,
the AI assistant's knowledge, email, VietQR payments and webhooks.

```bash
pip install hatang
```

Python 3.9+. Sync (`Hatang`) and asyncio (`AsyncHatang`) clients, typed request bodies.

## Quick start

```python
from hatang import Hatang

hatang = Hatang()  # reads HATANG_API_KEY; or Hatang("ht_…")

# What a customer pays for, from your backend (web sales included).
hatang.chat.subscriptions.upsert("web", "sub_123", {
    "status": "active",
    "sku": "PRO-1M",                    # finds the product in your catalog
    "external_user_id": "user-42",      # the id you pass to identify() in the chat
    "current_period_end": "2026-12-01T00:00:00Z",
    "amount": 99000, "currency": "VND",
})
hatang.chat.purchases.upsert("web", "order_981", {
    "store_product_id": "credits.300", "sku": "XU-300", "kind": "consumable",
    "external_user_id": "user-42", "amount": 29000, "currency": "VND",
})
```

asyncio (FastAPI, aiohttp…):

```python
from hatang import AsyncHatang

async with AsyncHatang() as hatang:
    hits = await hatang.knowledge.search("hoàn tiền", limit=3)
```

Every method returns the API's JSON as a `dict`. A call that does not succeed raises `HatangError` with `status_code`
(0 when Ha Tang was not reached), `name` (`validation_error`, `not_found`…), `message`, and `retryable` (unreachable,
429 or 5xx).

## What is in it

| Namespace | Methods |
|---|---|
| `chat.subscriptions` | `upsert`, `list`, `for_customer`, `purchase_token` |
| `chat.purchases` | `upsert`, `list`, `for_customer` |
| `chat.customers` | `list`, `get`, `update`, `conversations`, `export_csv` |
| `chat.conversations` | `list`, `get`, `update`, `messages`, `send`, `send_products` |
| `chat.products` | `list`, `search`, `get`, `create`, `update`, `remove` |
| `chat.orders` | `list`, `get`, `create`, `update`, `payment_link` |
| `knowledge` | `upsert`, `batch`, `sync`, `get`, `list`, `remove`, `search` |
| `emails`, `batch` | `send`, `get`, `list`, `update`, `cancel`; `batch.send` |
| `payments` | `create`, `get`, `list`, `cancel` |
| `events` | `send` |

## Helpers

```python
from hatang import identity_hash, purchase_token, construct_webhook_event, construct_ipn_event

# Signed chat identity: send this as `hash` with userId to identify() in the widget or the app SDKs.
identity_hash("user-42", IDENTITY_SECRET)

# StoreKit appAccountToken / Google Play obfuscatedAccountId for one of your users.
purchase_token("site_…", "user-42")

# Webhooks (whsec_… secret) and payment IPN calls: pass the raw body, before JSON parsing.
event = construct_webhook_event(request.body, request.headers, WEBHOOK_SECRET)
ipn = construct_ipn_event(request.body, request.headers, SECRET_KEY)
```

Both raise `HatangSignatureError` when the signature does not match; `verify_webhook` / `verify_ipn` return a bool.

## Configuration

| Argument | Environment | Default |
|---|---|---|
| `api_key` | `HATANG_API_KEY` | required |
| `base_url` | `HATANG_BASE_URL` | `https://api.hatang.dev` |
| `environment` | `HATANG_ENVIRONMENT` | the key's own |
| `timeout` | | 30 s |
| `http_client` | | an `httpx.Client` / `httpx.AsyncClient` of your own (proxies, retries, tests) |

License: MIT

<!-- hatang:about:start -->
<!-- generated by scripts/sync-versions.ts from sdks/listing.json, do not edit -->
## About Ha Tang

[Ha Tang](https://hatang.dev) (Hạ Tầng) is a customer support platform for businesses in Vietnam: one inbox for your website, mobile app, Zalo, Messenger, Instagram, TikTok Shop, WhatsApp and email, with an AI assistant, plus a transactional email API, VietQR payments and e-invoices.

- Product: [hatang.dev](https://hatang.dev)
- Guide: [Ha Tang Python SDK](https://hatang.dev/docs/guides/sdks/python) ([Tiếng Việt](https://hatang.dev/vi/docs/guides/sdks/python))
- REST API: [hatang.dev/docs/reference/api](https://hatang.dev/docs/reference/api)
- Changelog: [hatang.dev/docs/changelog](https://hatang.dev/docs/changelog)
- Support: [hatang.dev/contact](https://hatang.dev/contact)
<!-- hatang:about:end -->
