Metadata-Version: 2.4
Name: kynode
Version: 0.1.0
Summary: Official Python SDK for Kynode Korean Business Verification API
Project-URL: Homepage, https://kynode.dev
Project-URL: Documentation, https://kynode.dev/docs/api-reference
Project-URL: Repository, https://github.com/kynode/kynode-python
Author-email: Nodemetrics <hello@kynode.dev>
License: MIT
Keywords: api,business-verification,korea,kyb,kynode
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.8
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: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.8
Requires-Dist: httpx<1.0.0,>=0.24.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Description-Content-Type: text/markdown

# kynode

Official Python SDK for the [Kynode](https://kynode.dev) Korean Business Verification API.

Verify Korean business registration numbers against NTS data with optional DART-verified English company names.

## Requirements

- Python 3.8+
- `httpx` (installed automatically)

## Installation

```bash
pip install kynode
```

## Quick start

```python
from kynode import Kynode

client = Kynode(api_key="sk_live_...")

result = client.verify(
    business_number="8090903407",
    start_date="20260513",
    owner_name="강민구",
    company_name="노드메트릭스",
    language="en",
)

print(result["isValid"], result.get("businessInfo", {}).get("companyName"))
```

## Client options

| Parameter  | Type    | Default                                 | Description           |
| ---------- | ------- | --------------------------------------- | --------------------- |
| `api_key`  | `str`   | required                                | Your Kynode API key   |
| `base_url` | `str`   | `https://kynode-api.kynode.workers.dev` | API base URL          |
| `timeout`  | `float` | `30.0`                                  | Request timeout (sec) |

Use as a context manager to close HTTP connections:

```python
with Kynode(api_key="sk_live_...") as client:
    result = client.verify(...)
```

## Single verification (sync)

```python
result = client.verify(
    business_number="1234567890",
    start_date="20240101",
    owner_name="홍길동",
    language="en",  # optional: en | ko | both | code (default: en)
)
```

Calls `POST /v1/verify` with Bearer authentication.

## Single verification (async)

```python
import asyncio
from kynode import Kynode

async def main():
    client = Kynode(api_key="sk_live_...")
    try:
        result = await client.verify_async(
            business_number="1234567890",
            start_date="20240101",
            owner_name="홍길동",
        )
        print(result)
    finally:
        await client.aclose()

asyncio.run(main())
```

## Batch verification (sync)

```python
batch = client.batch_verify([
    {"business_number": "1234567890", "start_date": "20240101", "owner_name": "홍길동"},
    {"business_number": "9876543210", "start_date": "20240101", "owner_name": "김철수"},
])

print(batch["total"], batch["success"], batch["failed"])
for row in batch["results"]:
    if row["success"]:
        print(row["business_number"], row["data"])
    else:
        print(row["business_number"], row["error"])
```

- If all items share the same `start_date`, `owner_name`, `language`, and `company_name`, the client calls `POST /v1/batch/verify` (Pro tier and above).
- If fields differ per row, the client runs parallel single verifications and returns a batch-shaped response.

## Batch verification (async)

```python
batch = await client.batch_verify_async([...])
```

## Error handling

```python
from kynode import (
    Kynode,
    KynodeError,
    KynodeAuthError,
    KynodeQuotaError,
    KynodeValidationError,
    KynodeNotFoundError,
)

try:
    client.verify(...)
except KynodeAuthError:
    # 401 — invalid or missing API key
    pass
except KynodeQuotaError:
    # 429 — monthly quota exceeded
    pass
except KynodeValidationError:
    # 400 — invalid request
    pass
except KynodeNotFoundError:
    # 404 — endpoint not found
    pass
except KynodeError as exc:
    print(exc.status_code, exc.code, exc.message, exc.details)
```

| Exception               | HTTP status | Typical cause                 |
| ----------------------- | ----------- | ----------------------------- |
| `KynodeAuthError`       | 401         | Invalid API key               |
| `KynodeValidationError` | 400         | Missing or invalid parameters |
| `KynodeNotFoundError`   | 404         | Unknown endpoint              |
| `KynodeQuotaError`      | 429         | Monthly quota exceeded        |
| `KynodeError`           | other       | Server errors, timeouts       |

Timeouts raise `KynodeError` with `code="timeout"` and `status_code=408`.

## Development

```bash
cd kynode
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pytest
```

## Build for PyPI

```bash
pip install build twine
python -m build
twine check dist/*
# twine upload dist/*
```

## Links

- [API documentation](https://kynode.dev/docs/api-reference)
- [Get an API key](https://kynode.dev/dashboard)

## License

MIT
