namecheap-python 1.1.0__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. namecheap_python-1.2.0/CLAUDE.md +2 -0
  2. namecheap_python-1.2.0/CONTRIBUTING.md +113 -0
  3. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/PKG-INFO +83 -14
  4. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/README.md +82 -13
  5. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/pyproject.toml +1 -1
  6. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/__init__.py +14 -2
  7. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/_api/dns.py +35 -1
  8. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/_api/domains.py +47 -1
  9. namecheap_python-1.2.0/src/namecheap/_api/users.py +32 -0
  10. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/client.py +8 -0
  11. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/models.py +60 -0
  12. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_cli/__main__.py +86 -50
  13. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/uv.lock +1 -1
  14. namecheap_python-1.1.0/docs/dev/README.md +0 -220
  15. namecheap_python-1.1.0/pending.md +0 -94
  16. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/.env.example +0 -0
  17. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/.github/cliff.toml +0 -0
  18. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/.github/workflows/release.yml +0 -0
  19. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/.gitignore +0 -0
  20. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/.pre-commit-config.yaml +0 -0
  21. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/CLI.md +0 -0
  22. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/LICENSE +0 -0
  23. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/MANIFEST.in +0 -0
  24. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/examples/README.md +0 -0
  25. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/examples/quickstart.py +0 -0
  26. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/_api/__init__.py +0 -0
  27. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/_api/base.py +0 -0
  28. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/errors.py +0 -0
  29. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap/logging.py +0 -0
  30. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_cli/README.md +0 -0
  31. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_cli/__init__.py +0 -0
  32. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_cli/completion.py +0 -0
  33. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_dns_tui/README.md +0 -0
  34. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_dns_tui/__init__.py +0 -0
  35. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_dns_tui/__main__.py +0 -0
  36. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_dns_tui/assets/screenshot1.png +0 -0
  37. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_dns_tui/assets/screenshot2.png +0 -0
  38. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_dns_tui/assets/screenshot3.png +0 -0
  39. {namecheap_python-1.1.0 → namecheap_python-1.2.0}/src/namecheap_dns_tui/assets/screenshot4.png +0 -0
