namecheap-client
An unofficial, async Rust client for the Namecheap API.
namecheap-client is a small, type-safe wrapper over the Namecheap API. It takes
care of the HTTPS requests and the XML parsing, so you can check, register, and
configure domains using ordinary Rust types and async/await instead of
hand-rolling query strings and walking an XML document.
Disclaimer: This is an independent, community project. It is not affiliated with, endorsed by, or sponsored by Namecheap, and it does not use Namecheap's trademarks or branding. It is maintained on a best-effort basis. "Namecheap" is a trademark of its respective owner.
Scope
Version 0.1 focuses on the core commands needed to stand a domain up end to end, including pointing its email at a provider:
| Method | Namecheap command | Purpose |
|---|---|---|
client.domains().check(...) |
namecheap.domains.check |
Check domain availability |
client.domains().create(...) |
namecheap.domains.create |
Register a domain |
client.domains().list() |
namecheap.domains.getList |
List domains (with auto-renew status) |
client.domains().set_auto_renew(...) |
namecheap.domains.setAutoRenew |
Enable or disable auto-renewal |
client.domains().dns().get_hosts(...) |
namecheap.domains.dns.getHosts |
Read DNS host records |
client.domains().dns().set_hosts(...) |
namecheap.domains.dns.setHosts |
Replace DNS host records |
client.users().get_balances() |
namecheap.users.getBalances |
Read account balances |
client.users().get_pricing(...) |
namecheap.users.getPricing |
Look up standard TLD prices |
Not yet covered: full endpoint coverage, a blocking (synchronous) API, and reseller commands. The surface area is intentionally small. If a command you need is missing, please open an issue.
Installation
Add the crate and an async runtime to your Cargo.toml:
[]
= "0.1"
= { = "1", = ["full"] }
This crate has not been published to crates.io yet. Until the first release is out, depend on it directly from Git:
[]
= { = "https://github.com/Jackson-Desync/namecheap-client" }
Getting API access
Before any call will succeed you need three things from Namecheap:
- API access enabled on your account (Profile, then Tools, then the Namecheap API Access section).
- Your public IPv4 address whitelisted in that same section.
- That exact IP used as
client_ip. Namecheap requires the request to come from a whitelisted address, and the address you send asClientIphas to match the address the request actually originates from.
While developing, point the client at the sandbox (Environment::Sandbox). The
sandbox uses separate credentials and a separate account that you create at
sandbox.namecheap.com. Calls such as domain
registration place real, billable orders in production.
Quick start
use ;
async
UserName defaults to api_user. Set it explicitly with .user_name(...) only
when you act on behalf of a different account.
Setting up email DNS (MX, SPF, DKIM, DMARC)
set_hosts is the command for wiring a domain up to an email provider. Supply
the MX records and set the email type to EmailType::Mx, then add the TXT
records for SPF, DKIM, and DMARC.
Important:
setHostsreplaces the full set of host records. Any record you do not include is removed. Always send the complete set you want the domain to end up with, including your website records.
use ;
// `client` is a built Client (see Quick start above).
let records = vec!;
let request = from_domain
.expect
.with_email_type;
let result = client.domains.dns.set_hosts.await?;
println!;
from_domain splits a registrable domain at the first dot, which is correct for
both example.com and example.co.uk. If you already have the parts, construct
the request with SetHostsRequest::new(sld, tld, records).
Reading and updating records
Because setHosts replaces everything, the safe way to change a single record is
read-modify-write: read the current records with get_hosts, change what you
need, and send the full set back. GetHostsResult::to_host_records converts the
records straight into the writable form set_hosts expects.
use ;
// `client` is a built Client (see Quick start above).
let = ;
// Read.
let current = client.domains.dns.get_hosts.await?;
for record in ¤t.records
// Modify: keep everything, add one record.
let mut records = current.to_host_records;
records.push;
// Write the complete set back.
let request = new;
client.domains.dns.set_hosts.await?;
GetHostsResult::is_using_our_dns tells you whether the domain points at
Namecheap's DNS; set_hosts only takes effect when it does.
Registering a domain
Heads up: In production,
createplaces a real order and charges your account. Test against the sandbox first.
use ;
// `client` is a built Client (see Quick start above).
let contact = new;
// One contact is reused for the registrant, tech, admin, and billing roles.
let request = new;
let result = client.domains.create.await?;
println!;
WhoisGuard privacy is requested by default; disable it with
.with_whois_privacy(false). Set custom nameservers with .with_nameservers([...]).
Listing domains and auto-renewal
List the domains on the account (with each one's auto-renew flag and expiry), and turn auto-renewal on or off:
// `client` is a built Client (see Quick start above).
let list = client.domains.list.await?;
for domain in &list.domains
// Stop a domain from renewing automatically (it then lapses at expiry).
client.domains.set_auto_renew.await?;
Domains registered through the API default to auto-renew off, so a domain will not renew on its own unless you enable it.
Checking prices
Standard (non-premium) TLD pricing is a free, read-only lookup. The response is
nested, so prices() flattens it to one entry per available duration:
use PricingRequest;
// `client` is a built Client (see Quick start above).
let result = client.users
.get_pricing
.await?;
for price in result.prices
For a premium domain, the per-name price instead comes from check(), via
DomainCheckResult::premium_registration_price.
Error handling
Failures are split into distinct categories so you can react to them precisely.
Errors that Namecheap reports inside the XML body are surfaced as Error::Api,
separate from transport-level HTTP failures.
use Error;
// `client` is a built Client (see Quick start above).
match client.domains.check.await
TLS backends
By default the crate uses rustls, so it
builds without a system OpenSSL installation. To use the platform-native TLS
stack instead, disable default features and enable native-tls:
[]
= { = "0.1", = false, = ["native-tls"] }
Running the examples
The repository includes runnable examples that read credentials from the environment:
NAMECHEAP_API_USER=your-user \
NAMECHEAP_API_KEY=your-key \
NAMECHEAP_CLIENT_IP=your.whitelisted.ip \
# and the email DNS walkthrough:
Design notes
- Async-first, built on reqwest and tokio.
- Strongly-typed request and response structs for every supported command.
- XML decoding with serde and quick-xml.
#![forbid(unsafe_code)]and nobuild.rsin this crate, to keep it easy to audit.- A deliberately small dependency set.
Versioning
This project follows Semantic Versioning. While the major
version is 0, minor releases may contain breaking changes. A recent stable
Rust toolchain is recommended.
Contributing
Issues and pull requests are welcome. For larger changes, please open an issue first to discuss the direction. By contributing you agree that your work is licensed under the same terms as the project.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.