Domain

Domains: buy one in your user's name, connect one they own, or transfer one in.

[offer] = noclick.Domain.search("anasilva", tlds=["dev"], limit=1)
ana = noclick.DomainContact(name="Ana Silva", email="ana@example.com", phone="+14155550123",
                            address="500 Market St", city="San Francisco", region="CA", postal_code="94105",
                            country="US", agreement_accepted_at=accepted_at)   # when she accepted the agreement
with noclick.as_user("user_42"):
    bought = noclick.Domain.buy(offer, max_price_usd=20, registrant=ana).wait()   # Ana's, charged to you

owned = noclick.Domain.connect("acme.test")              # one they already own
for record in owned.records:
    print(record.type, record.name, record.value)       # add these where its DNS is hosted
inbox = noclick.Inbox.create(local_part="help", domain="mail.acme.test")   # its own mail stays put

A bought domain is registered to the person (you, or the user it's bought for) and charged to your account in dollars, like everything else: NoClick never bills your users. It's never deleted: turn off auto-renew to let it lapse, or transfer_out() to move it to another registrar. One registered elsewhere moves here with Domain.transfer_in.

class Domain

A domain you bought through NoClick, transferred in, or connected from elsewhere, and what it serves.

Attributes
idstr
namestr

The domain, like acmebooking.com.

sourcestr

bought (through NoClick), transferred (moved here from another registrar, then registered through NoClick like a bought one) or connected (owned elsewhere).

noclick_dnsbool

Whether NoClick hosts its DNS: a bought domain, or a transferred one after use_noclick_dns(). When False, records are added where its DNS is hosted and dns raises noclick.NotAvailable.

wildcardbool

Whether its *.<name> records are set too, so every subdomain can serve.

statusstr

awaiting_human (its purchase held for your policy's approver), registering, transferring_in (moving here from another registrar), pending_dns, active, registrant_unverified, expiring, expired, transferring_out or failed.

expires_atAny

When the registration runs out (None for a connected domain).

auto_renewbool | None

Whether it renews itself 30 days before expires_at (None for a connected domain).

renewable_untilAny

The end of the guaranteed renewal window after expires_at: the last moment renew() works (None for a connected domain).

renewal_usdfloat | None

What renewing for renewal_years costs, in US dollars.

renewal_yearsint | None

The term renewal_usd buys, in years: the TLD's minimum (None for a connected domain).

registrantDomainContact | None

The person it's registered to (None for a connected domain); update(registrant=...) changes it.

recordslist[DnsRecord]

The records it needs for what it serves: on a connected domain, the ones to add where its DNS is hosted, each with its status; on a bought one, the ones NoClick keeps for you.

setup_urlstr | None

A connected domain's one-click setup, where its DNS host supports the open Domain Connect standard: the person signs in there and approves the records on the host's consent page, which names NoClick alongside your brand (None otherwise).

serveslist[dict[str, Any]]

What it points at, one entry per name of it: {kind, id, name, hostname} for each app (project) and inbox, and brand when it serves your brand's pages (Brand.set(domain=)); hostname is the name serving it.

registrant_emailstr | None

Where the link to confirm the registrant's address went, sent in your brand on ICANN's behalf (a bought domain).

registrant_verify_byAny

While registrant_unverified: the day (15 days on) the domain stops resolving unless the registrant has confirmed their address.

transfer_locked_untilAny

Until then transfer_out() is refused: the registry's transfer lock after a domain is registered, transferred in or its registrant changes.

user_idstr | None
created_atAny
dnsDomainDns

The records of a bought domain: records(), set(...), delete(record).

searchstaticasync

noclick.Domain.search(
    query, *, tlds=None, limit=None, user=..., client=None
) -> list[DomainOffer]

Names for sale built from query (a word, or a whole name like acmebooking.com), in tlds or a common set, with close alternatives.

Parameters
querystrrequired
tldsSequence[str] | Nonedefault None
limitint | None

Return at most this many.

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
list[DomainOffer]

Up to limit offers (10 by default, at most 50), exact matches first, each with its price and renewal price for the TLD's shortest term (min_years), the longest it allows (max_years), whether it's available, and any trademark claims_notice. Names that imitate well-known brands or banks aren't offered.

Usage

See what's free and what it costs:

for offer in noclick.Domain.search("acmebooking", tlds=["com", "ai"]):
    print(offer.name, offer.available, offer.price_usd, offer.min_years, offer.renewal_usd, offer.premium)

Or check one name:

[offer] = noclick.Domain.search("acmebooking.com", limit=1)
print(offer.available)

buyclassmethodasync

noclick.Domain.buy(
    offer, *, max_price_usd, years=None, registrant=None, auto_renew=True,
    accept_claims=False, user=..., client=None
) -> DomainPurchase

Register offer (a DomainOffer or a name) in the person's name: yours, or inside as_user the user's. years is the term, between the offer's min_years and max_years; left out, it's the TLD's minimum (two years for .ai), and a term the TLD doesn't offer raises noclick.InvalidRequest naming years, with the terms it does. It's charged to your account, never to the user, and refused (noclick.PriceExceeded) if it costs more than max_price_usd.

registrant is the person it's registered to, with the agreement_accepted_at that says when they accepted Domain.agreement(). A user's domain is registered to that user, so inside as_user it's required: without it, noclick.InvalidRequest names registrant and nothing is sent. A domain your account buys for itself, outside as_user, uses the account's default registrant when you pass none (Domain.set_default_registrant); with none set, it raises noclick.ActionRequired whose next_step links to the console page where it's set, and nothing is bought.

accept_claims=True says the registrant has been shown the offer's claims_notice and still wants the name. A name with a notice is refused without it (noclick.ActionRequired whose details carry claims_notice), and nothing is bought.

NoClick checks your account can pay before registering (noclick.PaymentRequired otherwise) and charges it when the registry confirms the registration; a registration that fails is never charged. When your policy holds purchases for a person to approve, it waits in awaiting_human until the approver answers; nobody answering within 24 hours (the approval's life) expires it, and nothing is charged. The price is checked against max_price_usd again when it runs.

Parameters
offerstr | DomainOfferrequired
max_price_usdfloatrequired
yearsint | Nonedefault None
registrantDomainContact | Nonedefault None
auto_renewbooldefault True
accept_claimsbooldefault False
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
DomainPurchase

The purchase: an operation whose .wait() gives the Domain once it's registered and its DNS is set up.

Usage

Buy a name with a ceiling on the price, registered to the person you name:

[offer] = noclick.Domain.search("acmebooking", tlds=["com"], limit=1)
owner = noclick.DomainContact(
    name="Dana Reyes", email="dana@acmebooking.test", phone="+14155550188",
    address="1 Ferry Building", city="San Francisco", region="CA", postal_code="94111", country="US",
    agreement_accepted_at=accepted_at,   # when Dana accepted noclick.Domain.agreement()
)
domain = noclick.Domain.buy(offer, max_price_usd=15, registrant=owner).wait()
print(domain.name, domain.expires_at)

Buy one for a user: registered to them, charged to you:

ana = noclick.DomainContact(
    name="Ana Silva", email="ana@example.com", phone="+14155550123",
    address="500 Market St", city="San Francisco", region="CA", postal_code="94105", country="US",
    agreement_accepted_at=accepted_at,
)
with noclick.as_user("user_42"):
    domain = noclick.Domain.buy("anasilva.dev", max_price_usd=20, registrant=ana).wait()

A name with a trademark claim, once the registrant has read its notice and still wants it:

[offer] = noclick.Domain.search("acmebooking.ai", limit=1)
print(offer.claims_notice)   # show this to the registrant first
domain = noclick.Domain.buy(offer, max_price_usd=200, registrant=owner, accept_claims=True).wait()

agreementclassmethodasync

noclick.Domain.agreement(*, client=None) -> DomainAgreement

NoClick's domain registration agreement, which every registrant accepts. Its page names the sponsoring registrar, as ICANN requires, and carries the fee schedule (registration, renewal, renewal after expiry, restore) and ICANN's registrant rights and responsibilities. Show it to the person, and record when they accept it as agreement_accepted_at on their DomainContact: a registration needs it.

Parameters
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
DomainAgreement

The agreement's url and version.

Usage
agreement = noclick.Domain.agreement()
print(f"Before we register your domain, read and accept {agreement.url}")

default_registrantclassmethodasync

noclick.Domain.default_registrant(*, client=None) -> DomainContact | None

The registrant your account's own domains are registered to when a purchase names none.

Parameters
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
DomainContact | None

The contact, or None until you set one.

Usage
contact = noclick.Domain.default_registrant()
print(contact.email if contact else "No default registrant yet")

set_default_registrantclassmethodasync

noclick.Domain.set_default_registrant(contact, *, client=None) -> DomainContact | None

Set (or with None clear) the registrant your account's own domains use when a purchase names none: set it once, and Domain.buy or Domain.from_name(..., create_if_missing=True) outside as_user needs no contact in code. Until one is set, such a purchase raises noclick.ActionRequired whose next_step links to the console page that sets it. A user's domain is still registered to that user: pass their details as registrant. Like any registrant, it needs agreement_accepted_at: when the person accepted Domain.agreement() for your account.

Parameters
contactDomainContact | Nonerequired
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
DomainContact | None

The contact now on file (None once cleared).

Usage
noclick.Domain.set_default_registrant(noclick.DomainContact(
    name="Dana Reyes", email="dana@acmebooking.test", phone="+14155550188", organization="Acme Booking",
    address="1 Ferry Building", city="San Francisco", region="CA", postal_code="94111", country="US",
    agreement_accepted_at=accepted_at,   # when Dana accepted noclick.Domain.agreement()
))

connectclassmethodasync

noclick.Domain.connect(name, *, wildcard=False, user=..., client=None) -> Domain

Connect a domain the person already owns (acme.com, or a subdomain like book.acme.com). Connecting it again returns the same domain; one another account has connected raises noclick.Conflict.

On a bare domain, www is the primary address and the bare name needs your DNS host's CNAME flattening (ALIAS or ANAME) or a forward to www.

wildcard=True adds the *.<name> records to records too, so once they're set every subdomain can serve an app (Project.add_domain) or send an app's email without a record of its own: the way to give each of your users an address under yours. Each subdomain goes live once its certificate is issued, usually within minutes of its first use.

Parameters
namestrrequired
wildcardbooldefault False
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
Domain

The domain, pending_dns until the records in records are added where its DNS is hosted, with setup_url when that host can add them in one click (the open Domain Connect standard; the host's consent page names NoClick alongside your brand).

Usage

Connect a domain and add its records where its DNS is hosted:

domain = noclick.Domain.connect("acme.test")
if domain.setup_url:
    print("Add the records in one click:", domain.setup_url)
for record in domain.records:
    print(record.type, record.name, record.value, record.purpose)

Connect it for every subdomain:

domain = noclick.Domain.connect("apps.acme.test", wildcard=True)
print([record.name for record in domain.records])   # includes *.apps.acme.test

transfer_quotestaticasync

noclick.Domain.transfer_quote(name, *, user=..., client=None) -> TransferQuote

Whether name, registered elsewhere, can move to NoClick now, and what moving it costs. Nothing is charged. NoClick works it out from the domain's public registration data (its registrar lock, its transfer lock, whether NoClick registers the TLD) and the registrar's price, so it's a best answer until transfer_in is accepted. A domain already with NoClick's registrar under another account isn't eligible: reason says moving it between accounts isn't supported yet.

Parameters
namestrrequired
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
TransferQuote

The quote: eligible with the price_usd the transfer charges (it adds years to the registration) and the renewal_usd after, or not eligible with the reason and, inside the registry's transfer lock, locked_until.

Usage
quote = noclick.Domain.transfer_quote("acme.test")
if quote.eligible:
    print(f"Moving it costs ${quote.price_usd} and adds {quote.years} year(s), then ${quote.renewal_usd}")
else:
    print(quote.reason, quote.locked_until)

transfer_inclassmethodasync

noclick.Domain.transfer_in(
    name, *, auth_code, max_price_usd, registrant=None, user=..., client=None
) -> DomainTransfer

Move name (a name, a TransferQuote, or a domain you connected) to NoClick from its current registrar, with the auth_code that registrar gives for it. It's charged to your account like a purchase: the quote, which adds the quote's years to the registration, charged once the transfer completes; refused (noclick.PriceExceeded) above max_price_usd; held in awaiting_human while your policy holds purchases. It's registered to registrant on the same rule as Domain.buy, agreement_accepted_at included: required for a user's domain (noclick.InvalidRequest naming registrant without it, and nothing is sent), else your account's default registrant. A name the registry won't move now raises noclick.NotAvailable with the reason (transfer_quote says so first).

Its nameservers don't change during the move, so its DNS keeps working where it's hosted. Once it's active, use_noclick_dns() moves the DNS to NoClick, or it stays where it is like a connected domain. A connected domain keeps its id and what it serves, and passed as a Domain the transfer acts in that domain's own scope (its user, else your account); a name acts for the current user, or user=.

Parameters
namestr | TransferQuote | Domainrequired
auth_codestrrequired
max_price_usdfloatrequired
registrantDomainContact | Nonedefault None
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
DomainTransfer

The transfer: an operation whose .wait() gives the Domain once it's moved, source transferred. The domain is transferring_in meanwhile, up to about 5 days; the current owner may be emailed by their registrar to approve. If the registry refuses (a wrong auth code is noclick.InvalidRequest naming auth_code), the transfer fails with its reason and nothing is charged.

Usage

Check it can move, then move it with the code from its current registrar:

quote = noclick.Domain.transfer_quote("acme.test")
if quote.eligible:
    transfer = noclick.Domain.transfer_in(quote, auth_code="Xy7#pQ2!", max_price_usd=15)
    domain = transfer.wait()
    print(domain.source, domain.expires_at)   # transferred, quote.years later than before

A user's domain is registered to them, charged to you:

ana = noclick.DomainContact(
    name="Ana Silva", email="ana@example.com", phone="+14155550123",
    address="500 Market St", city="San Francisco", region="CA", postal_code="94105", country="US",
    agreement_accepted_at=accepted_at,   # when she accepted noclick.Domain.agreement()
)
with noclick.as_user("user_42"):
    transfer = noclick.Domain.transfer_in(
        "anasilva.dev", auth_code="Kq9!mT4z", max_price_usd=20, registrant=ana,
    )

from_nameclassmethod

noclick.Domain.from_name(
    name, *, create_if_missing=False, max_price_usd=None, years=None, registrant=None,
    auto_renew=..., client=None, user=...
) -> Domain

A lazy reference to your domain called name, bought or connected. With create_if_missing=True your code owns it idempotently: the first time it's used with no such domain, it's bought as Domain.buy would (max_price_usd is required and years is the TLD's minimum when left out; inside as_user the user's registrant is required too, and outside it defaults to your account's own default registrant: with none set, the first use raises noclick.ActionRequired whose next_step links to where it's set), and an existing one whose auto_renew differs is updated. A name someone else holds raises noclick.NotAvailable.

Parameters
namestrrequired
create_if_missingbooldefault False
max_price_usdfloat | Nonedefault None
yearsint | Nonedefault None
registrantDomainContact | Nonedefault None
auto_renewAnyomit to leave it unchanged
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns
Domain

A domain that loads (or is bought) the first time you read a field; noclick.NotFound then if there's none. A domain just bought is registering (awaiting_human while your policy holds it) until the purchase finishes. Nothing is sent yet.

Usage

Refer to a domain you have:

domain = noclick.Domain.from_name("acmebooking.com")
print(domain.status, domain.expires_at)

Or own it from code, run at every deploy: the first run buys it:

domain = noclick.Domain.from_name("acmebooking.com", create_if_missing=True, max_price_usd=15)
print(domain.status)   # registering, then active

from_idclassmethod

noclick.Domain.from_id(domain_id, *, client=None, user=...) -> Domain

A lazy reference to a domain by id.

Parameters
domain_idstrrequired
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
Returns
Domain

A domain that loads the first time you read a field. Nothing is sent yet.

Usage
domain = noclick.Domain.from_id("5c8e2a1f-7b3d-4e96-a0c4-9d1f6b2e8a57")
print(domain.name, domain.serves)

getclassmethodasync

noclick.Domain.get(domain_id, *, user=..., client=None) -> Domain

Load a domain by id now; an unknown id raises noclick.NotFound.

Parameters
domain_idstrrequired
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
Domain

The domain, loaded.

Usage
domain = noclick.Domain.get("5c8e2a1f-7b3d-4e96-a0c4-9d1f6b2e8a57")
print(domain.name, domain.source, domain.status)

listclassmethodasync

noclick.Domain.list(
    *, limit=None, user_filter=None, user=..., client=None
) -> list[Domain]

Your domains, bought and connected (the current user's inside as_user, or those user_filter covers).

Parameters
limitint | None

Return at most this many.

(default None)
user_filterAny

Which users a read covers: noclick.ALL_USERS, noclick.NO_USER, a User, or your id for one. It filters without acting as that user.

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
list[Domain]

Every matching domain, newest first, fetched page by page. A domain transferred out or disconnected isn't listed.

Usage
for domain in noclick.Domain.list():
    print(domain.name, domain.source, domain.status, domain.expires_at)

everyone = noclick.Domain.list(user_filter=noclick.ALL_USERS)   # every user's, plus your account's

list_pageclassmethodasync

noclick.Domain.list_page(
    *, cursor=None, limit=None, user_filter=None, user=..., client=None
) -> Page

One page of domains; pass next_cursor back as cursor.

Parameters
cursorstr | None

The next_cursor of the page before; omit it for the first page.

(default None)
limitint | None

Return at most this many.

(default None)
user_filterAny

Which users a read covers: noclick.ALL_USERS, noclick.NO_USER, a User, or your id for one. It filters without acting as that user.

(default None)
userAny

Who the call acts for. Defaults to the user set by noclick.as_user (none: the account itself).

(defaults to the current user)
clientClient | None

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

(default None)
Returns
Page

A page whose data holds the domains and whose next_cursor is None on the last page.

Usage
page = noclick.Domain.list_page(limit=50)
while True:
    for domain in page.data:
        print(domain.name)
    if page.next_cursor is None:
        break
    page = noclick.Domain.list_page(limit=50, cursor=page.next_cursor)

verifyasync

domain.verify() -> Domain

Check the domain's DNS now, rather than waiting for NoClick's own checks (every few minutes while records are pending).

Returns
Domain

This domain, with each record's status and the domain's own status as found.

Usage
domain = noclick.Domain.from_name("acme.test")
domain.verify()
print(domain.status)   # active once every required record is verified
for record in domain.records:
    print(record.name, record.type, record.status)

updateasync

domain.update(*, auto_renew=None, registrant=None) -> Domain

Change a bought domain's settings; one you leave out is unchanged.

registrant replaces the details of the person it's registered to. ICANN requires accurate details, so update them when the person's change. Changing the registrant's name, organization or email asks the new registrant to confirm their email again (the domain is registrant_unverified meanwhile) and may start the registry's transfer lock (see transfer_locked_until).

Parameters
auto_renewbool | Nonedefault None
registrantDomainContact | Nonedefault None
Returns
Domain

This domain, updated.

Usage

Stop renewing, so the domain lapses at expires_at:

domain = noclick.Domain.from_name("acmebooking.com")
domain.update(auto_renew=False)

Keep the registrant's details current when they change:

import dataclasses
domain = noclick.Domain.from_name("anasilva.dev")
domain.update(registrant=dataclasses.replace(domain.registrant, email="ana@newmail.example"))
print(domain.status)   # registrant_unverified until Ana confirms the new address

renewasync

domain.renew(*, years=None, max_price_usd) -> DomainPurchase

Extend a bought domain's registration now, instead of waiting for auto-renew, by years, or left out the TLD's minimum term (renewal_years, which renewal_usd prices). It's charged to your account when the renewal lands, refused (noclick.PriceExceeded) above max_price_usd, and like a purchase it may wait in awaiting_human for your policy's approver.

An expired domain renews until renewable_until. After that it raises noclick.NotAvailable: renewing past the guaranteed renewal window, or restoring a domain the registry is about to delete, isn't an API call (NoClick support may be able to restore it, at the registry's restore fee).

Parameters
yearsint | Nonedefault None
max_price_usdfloatrequired
Returns
DomainPurchase

The renewal: an operation whose .wait() gives the Domain with its later expires_at.

Usage
domain = noclick.Domain.from_name("acmebooking.com")
renewal = domain.renew(max_price_usd=15)   # renewal_years, at renewal_usd
print(renewal.wait().expires_at)

use_noclick_dnsasync

domain.use_noclick_dns() -> list[DnsRecord]

Move a transferred domain's DNS hosting to NoClick. The records NoClick can read where its DNS is hosted now are copied first, then its nameservers change, so it keeps answering throughout. On a domain whose DNS NoClick already hosts, it copies nothing; a connected domain raises noclick.NotAvailable (transfer it in first).

Returns
list[DnsRecord]

The records it copied, for review: add any it couldn't read with dns.set. The domain's noclick_dns is now True.

Usage
domain = noclick.Domain.from_name("acme.test")
for record in domain.use_noclick_dns():
    print("Copied", record.type, record.name, record.value)
domain.dns.set("TXT", "@", "google-site-verification=3pL0x0kA1b2C")   # one it couldn't read

transfer_outasync

domain.transfer_out() -> TransferCode

Unlock a bought or transferred domain to move it to another registrar. Inside the registry's transfer lock after a domain is registered, transferred in or its registrant changes (transfer_locked_until) it raises noclick.NotAvailable, and a connected domain has nothing to transfer.

Returns
TransferCode

The auth code to give the other registrar, until its expires_at (call transfer_out() again for a fresh one). The domain shows transferring_out until the move completes, then leaves your list.

Usage
domain = noclick.Domain.from_name("acmebooking.com")
try:
    code = domain.transfer_out()
except noclick.NotAvailable as err:
    print(err.message, domain.transfer_locked_until)
else:
    print("Give your new registrar:", code.auth_code)

deleteasync

domain.delete() -> None

Disconnect a connected domain: it stops serving your apps, and its DNS stays as it is where it's hosted. It raises noclick.Conflict while an inbox still uses the domain, and on a bought domain, which can only lapse or be transferred out.

Usage
domain = noclick.Domain.from_name("acme.test")
domain.delete()

DomainOffer

class DomainOffer

A name from noclick.Domain.search; buy it with noclick.Domain.buy(offer, max_price_usd=...). price_usd is what buying it charges now, for min_years (the TLD's shortest term: two years for .ai), and renewal_usd what each renewal of min_years costs; max_years is the longest term the TLD allows. premium means the registry prices this name above its usual rate, often far above.

claims_notice is set during the TLD's trademark-claims period for a name that matches a registered trademark: the Trademark Clearinghouse notice (Markdown) the registrant must be shown before buying it, with accept_claims=True once they have. It's None otherwise.

Attributes
namestr
availablebool
price_usdfloat | None
renewal_usdfloat | None
premiumbool
min_yearsint | None
max_yearsint | None
claims_noticestr | None
rawdict[str, Any]

The response JSON exactly as the API sent it.

DomainContact

noclick.DomainContact(
    name, email, phone, address, city, postal_code, country, region, organization=None,
    agreement_accepted_at=None
)

The registrant: the person a domain is registered to, as the registry records it. ICANN requires real details, kept accurate (domain.update(registrant=...) when they change), and email is sent a link to confirm the address, in your brand on ICANN's behalf; a person confirms once, for all their domains. phone is in E.164 form and country a two-letter code; a second street line follows a newline in address. region is the state, province or region of the address; the registry requires one. Domains are registered through NoClick's registrar partner, which the public registration record names; privacy protection keeps the registrant's details out of it.

organization, when set, is the legal owner (ICANN's "Registered Name Holder"): never put your company on a user's domain unless your company means to own it.

agreement_accepted_at is when this person explicitly accepted the domain registration agreement (Domain.agreement().url). A registration needs it: a registrant, or your account's default registrant, without it is refused with noclick.InvalidRequest naming registrant.agreement_accepted_at.

Parameters
namestrrequired
emailstrrequired
phonestrrequired
addressstrrequired
citystrrequired
postal_codestrrequired
countrystrrequired
regionstrrequired
organizationstr | Nonedefault None
agreement_accepted_atdatetime | Nonedefault None
Usage
ana = noclick.DomainContact(
    name="Ana Silva", email="ana@example.com", phone="+14155550123",
    address="500 Market St", city="San Francisco", region="CA", postal_code="94105", country="US",
    agreement_accepted_at=accepted_at,   # when she accepted noclick.Domain.agreement()
)
[offer] = noclick.Domain.search("anasilva", tlds=["dev"], limit=1)
purchase = noclick.Domain.buy(offer, max_price_usd=20, registrant=ana, user="user_42")
Attributes
namestr
emailstr
phonestr
addressstr
citystr
postal_codestr
countrystr
regionstr
organizationstr | None
agreement_accepted_atdatetime | None

DomainPurchase

class DomainPurchase(Operation)

A domain bought or renewed: the operation Domain.buy and domain.renew return. It's charged to your account when the registry confirms it, and one that fails is never charged; while your policy holds it for a person to approve, it waits in awaiting_human. wait() gives the Domain.

Attributes
price_usdfloat | None

What it charges your account, in US dollars.

domain_idstr | None

The domain being bought or renewed.

domainDomain

The domain, already listed while the purchase runs (its status follows it).

DomainTransfer

class DomainTransfer(DomainPurchase)

A domain moving to NoClick from another registrar: the operation Domain.transfer_in returns. It's charged to your account like a purchase (the quote, which adds the quote's years to the registration) once the transfer completes, and waits in awaiting_human while your policy holds it. The domain is transferring_in while the registry and its current registrar move it, up to about 5 days; wait() gives the Domain once it's active. If the registry refuses, it fails with the registry's reason (a wrong auth code is noclick.InvalidRequest naming auth_code) and nothing is charged.

DnsRecord

class DnsRecord

One DNS record: type (A, CNAME, ALIAS, MX, TXT, ...), name (@ for the domain itself, or the label before it, like www) and value.

status is verified once public DNS answers with it, pending until then, and conflict when another record at that name is in the way. purpose says what it's for. required is False for a record the domain works without (a connected domain's bare-name ALIAS, which forwarding can replace). managed marks a record NoClick keeps for something the domain serves: change what it serves, not the record.

Attributes
typestr
namestr
valuestr
statusstr | None
purposestr | None
requiredbool
managedbool
rawdict[str, Any]

The response JSON exactly as the API sent it.

DomainDns

class DomainDns

domain.dns: the records of a bought domain, whose DNS NoClick hosts. A connected domain's DNS stays where it is (domain.records lists what to add there), so these raise noclick.NotAvailable on one.

recordsasync

domain.dns.records() -> list[DnsRecord]

Every record in the domain's DNS: yours, and the ones NoClick keeps for what it serves.

Returns
list[DnsRecord]

The records, each with its status; managed marks NoClick's.

Usage
domain = noclick.Domain.from_name("acmebooking.com")
for record in domain.dns.records():
    print(record.name, record.type, record.value, "(managed)" if record.managed else "")

setasync

domain.dns.set(type, name, value) -> DnsRecord

Add a record, or keep it if the same one is there. A CNAME replaces the name's existing CNAME (a name holds at most one); other types add alongside the records already at that name. A record that would clash with one NoClick manages raises noclick.Conflict.

Parameters
typestrrequired
namestrrequired
valuestrrequired
Returns
DnsRecord

The record as saved; its status turns verified once public DNS serves it, usually within minutes.

Usage

Prove the domain to another service, or point a name at something you run elsewhere:

domain = noclick.Domain.from_name("acmebooking.com")
domain.dns.set("TXT", "@", "google-site-verification=3pL0x0kA1b2C")
domain.dns.set("CNAME", "status", "acme.statuspage.example")

deleteasync

domain.dns.delete(record) -> None

Remove record (from records()). A record NoClick manages raises noclick.Conflict.

Parameters
recordDnsRecordrequired
Usage
domain = noclick.Domain.from_name("acmebooking.com")
for record in domain.dns.records():
    if record.type == "TXT" and record.value.startswith("google-site-verification="):
        domain.dns.delete(record)

TransferCode

class TransferCode

What domain.transfer_out() gives: the auth_code the other registrar asks for, when the domain was unlocked for the move, and expires_at: when the code stops working, where the registry limits it (None otherwise); call transfer_out() again for a fresh one. Printing it never shows the code.

Attributes
auth_codestr
unlocked_atAny
expires_atAny
rawdict[str, Any]

The response JSON exactly as the API sent it.

TransferQuote

class TransferQuote

What noclick.Domain.transfer_quote finds: whether name can move to NoClick from its current registrar now, and what it costs. eligible is False, with reason, while the domain is locked at its registrar, inside the registry's transfer lock after a domain is registered, transferred in or its registrant changes (until locked_until), on a TLD NoClick doesn't register, or already with NoClick's registrar under another account (moving it between accounts isn't supported yet). price_usd is what the transfer charges your account, and it adds years to the registration (the TLD's minimum, one year for most); renewal_usd is what each renewal of years costs after.

Attributes
namestr
eligiblebool
reasonstr | None
price_usdfloat | None
renewal_usdfloat | None
yearsint | None
locked_untilAny
rawdict[str, Any]

The response JSON exactly as the API sent it.

DomainAgreement

class DomainAgreement

NoClick's domain registration agreement, from noclick.Domain.agreement(). The page at url is the agreement the registrant accepts (it names the sponsoring registrar, as ICANN requires), the fee schedule (registration, renewal, renewal after expiry, restore) and ICANN's registrant rights and responsibilities. Show it to the person and record when they accept it, as agreement_accepted_at on their DomainContact. version names the revision.

Attributes
urlstr
versionstr
rawdict[str, Any]

The response JSON exactly as the API sent it.