@@ -0,0 +1,2 @@
1
+ @README.md
2
+ @CONTRIBUTING.md
@@ -0,0 +1,113 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ git clone https://github.com/adriangalilea/namecheap-python.git
7
+ cd namecheap-python
8
+ uv sync --all-extras
9
+ pre-commit install
10
+ ```
11
+
12
+ ## Code Quality
13
+
14
+ ```bash
15
+ uv run ruff check # lint
16
+ uv run ruff check --fix # auto-fix
17
+ uv run ruff format # format
18
+
19
+ pre-commit run --all-files # run all hooks
20
+ ```
21
+
22
+ ## Building
23
+
24
+ ```bash
25
+ uv build
26
+ ```
27
+
28
+ ## Release
29
+
30
+ Automated via GitHub Actions on push to `main`. If the version in `pyproject.toml` doesn't exist on PyPI, CI publishes automatically, creates a git tag, and generates a GitHub release with changelog via [git-cliff](https://git-cliff.org/).
31
+
32
+ Bump version in both `pyproject.toml` and `src/namecheap/__init__.py`.
33
+
34
+ ## Debugging
35
+
36
+ ```python
37
+ import logging
38
+ logging.basicConfig(level=logging.DEBUG)
39
+ ```
40
+
41
+ Or set `NAMECHEAP_DEBUG=true`.
42
+
43
+ ## Architecture
44
+
45
+ ### Project Structure
46
+
47
+ ```
48
+ src/
49
+ ├── namecheap/ # Core SDK
50
+ │ ├── client.py # Main client — wires up API classes
51
+ │ ├── models.py # Pydantic models (all API data types live here)
52
+ │ ├── errors.py # Exceptions with helpful messages
53
+ │ ├── logging.py # Colored logging and error display
54
+ │ └── _api/ # API implementations
55
+ │ ├── base.py # BaseAPI with _request() — all API calls go through here
56
+ │ ├── domains.py # namecheap.domains.* endpoints
57
+ │ └── dns.py # namecheap.domains.dns.* endpoints + builder
58
+ ├── namecheap_cli/ # CLI (click)
59
+ │ ├── __main__.py # All commands in one file
60
+ │ └── completion.py # Shell completions
61
+ └── namecheap_dns_tui/ # TUI (textual)
62
+ └── __main__.py
63
+ ```
64
+
65
+ ### Key Patterns
66
+
67
+ **SDK layer** (`src/namecheap/_api/`):
68
+ - Every API class extends `BaseAPI` which provides `_request(command, params, model=, path=)`
69
+ - `_request` handles auth params, XML parsing, error handling, and Pydantic deserialization
70
+ - Pass `model=SomeModel` to auto-parse, or omit for raw dict access
71
+ - Pass `path="DotSeparated.Path"` to navigate the XML response
72
+ - Domain parsing uses `tldextract` to split into SLD/TLD — see any method in `dns.py`
73
+ - Return Pydantic models, not dicts — see `Nameservers`, `DNSRecord`, `Domain`, etc.
74
+ - Use `assert` for assumptions, `ValueError` for bad user input
75
+
76
+ **Models** (`src/namecheap/models.py`):
77
+ - `XMLModel` base handles XML attribute aliases (`@Name` → `name`) and boolean parsing
78
+ - All new data types go here and get exported from `__init__.py`
79
+
80
+ **CLI layer** (`src/namecheap_cli/__main__.py`):
81
+ - Commands use `@pass_config` decorator for client initialization
82
+ - Interactive operations use `rich.progress.Progress` with `SpinnerColumn` for loading
83
+ - Destructive operations use `rich.prompt.Confirm.ask` with `--yes/-y` to skip
84
+ - Table output via `rich.table.Table`, with `output_formatter()` for JSON/YAML alternatives
85
+ - Error handling: catch `NamecheapError`, print with `[red]`, `sys.exit(1)`
86
+
87
+ **DNS Builder** (`src/namecheap/_api/dns.py`):
88
+ - Fluent interface: `builder.a(...).mx(...).txt(...)` returns `Self` for chaining
89
+ - Default TTL is 1799 (displays as "Automatic" in Namecheap UI)
90
+
91
+ ### Adding a New API Endpoint
92
+
93
+ 1. Add Pydantic model in `models.py`, export from `__init__.py`
94
+ 2. Add method in the appropriate `_api/*.py` file using `self._request()`
95
+ 3. Add CLI command in `__main__.py` following existing patterns
96
+ 4. Update the API Coverage table in `README.md`
97
+
98
+ Best reference: `dns.py:get_nameservers()` for SDK, `__main__.py:dns_nameservers()` for CLI.
99
+
100
+ ## PR Checklist
101
+
102
+ - [ ] `uv run ruff check` passes
103
+ - [ ] `uv run ruff format --check` passes
104
+ - [ ] Examples work correctly
105
+ - [ ] Documentation updated if needed
106
+
107
+ ## Links
108
+
109
+ - [Namecheap API Documentation](https://www.namecheap.com/support/api/methods/)
110
+ - [Pydantic Documentation](https://docs.pydantic.dev/)
111
+ - [Click Documentation](https://click.palletsprojects.com/)
112
+ - [Textual Documentation](https://textual.textualize.io/)
113
+ - [Ruff Documentation](https://docs.astral.sh/ruff/)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: namecheap-python
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: A friendly Python SDK for Namecheap API
5
5
  Project-URL: Homepage, https://github.com/adriangalilea/namecheap-python
6
6
  Project-URL: Repository, https://github.com/adriangalilea/namecheap-python
@@ -42,6 +42,12 @@ Description-Content-Type: text/markdown
42
42
 
43
43
  # Namecheap Python SDK
44
44
 
45
+ [![PyPI version](https://badge.fury.io/py/namecheap-python.svg)](https://pypi.org/project/namecheap-python/)
46
+ [![Downloads](https://pepy.tech/badge/namecheap-python)](https://pepy.tech/project/namecheap-python)
47
+ [![Downloads/month](https://pepy.tech/badge/namecheap-python/month)](https://pepy.tech/project/namecheap-python)
48
+ [![Python](https://img.shields.io/pypi/pyversions/namecheap-python)](https://pypi.org/project/namecheap-python/)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
50
+
45
51
  A modern, friendly Python SDK for the Namecheap API with comprehensive CLI and TUI tools.
46
52
 
47
53
  ## 🚀 Features
@@ -206,6 +212,38 @@ Adding CNAME record to tdo.garden...
206
212
  ```
207
213
 
208
214
 
215
+ Check account balance:
216
+
217
+ ```bash
218
+ ❯ namecheap-cli account balance
219
+ Account Balance
220
+ ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
221
+ ┃ Field ┃ Amount ┃
222
+ ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
223
+ │ Available Balance │ 0.00 USD │
224
+ │ Account Balance │ 0.00 USD │
225
+ │ Earned Amount │ 0.00 USD │
226
+ │ Withdrawable │ 0.00 USD │
227
+ │ Auto-Renew Required │ 20.16 USD │
228
+ └─────────────────────┴───────────┘
229
+ ```
230
+
231
+ Get detailed domain info:
232
+
233
+ ```bash
234
+ ❯ namecheap-cli domain info self.fm
235
+
236
+ Domain Information: self.fm
237
+
238
+ Status: Ok
239
+ Owner: adriangalilea
240
+ Created: 07/15/2023
241
+ Expires: 07/15/2026
242
+ Premium: No
243
+ WHOIS Guard: ✓ Enabled
244
+ DNS Provider: CUSTOM
245
+ ```
246
+
209
247
  You can also export DNS records:
210
248
 
211
249
  ```bash
@@ -320,6 +358,33 @@ nc.dns.set_custom_nameservers("example.com", [
320
358
  nc.dns.set_default_nameservers("example.com")
321
359
  ```
322
360
 
361
+ ### Domain Info
362
+
363
+ ```python
364
+ info = nc.domains.get_info("example.com")
365
+ print(info.status) # 'Ok'
366
+ print(info.whoisguard_enabled) # True
367
+ print(info.dns_provider) # 'CUSTOM'
368
+ print(info.created) # '07/15/2023'
369
+ print(info.expires) # '07/15/2026'
370
+ ```
371
+
372
+ ### Account Balance
373
+
374
+ ```python
375
+ bal = nc.users.get_balances()
376
+ print(f"{bal.available_balance} {bal.currency}") # '4932.96 USD'
377
+ print(bal.funds_required_for_auto_renew) # Decimal('20.16')
378
+ ```
379
+
380
+ ### Email Forwarding
381
+
382
+ ```python
383
+ rules = nc.dns.get_email_forwarding("example.com")
384
+ for r in rules:
385
+ print(f"{r.mailbox} -> {r.forward_to}")
386
+ ```
387
+
323
388
  ### Domain Management
324
389
 
325
390
  ```python
@@ -393,22 +458,24 @@ nc.dns.builder().a("www", "192.0.2.1", ttl=1799) # Shows as "Automatic"
393
458
  nc.dns.builder().a("www", "192.0.2.1", ttl=1800) # Shows as "30 min"
394
459
  ```
395
460
 
396
- ## 🚧 Pending Features
397
-
398
- The following Namecheap API features are planned for future releases:
399
-
400
- - **SSL API** - Certificate management
401
- - **Domain Transfer API** - Transfer domains between registrars
402
- - **Domain NS API** - Glue record management (child nameservers)
403
- - **Users API** - Account management and balance checking
404
- - **Whois API** - WHOIS information lookups
405
- - **Email Forwarding** - Email forwarding configuration
406
-
407
- See [pending.md](pending.md) for full details.
461
+ ## 📊 [API Coverage](https://www.namecheap.com/support/api/methods/)
462
+
463
+ | API | Status | Methods |
464
+ |-----|--------|---------|
465
+ | `namecheap.domains.*` | Done | `check`, `list`, `getInfo`, `register`, `renew`, `setContacts`, `lock`/`unlock` |
466
+ | `namecheap.domains.dns.*` | Done | `getHosts`, `setHosts` (builder pattern), `add`, `delete`, `export`, `getList`, `setCustom`, `setDefault`, `getEmailForwarding` |
467
+ | `namecheap.users.*` | ⚠️ Partial | `getBalances`, `getPricing` (needs debugging). Planned: `changePassword`, `update`, `create`, `login`, `resetPassword` |
468
+ | `namecheap.domains.*` | 🚧 Planned | `getContacts`, `getTldList`, `reactivate` |
469
+ | `namecheap.domains.dns.*` | 🚧 Planned | `setEmailForwarding` |
470
+ | `namecheap.users.address.*` | 🚧 Planned | `create`, `delete`, `getInfo`, `getList`, `setDefault`, `update` |
471
+ | `namecheap.ssl.*` | 🚧 Planned | `create`, `activate`, `renew`, `revoke`, `getList`, `getInfo`, `parseCSR`, `reissue`, and more |
472
+ | `namecheap.domains.transfer.*` | 🚧 Planned | `create`, `getStatus`, `updateStatus`, `getList` |
473
+ | `namecheap.domains.ns.*` | 🚧 Planned | Glue records — `create`, `delete`, `getInfo`, `update` |
474
+ | `namecheap.domainprivacy.*` | 🚧 Planned | `enable`, `disable`, `renew`, `getList`, `changeemailaddress` |
408
475
 
409
476
  ## 🛠️ Development
410
477
 
411
- See [Development Guide](docs/dev/README.md) for detailed development instructions.
478
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for setup and development guidelines.
412
479
 
413
480
  ## 📝 License
414
481
 
@@ -420,4 +487,6 @@ Contributions are welcome! Please feel free to submit a Pull Request. See the [D
420
487
 
421
488
  ### Contributors
422
489
 
490
+ - [@huntertur](https://github.com/huntertur) — Rich dependency fix
491
+ - [@jeffmcadams](https://github.com/jeffmcadams) — Domain serialization round-trip
423
492
  - [@cosmin](https://github.com/cosmin) — Nameserver management
@@ -1,5 +1,11 @@
1
1
  # Namecheap Python SDK
2
2
 
3
+ [![PyPI version](https://badge.fury.io/py/namecheap-python.svg)](https://pypi.org/project/namecheap-python/)
4
+ [![Downloads](https://pepy.tech/badge/namecheap-python)](https://pepy.tech/project/namecheap-python)
5
+ [![Downloads/month](https://pepy.tech/badge/namecheap-python/month)](https://pepy.tech/project/namecheap-python)
6
+ [![Python](https://img.shields.io/pypi/pyversions/namecheap-python)](https://pypi.org/project/namecheap-python/)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
3
9
  A modern, friendly Python SDK for the Namecheap API with comprehensive CLI and TUI tools.
4
10
 
5
11
  ## 🚀 Features
@@ -164,6 +170,38 @@ Adding CNAME record to tdo.garden...
164
170
  ```
165
171
 
166
172
 
173
+ Check account balance:
174
+
175
+ ```bash
176
+ ❯ namecheap-cli account balance
177
+ Account Balance
178
+ ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
179
+ ┃ Field ┃ Amount ┃
180
+ ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
181
+ │ Available Balance │ 0.00 USD │
182
+ │ Account Balance │ 0.00 USD │
183
+ │ Earned Amount │ 0.00 USD │
184
+ │ Withdrawable │ 0.00 USD │
185
+ │ Auto-Renew Required │ 20.16 USD │
186
+ └─────────────────────┴───────────┘
187
+ ```
188
+
189
+ Get detailed domain info:
190
+
191
+ ```bash
192
+ ❯ namecheap-cli domain info self.fm
193
+
194
+ Domain Information: self.fm
195
+
196
+ Status: Ok
197
+ Owner: adriangalilea
198
+ Created: 07/15/2023
199
+ Expires: 07/15/2026
200
+ Premium: No
201
+ WHOIS Guard: ✓ Enabled
202
+ DNS Provider: CUSTOM
203
+ ```
204
+
167
205
  You can also export DNS records:
168
206
 
169
207
  ```bash
@@ -278,6 +316,33 @@ nc.dns.set_custom_nameservers("example.com", [
278
316
  nc.dns.set_default_nameservers("example.com")
279
317
  ```
280
318
 
319
+ ### Domain Info
320
+
321
+ ```python
322
+ info = nc.domains.get_info("example.com")
323
+ print(info.status) # 'Ok'
324
+ print(info.whoisguard_enabled) # True
325
+ print(info.dns_provider) # 'CUSTOM'
326
+ print(info.created) # '07/15/2023'
327
+ print(info.expires) # '07/15/2026'
328
+ ```
329
+
330
+ ### Account Balance
331
+
332
+ ```python
333
+ bal = nc.users.get_balances()
334
+ print(f"{bal.available_balance} {bal.currency}") # '4932.96 USD'
335
+ print(bal.funds_required_for_auto_renew) # Decimal('20.16')
336
+ ```
337
+
338
+ ### Email Forwarding
339
+
340
+ ```python
341
+ rules = nc.dns.get_email_forwarding("example.com")
342
+ for r in rules:
343
+ print(f"{r.mailbox} -> {r.forward_to}")
344
+ ```
345
+
281
346
  ### Domain Management
282
347
 
283
348
  ```python
@@ -351,22 +416,24 @@ nc.dns.builder().a("www", "192.0.2.1", ttl=1799) # Shows as "Automatic"
351
416
  nc.dns.builder().a("www", "192.0.2.1", ttl=1800) # Shows as "30 min"
352
417
  ```
353
418
 
354
- ## 🚧 Pending Features
355
-
356
- The following Namecheap API features are planned for future releases:
357
-
358
- - **SSL API** - Certificate management
359
- - **Domain Transfer API** - Transfer domains between registrars
360
- - **Domain NS API** - Glue record management (child nameservers)
361
- - **Users API** - Account management and balance checking
362
- - **Whois API** - WHOIS information lookups
363
- - **Email Forwarding** - Email forwarding configuration
364
-
365
- See [pending.md](pending.md) for full details.
419
+ ## 📊 [API Coverage](https://www.namecheap.com/support/api/methods/)
420
+
421
+ | API | Status | Methods |
422
+ |-----|--------|---------|
423
+ | `namecheap.domains.*` | Done | `check`, `list`, `getInfo`, `register`, `renew`, `setContacts`, `lock`/`unlock` |
424
+ | `namecheap.domains.dns.*` | Done | `getHosts`, `setHosts` (builder pattern), `add`, `delete`, `export`, `getList`, `setCustom`, `setDefault`, `getEmailForwarding` |
425
+ | `namecheap.users.*` | ⚠️ Partial | `getBalances`, `getPricing` (needs debugging). Planned: `changePassword`, `update`, `create`, `login`, `resetPassword` |
426
+ | `namecheap.domains.*` | 🚧 Planned | `getContacts`, `getTldList`, `reactivate` |
427
+ | `namecheap.domains.dns.*` | 🚧 Planned | `setEmailForwarding` |
428
+ | `namecheap.users.address.*` | 🚧 Planned | `create`, `delete`, `getInfo`, `getList`, `setDefault`, `update` |
429
+ | `namecheap.ssl.*` | 🚧 Planned | `create`, `activate`, `renew`, `revoke`, `getList`, `getInfo`, `parseCSR`, `reissue`, and more |
430
+ | `namecheap.domains.transfer.*` | 🚧 Planned | `create`, `getStatus`, `updateStatus`, `getList` |
431
+ | `namecheap.domains.ns.*` | 🚧 Planned | Glue records — `create`, `delete`, `getInfo`, `update` |
432
+ | `namecheap.domainprivacy.*` | 🚧 Planned | `enable`, `disable`, `renew`, `getList`, `changeemailaddress` |
366
433
 
367
434
  ## 🛠️ Development
368
435
 
369
- See [Development Guide](docs/dev/README.md) for detailed development instructions.
436
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for setup and development guidelines.
370
437
 
371
438
  ## 📝 License
372
439
 
@@ -378,4 +445,6 @@ Contributions are welcome! Please feel free to submit a Pull Request. See the [D
378
445
 
379
446
  ### Contributors
380
447
 
448
+ - [@huntertur](https://github.com/huntertur) — Rich dependency fix
449
+ - [@jeffmcadams](https://github.com/jeffmcadams) — Domain serialization round-trip
381
450
  - [@cosmin](https://github.com/cosmin) — Nameserver management
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "namecheap-python"
3
- version = "1.1.0"
3
+ version = "1.2.0"
4
4
  description = "A friendly Python SDK for Namecheap API"
5
5
  authors = [{name = "Adrian Galilea Delgado", email = "adriangalilea@gmail.com"}]
6
6
  readme = "README.md"
@@ -12,15 +12,27 @@ from __future__ import annotations
12
12
 
13
13
  from .client import Namecheap
14
14
  from .errors import ConfigurationError, NamecheapError, ValidationError
15
- from .models import Contact, DNSRecord, Domain, DomainCheck, Nameservers
15
+ from .models import (
16
+ AccountBalance,
17
+ Contact,
18
+ DNSRecord,
19
+ Domain,
20
+ DomainCheck,
21
+ DomainInfo,
22
+ EmailForward,
23
+ Nameservers,
24
+ )
16
25
 
17
- __version__ = "1.1.0"
26
+ __version__ = "1.2.0"
18
27
  __all__ = [
28
+ "AccountBalance",
19
29
  "ConfigurationError",
20
30
  "Contact",
21
31
  "DNSRecord",
22
32
  "Domain",
23
33
  "DomainCheck",
34
+ "DomainInfo",
35
+ "EmailForward",
24
36
  "Namecheap",
25
37
  "NamecheapError",
26
38
  "Nameservers",
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Any, Literal
6
6
 
7
7
  import tldextract
8
8
 
9
- from namecheap.models import DNSRecord, Nameservers
9
+ from namecheap.models import DNSRecord, EmailForward, Nameservers
10
10
 
11
11
  from .base import BaseAPI
12
12
 
@@ -494,3 +494,37 @@ class DnsAPI(BaseAPI):
494
494
  nameservers = [ns_data] if isinstance(ns_data, str) else ns_data
495
495
 
496
496
  return Nameservers(is_default=is_default, nameservers=nameservers)
497
+
498
+ def get_email_forwarding(self, domain: str) -> list[EmailForward]:
499
+ """
500
+ Get email forwarding rules for a domain.
501
+
502
+ Args:
503
+ domain: Domain name
504
+
505
+ Returns:
506
+ List of EmailForward rules
507
+
508
+ Examples:
509
+ >>> rules = nc.dns.get_email_forwarding("example.com")
510
+ >>> for r in rules:
511
+ ... print(f"{r.mailbox} -> {r.forward_to}")
512
+ """
513
+ result: Any = self._request(
514
+ "namecheap.domains.dns.getEmailForwarding",
515
+ {"DomainName": domain},
516
+ path="DomainDNSGetEmailForwardingResult",
517
+ )
518
+
519
+ if not result:
520
+ return []
521
+
522
+ forwards = result.get("Forward", [])
523
+ if isinstance(forwards, dict):
524
+ forwards = [forwards]
525
+ assert isinstance(forwards, list), f"Unexpected Forward type: {type(forwards)}"
526
+
527
+ return [
528
+ EmailForward(mailbox=f.get("@mailbox", ""), forward_to=f.get("#text", ""))
529
+ for f in forwards
530
+ ]
@@ -9,7 +9,7 @@ from typing import Any
9
9
  import tldextract
10
10
 
11
11
  from namecheap.logging import logger
12
- from namecheap.models import Contact, Domain, DomainCheck
12
+ from namecheap.models import Contact, Domain, DomainCheck, DomainInfo
13
13
 
14
14
  from .base import BaseAPI
15
15
 
@@ -110,6 +110,52 @@ class DomainsAPI(BaseAPI):
110
110
  return [results]
111
111
  return results if isinstance(results, list) else []
112
112
 
113
+ def get_info(self, domain: str) -> DomainInfo:
114
+ """
115
+ Get detailed information about a domain.
116
+
117
+ Args:
118
+ domain: Domain name
119
+
120
+ Returns:
121
+ DomainInfo with status, whoisguard, DNS provider, etc.
122
+
123
+ Examples:
124
+ >>> info = nc.domains.get_info("example.com")
125
+ >>> print(f"{info.domain} status={info.status} whoisguard={info.whoisguard_enabled}")
126
+ """
127
+ result: Any = self._request(
128
+ "namecheap.domains.getInfo",
129
+ {"DomainName": domain},
130
+ path="DomainGetInfoResult",
131
+ )
132
+
133
+ assert result, f"API returned empty result for {domain} getInfo"
134
+
135
+ # Extract nested fields into flat structure
136
+ domain_details = result.get("DomainDetails", {})
137
+ whoisguard = result.get("Whoisguard", {})
138
+ dns_details = result.get("DnsDetails", {})
139
+
140
+ flat = {
141
+ "@ID": result.get("@ID"),
142
+ "@DomainName": result.get("@DomainName"),
143
+ "@OwnerName": result.get("@OwnerName"),
144
+ "@IsOwner": result.get("@IsOwner"),
145
+ "@IsPremium": result.get("@IsPremium", "false"),
146
+ "@Status": result.get("@Status"),
147
+ "created": domain_details.get("CreatedDate"),
148
+ "expires": domain_details.get("ExpiredDate"),
149
+ "whoisguard_enabled": whoisguard.get("@Enabled", "false").lower() == "true"
150
+ if isinstance(whoisguard, dict)
151
+ else False,
152
+ "dns_provider": dns_details.get("@ProviderType")
153
+ if isinstance(dns_details, dict)
154
+ else None,
155
+ }
156
+
157
+ return DomainInfo.model_validate(flat)
158
+
113
159
  def register(
114
160
  self,
115
161
  domain: str,
@@ -0,0 +1,32 @@
1
+ """Users API."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from namecheap.models import AccountBalance
8
+
9
+ from .base import BaseAPI
10
+
11
+
12
+ class UsersAPI(BaseAPI):
13
+ """User account operations."""
14
+
15
+ def get_balances(self) -> AccountBalance:
16
+ """
17
+ Get account balance information.
18
+
19
+ Returns:
20
+ AccountBalance with available balance, earned amount, etc.
21
+
22
+ Examples:
23
+ >>> bal = nc.users.get_balances()
24
+ >>> print(f"{bal.available_balance} {bal.currency}")
25
+ """
26
+ result: Any = self._request(
27
+ "namecheap.users.getBalances",
28
+ path="UserGetBalancesResult",
29
+ )
30
+
31
+ assert result, "API returned empty result for getBalances"
32
+ return AccountBalance.model_validate(result)
@@ -16,6 +16,7 @@ if TYPE_CHECKING:
16
16
 
17
17
  from ._api.dns import DnsAPI
18
18
  from ._api.domains import DomainsAPI
19
+ from ._api.users import UsersAPI
19
20
 
20
21
 
21
22
  class Namecheap:
@@ -110,6 +111,13 @@ class Namecheap:
110
111
 
111
112
  return DnsAPI(self)
112
113
 
114
+ @cached_property
115
+ def users(self) -> UsersAPI:
116
+ """User account operations."""
117
+ from ._api.users import UsersAPI
118
+
119
+ return UsersAPI(self)
120
+
113
121
  def __enter__(self) -> Self:
114
122
  """Enter context manager."""
115
123
  return self
@@ -251,6 +251,66 @@ class Domain(XMLModel):
251
251
  raise ValueError(f"Cannot parse datetime from {v}")
252
252
 
253
253
 
254
+ class AccountBalance(BaseModel):
255
+ """Account balance information."""
256
+
257
+ currency: str = Field(alias="@Currency")
258
+ available_balance: Decimal = Field(alias="@AvailableBalance")
259
+ account_balance: Decimal = Field(alias="@AccountBalance")
260
+ earned_amount: Decimal = Field(alias="@EarnedAmount")
261
+ withdrawable_amount: Decimal = Field(alias="@WithdrawableAmount")
262
+ funds_required_for_auto_renew: Decimal = Field(alias="@FundsRequiredForAutoRenew")
263
+
264
+ model_config = ConfigDict(populate_by_name=True)
265
+
266
+ @field_validator(
267
+ "available_balance",
268
+ "account_balance",
269
+ "earned_amount",
270
+ "withdrawable_amount",
271
+ "funds_required_for_auto_renew",
272
+ mode="before",
273
+ )
274
+ @classmethod
275
+ def parse_decimal(cls, v: Any) -> Decimal:
276
+ return Decimal(str(v)) if v is not None else Decimal("0")
277
+
278
+
279
+ class DomainInfo(BaseModel):
280
+ """Detailed domain information from getInfo."""
281
+
282
+ id: int = Field(alias="@ID")
283
+ domain: str = Field(alias="@DomainName")
284
+ owner: str = Field(alias="@OwnerName")
285
+ is_owner: bool = Field(alias="@IsOwner")
286
+ is_premium: bool = Field(alias="@IsPremium", default=False)
287
+ status: str = Field(alias="@Status")
288
+ created: str | None = Field(default=None)
289
+ expires: str | None = Field(default=None)
290
+ whoisguard_enabled: bool = Field(default=False)
291
+ dns_provider: str | None = Field(default=None)
292
+
293
+ model_config = ConfigDict(populate_by_name=True)
294
+
295
+ @field_validator("is_owner", "is_premium", mode="before")
296
+ @classmethod
297
+ def parse_bool(cls, v: Any) -> bool:
298
+ if isinstance(v, bool):
299
+ return v
300
+ if isinstance(v, str):
301
+ return v.lower() == "true"
302
+ return False
303
+
304
+
305
+ class EmailForward(BaseModel):
306
+ """Email forwarding rule."""
307
+
308
+ mailbox: str = Field(alias="@mailbox")
309
+ forward_to: str
310
+
311
+ model_config = ConfigDict(populate_by_name=True)
312
+
313
+
254
314
  class Nameservers(BaseModel):
255
315
  """Current nameserver configuration for a domain."""
256
316
 
@@ -367,57 +367,31 @@ def domain_info(config: Config, domain: str) -> None:
367
367
  nc = config.init_client()
368
368
 
369
369
  try:
370
- domains = nc.domains.list()
371
- domain_obj = next((d for d in domains if d.name == domain), None)
372
-
373
- if not domain_obj:
374
- console.print(f"[red]❌ Domain {domain} not found in your account[/red]")
375
- sys.exit(1)
370
+ with Progress(
371
+ SpinnerColumn(),
372
+ TextColumn("[progress.description]{task.description}"),
373
+ transient=True,
374
+ ) as progress:
375
+ progress.add_task(f"Getting info for {domain}...", total=None)
376
+ info = nc.domains.get_info(domain)
376
377
 
377
378
  if config.output_format == "table":
378
379
  console.print(f"\n[bold cyan]Domain Information: {domain}[/bold cyan]\n")
379
- console.print(
380
- f"[bold]Status:[/bold] "
381
- f"{'Active' if not domain_obj.is_expired else '[red]Expired[/red]'}"
382
- )
383
- console.print(
384
- f"[bold]Created:[/bold] {domain_obj.created.strftime('%Y-%m-%d')}"
385
- )
386
- console.print(
387
- f"[bold]Expires:[/bold] {domain_obj.expires.strftime('%Y-%m-%d')}"
388
- )
389
- console.print(
390
- f"[bold]Auto-Renew:[/bold] {'✓ Enabled' if domain_obj.auto_renew else '✗ Disabled'}"
391
- )
392
- console.print(
393
- f"[bold]Locked:[/bold] {'🔒 Yes' if domain_obj.is_locked else '🔓 No'}"
394
- )
380
+ console.print(f"[bold]Status:[/bold] {info.status}")
381
+ console.print(f"[bold]Owner:[/bold] {info.owner}")
382
+ if info.created:
383
+ console.print(f"[bold]Created:[/bold] {info.created}")
384
+ if info.expires:
385
+ console.print(f"[bold]Expires:[/bold] {info.expires}")
386
+ console.print(f"[bold]Premium:[/bold] {'Yes' if info.is_premium else 'No'}")
395
387
  console.print(
396
388
  f"[bold]WHOIS Guard:[/bold] "
397
- f"{'✓ Enabled' if domain_obj.whois_guard else '✗ Disabled'}"
389
+ f"{'✓ Enabled' if info.whoisguard_enabled else '✗ Disabled'}"
398
390
  )
399
-
400
- # Calculate days until expiration
401
- days_left = (domain_obj.expires - datetime.now()).days
402
- if days_left < 30:
403
- console.print(
404
- f"\n⚠️ [yellow]Domain expires in {days_left} days![/yellow]"
405
- )
406
- elif days_left < 60:
407
- console.print(f"\n📅 Domain expires in {days_left} days")
408
-
391
+ if info.dns_provider:
392
+ console.print(f"[bold]DNS Provider:[/bold] {info.dns_provider}")
409
393
  else:
410
- data = {
411
- "domain": domain_obj.name,
412
- "status": "active" if not domain_obj.is_expired else "expired",
413
- "created": domain_obj.created.isoformat(),
414
- "expires": domain_obj.expires.isoformat(),
415
- "auto_renew": domain_obj.auto_renew,
416
- "locked": domain_obj.is_locked,
417
- "whois_guard": domain_obj.whois_guard,
418
- "days_until_expiration": (domain_obj.expires - datetime.now()).days,
419
- }
420
- output_formatter(data, config.output_format)
394
+ output_formatter(info.model_dump(), config.output_format)
421
395
 
422
396
  except NamecheapError as e:
423
397
  console.print(f"[red]❌ Error: {e}[/red]")
@@ -906,6 +880,45 @@ def dns_export(config: Config, domain: str, format: str, output) -> None:
906
880
  sys.exit(1)
907
881
 
908
882
 
883
+ @dns_group.command("email-forwarding")
884
+ @click.argument("domain")
885
+ @pass_config
886
+ def dns_email_forwarding(config: Config, domain: str) -> None:
887
+ """Show email forwarding rules for a domain."""
888
+ nc = config.init_client()
889
+
890
+ try:
891
+ with Progress(
892
+ SpinnerColumn(),
893
+ TextColumn("[progress.description]{task.description}"),
894
+ transient=True,
895
+ ) as progress:
896
+ progress.add_task(f"Getting email forwarding for {domain}...", total=None)
897
+ rules = nc.dns.get_email_forwarding(domain)
898
+
899
+ if config.output_format == "table":
900
+ if not rules:
901
+ console.print(
902
+ f"\n[yellow]No email forwarding rules for {domain}[/yellow]"
903
+ )
904
+ return
905
+
906
+ table = Table(title=f"Email Forwarding for {domain}")
907
+ table.add_column("Mailbox", style="cyan")
908
+ table.add_column("Forwards To", style="green")
909
+
910
+ for rule in rules:
911
+ table.add_row(f"{rule.mailbox}@{domain}", rule.forward_to)
912
+
913
+ console.print(table)
914
+ else:
915
+ output_formatter([r.model_dump() for r in rules], config.output_format)
916
+
917
+ except NamecheapError as e:
918
+ console.print(f"[red]❌ Error: {e}[/red]")
919
+ sys.exit(1)
920
+
921
+
909
922
  @cli.group("account")
910
923
  def account_group() -> None:
911
924
  """Account management commands."""
@@ -916,14 +929,37 @@ def account_group() -> None:
916
929
  @pass_config
917
930
  def account_balance(config: Config) -> None:
918
931
  """Check account balance."""
919
- config.init_client()
932
+ nc = config.init_client()
920
933
 
921
934
  try:
922
- # This would need to be implemented in the SDK
923
- console.print(
924
- "[yellow]Account balance check not yet implemented in SDK[/yellow]"
925
- )
926
- console.print("This feature requires the users.getBalances API method")
935
+ with Progress(
936
+ SpinnerColumn(),
937
+ TextColumn("[progress.description]{task.description}"),
938
+ transient=True,
939
+ ) as progress:
940
+ progress.add_task("Getting account balance...", total=None)
941
+ bal = nc.users.get_balances()
942
+
943
+ if config.output_format == "table":
944
+ table = Table(title="Account Balance")
945
+ table.add_column("Field", style="cyan")
946
+ table.add_column("Amount", style="green", justify="right")
947
+
948
+ table.add_row(
949
+ "Available Balance", f"{bal.available_balance} {bal.currency}"
950
+ )
951
+ table.add_row("Account Balance", f"{bal.account_balance} {bal.currency}")
952
+ table.add_row("Earned Amount", f"{bal.earned_amount} {bal.currency}")
953
+ table.add_row("Withdrawable", f"{bal.withdrawable_amount} {bal.currency}")
954
+ if bal.funds_required_for_auto_renew > 0:
955
+ table.add_row(
956
+ "Auto-Renew Required",
957
+ f"{bal.funds_required_for_auto_renew} {bal.currency}",
958
+ )
959
+
960
+ console.print(table)
961
+ else:
962
+ output_formatter(bal.model_dump(mode="json"), config.output_format)
927
963
 
928
964
  except NamecheapError as e:
929
965
  console.print(f"[red]❌ Error: {e}[/red]")
@@ -200,7 +200,7 @@ wheels = [
200
200
 
201
201
  [[package]]
202
202
  name = "namecheap-python"
203
- version = "1.1.0"
203
+ version = "1.2.0"
204
204
  source = { editable = "." }
205
205
  dependencies = [
206
206
  { name = "httpx" },
@@ -1,220 +0,0 @@
1
- # Development Guide
2
-
3
- ## 🛠️ Development Setup
4
-
5
- ### Prerequisites
6
-
7
- - Python 3.12+
8
- - [uv](https://docs.astral.sh/uv/) package manager
9
- - Git
10
-
11
- ### Setup Development Environment
12
-
13
- ```bash
14
- # Clone repository
15
- git clone https://github.com/adriangalilea/namecheap-python.git
16
- cd namecheap-python
17
-
18
- # Install with uv (includes all extras and dev dependencies)
19
- uv sync --all-extras
20
-
21
- # Install pre-commit hooks
22
- pre-commit install
23
- ```
24
-
25
- ## 🧪 Running Tests
26
-
27
- ```bash
28
- # Run all tests
29
- uv run pytest
30
-
31
- # Run with coverage
32
- uv run pytest --cov=namecheap --cov-report=term-missing
33
-
34
- # Run specific test file
35
- uv run pytest tests/test_domains.py
36
-
37
- # Run with verbose output
38
- uv run pytest -vv
39
- ```
40
-
41
- ## 🔍 Code Quality
42
-
43
- ### Linting and Formatting
44
-
45
- ```bash
46
- # Check code with ruff
47
- uv run ruff check
48
-
49
- # Fix auto-fixable issues
50
- uv run ruff check --fix
51
-
52
- # Format code
53
- uv run ruff format
54
-
55
- # Check formatting without changing files
56
- uv run ruff format --check
57
- ```
58
-
59
- ### Type Checking
60
-
61
- ```bash
62
- # Type check the main package
63
- uv run mypy src/namecheap
64
-
65
- # Type check everything (slower)
66
- uv run mypy src/
67
- ```
68
-
69
- ### Pre-commit Hooks
70
-
71
- The project uses pre-commit hooks to ensure code quality:
72
-
73
- ```bash
74
- # Run all pre-commit hooks manually
75
- pre-commit run --all-files
76
-
77
- # Update pre-commit hooks
78
- pre-commit autoupdate
79
- ```
80
-
81
- ## 📦 Building and Publishing
82
-
83
- ### Building Locally
84
-
85
- ```bash
86
- # Build distribution packages
87
- uv build
88
-
89
- # This creates:
90
- # - dist/namecheap-1.0.0-py3-none-any.whl
91
- # - dist/namecheap-1.0.0.tar.gz
92
- ```
93
-
94
- ### Release Process
95
-
96
- Releases are automated via GitHub Actions:
97
-
98
- 1. **Manual Release** (via GitHub UI):
99
- - Go to Actions → "Bump Version and Release"
100
- - Click "Run workflow"
101
- - Select version bump type (major/minor/patch)
102
- - This will:
103
- - Bump version in pyproject.toml
104
- - Create git tag
105
- - Build and publish to PyPI
106
- - Create GitHub release
107
-
108
- 2. **Tag-based Release**:
109
- ```bash
110
- # Create and push a tag
111
- git tag v1.0.0
112
- git push origin v1.0.0
113
- ```
114
- This triggers the publish workflow automatically.
115
-
116
- ## 🏗️ Project Structure
117
-
118
- ```
119
- namecheap-python/
120
- ├── src/
121
- │ ├── namecheap/ # Core SDK package
122
- │ │ ├── __init__.py
123
- │ │ ├── client.py # Main client class
124
- │ │ ├── models.py # Pydantic models
125
- │ │ ├── errors.py # Custom exceptions
126
- │ │ └── _api/ # API implementations
127
- │ │ ├── base.py
128
- │ │ ├── domains.py
129
- │ │ └── dns.py
130
- │ ├── namecheap_cli/ # CLI tool
131
- │ │ ├── __init__.py
132
- │ │ ├── __main__.py # CLI entry point
133
- │ │ └── completion.py # Shell completions
134
- │ └── namecheap_dns_tui/ # TUI application
135
- │ ├── __init__.py
136
- │ └── __main__.py # TUI entry point
137
- ├── tests/ # Test suite
138
- ├── examples/ # Usage examples
139
- └── docs/ # Documentation
140
- ```
141
-
142
- ## 🧩 Adding New Features
143
-
144
- ### Adding a New API Endpoint
145
-
146
- 1. Create model in `src/namecheap/models.py`:
147
- ```python
148
- class NewFeature(BaseModel):
149
- field: str
150
- another_field: int
151
- ```
152
-
153
- 2. Add API method in appropriate file under `src/namecheap/_api/`:
154
- ```python
155
- def new_feature(self, param: str) -> NewFeature:
156
- """Implement new feature."""
157
- response = self._request("namecheap.newfeature.action", {"Param": param})
158
- return NewFeature(**response)
159
- ```
160
-
161
- 3. Add tests in `tests/test_newfeature.py`
162
-
163
- 4. Update documentation
164
-
165
- ### Adding CLI Commands
166
-
167
- 1. Add command group or command in `src/namecheap_cli/__main__.py`:
168
- ```python
169
- @cli.group("newfeature")
170
- def newfeature_group():
171
- """New feature commands."""
172
- pass
173
-
174
- @newfeature_group.command("action")
175
- @click.argument("param")
176
- @pass_config
177
- def newfeature_action(config: Config, param: str):
178
- """Perform new feature action."""
179
- nc = config.init_client()
180
- result = nc.newfeature.action(param)
181
- # Handle output
182
- ```
183
-
184
- 2. Add tests and update CLI documentation
185
-
186
- ## 🐛 Debugging
187
-
188
- ### Enable Debug Logging
189
-
190
- ```python
191
- import logging
192
- logging.basicConfig(level=logging.DEBUG)
193
-
194
- # Or set environment variable
195
- export NAMECHEAP_DEBUG=true
196
- ```
197
-
198
- ### Common Issues
199
-
200
- 1. **Import errors**: Make sure you're using `uv run` or have activated the virtual environment
201
- 2. **API errors**: Check credentials and sandbox mode settings
202
- 3. **Type errors**: Run `mypy` to catch type issues early
203
-
204
- ## 📋 Checklist for PRs
205
-
206
- - [ ] Code follows project style (run `uv run ruff check`)
207
- - [ ] All tests pass (`uv run pytest`)
208
- - [ ] Type hints added (`uv run mypy src/namecheap`)
209
- - [ ] Documentation updated if needed
210
- - [ ] Examples work correctly
211
- - [ ] Commit messages are clear and descriptive
212
-
213
- ## 🔗 Useful Links
214
-
215
- - [Namecheap API Documentation](https://www.namecheap.com/support/api/methods/)
216
- - [Python Type Hints](https://docs.python.org/3/library/typing.html)
217
- - [Pydantic Documentation](https://docs.pydantic.dev/)
218
- - [Click Documentation](https://click.palletsprojects.com/)
219
- - [Textual Documentation](https://textual.textualize.io/)
220
- - [Ruff Documentation](https://docs.astral.sh/ruff/)
@@ -1,94 +0,0 @@
1
- # Pending Features from Previous SDK
2
-
3
- Based on the previous Namecheap Python SDK implementation, here's what's still pending in our new clean architecture:
4
-
5
- ## 🚧 Not Yet Implemented
6
-
7
- ### 1. **SSL API** (`namecheap.ssl.*`)
8
- - `create()` - Purchase SSL certificates
9
- - `activate()` - Activate SSL certificates
10
- - `getInfo()` - Get SSL certificate details
11
- - `parseCSR()` - Parse Certificate Signing Request
12
- - `getApproverEmailList()` - Get domain control validation emails
13
- - `resendApproverEmail()` - Resend DCV email
14
- - `reissue()` - Reissue SSL certificate
15
- - `renew()` - Renew SSL certificate
16
- - `revoke()` - Revoke SSL certificate
17
- - `getList()` - List SSL certificates
18
-
19
- ### 2. **Users API** (`namecheap.users.*`)
20
- - `getBalances()` - Get account balance
21
- - `changePassword()` - Change account password
22
- - `update()` - Update user information
23
- - `createAddFundsRequest()` - Create add funds request
24
- - `getAddFundsStatus()` - Check add funds status
25
- - `create()` - Create sub-account (resellers)
26
- - `login()` - Login to get session
27
- - `resetPassword()` - Reset password
28
-
29
- ### 3. **Domains Transfer API** (`namecheap.domains.transfer.*`)
30
- - `create()` - Initiate domain transfer
31
- - `getStatus()` - Check transfer status
32
- - `updateStatus()` - Approve/reject transfer
33
- - `getList()` - List pending transfers
34
-
35
- ### 4. **Domains NS API** (`namecheap.domains.ns.*`) — Glue Records
36
- - `create()` - Register a child nameserver (e.g., ns1.yourdomain.com → 1.2.3.4)
37
- - `delete()` - Delete a child nameserver
38
- - `getInfo()` - Get child nameserver details
39
- - `update()` - Update child nameserver IP
40
-
41
- ### 5. **Whois API** (`namecheap.whois.*`)
42
- - `getWhoisInfo()` - Get WHOIS information
43
-
44
- ### 6. **Domains Forwarding API**
45
- - `setEmailForwarding()` - Configure email forwarding
46
- - `getEmailForwarding()` - Get email forwarding settings
47
-
48
- ## ✅ Already Implemented (Core Features)
49
-
50
- ### Domains API
51
- - ✅ `check()` - Check domain availability
52
- - ✅ `list()` - List domains in account
53
- - ✅ `register()` - Register new domain
54
- - ✅ `renew()` - Renew domain
55
- - ✅ `setContacts()` - Update contact information
56
- - ✅ `lock()`/`unlock()` - Domain locking
57
-
58
- ### DNS API
59
- - ✅ `get()` - Get DNS records
60
- - ✅ `set()` - Set DNS records (with builder pattern!)
61
- - ✅ `add()` - Add single record
62
- - ✅ `delete()` - Delete records
63
- - ✅ `set_custom_nameservers()` - Switch to custom nameservers (e.g., Route 53)
64
- - ✅ `set_default_nameservers()` - Reset to Namecheap BasicDNS
65
- - ✅ `get_nameservers()` - Get current nameserver configuration
66
-
67
- ### Enhanced Features
68
- - ✅ Smart IP detection and validation
69
- - ✅ Helpful error messages with IP troubleshooting
70
- - ✅ Pydantic models with proper type safety
71
- - ✅ Rich logging with colors
72
- - ✅ Context manager support
73
- - ✅ DNS builder pattern
74
-
75
- ## 🔧 Pricing Implementation Status
76
-
77
- ### Current Issues
78
- - The `getPricing` API call is implemented but needs debugging
79
- - Price fields are properly modeled but not being populated correctly
80
- - Need to verify the API path and response structure for pricing
81
-
82
- ### Enhanced Domain Check (from old SDK)
83
- The old SDK had an enhanced domain check that fetched pricing automatically. We've implemented this with the `include_pricing=True` parameter, but it needs fixing.
84
-
85
- ## 📝 Notes
86
-
87
- The core domain and DNS functionality is complete and working well. The additional APIs (SSL, transfers, user management) are less commonly used but would make the SDK feature-complete with the Namecheap API.
88
-
89
- Priority for implementation:
90
- 1. Fix pricing retrieval (high - already partially implemented)
91
- 2. SSL API (medium - common use case)
92
- 3. Transfer API (medium - needed for domain transfers)
93
- 4. Users API pricing methods (medium - already have getPricing)
94
- 5. Other APIs (low - rarely used)