core

Sherlock is a python SDK for AI agents to interact with the Sherlock API.

Sherlock

This is the main class for the SDK. If a private key is not provided, we will try to load it from the config file. If neither the private key nor the config file is provided, we will generate a new one and store it in the config file.


source

Sherlock

 Sherlock (priv:str='')

Sherlock client class to interact with the Sherlock API.

Type Default Details
priv str private key
s = Sherlock(priv)
s
Sherlock(pubkey=90ba884688884277e49080712f386eebc88806efa8345ca937f75fe80950156d)

Me

Let’s do an authenticated request to verify we’re authenticated.

Exported source
def _mk_headers(tok): return {"Authorization": f"Bearer {tok}"}
r = httpx.get(me_endpoint, headers=_mk_headers(s.atok))
r, r.json()
(<Response [200 OK]>,
 {'logged_in': True,
  'email': 'jordi@fewsats.com',
  'public_key': '90ba884688884277e49080712f386eebc88806efa8345ca937f75fe80950156d'})

source

Sherlock.me

 Sherlock.me ()

Get authenticated user information

s.me()
{'logged_in': True,
 'email': 'jordi@fewsats.com',
 'public_key': '90ba884688884277e49080712f386eebc88806efa8345ca937f75fe80950156d'}

API methods

Claim account

Accounts created by AI Agents can link an email. After confirming the account users will be able log in and use the web interface for Sherlock Domains.

An email cannot be claimed more than once.


source

Sherlock.claim_account

 Sherlock.claim_account (email:str)

Claim an account by linking an email address

Search domains

Search domains returns domain availability and its prices in USD cents.


source

Sherlock.search

 Sherlock.search (q:str)

Search for domains with a query. Returns prices in USD cents.

Type Details
q str query
sr = s.search("trakwiska")
# Don't print the whole lists
sr['available'] = sr['available'][:1]
sr['unavailable'] = sr['unavailable'][:1]
sr
{'id': '49350e55-aaf1-4acd-93f1-304d33271207',
 'created_at': '2025-01-14T03:34:33.957Z',
 'available': [{'name': 'trakwiska.com',
   'tld': 'com',
   'tags': [],
   'price': 1105,
   'currency': 'USD',
   'available': True}],
 'unavailable': []}

Contact Information

Contact information is required for ICANN domain registration and billing.


source

Contact

 Contact (first_name, last_name, email, address, city, state, postal_code,
          country)

Contact information for a domain purchase


source

Sherlock.get_contact_information

 Sherlock.get_contact_information ()

Get the contact information for the Sherlock user.


source

Sherlock.set_contact_information

 Sherlock.set_contact_information (cfn:str='', cln:str='', cem:str='',
                                   cadd:str='', cct:str='', cst:str='',
                                   cpc:str='', ccn:str='')

Set the contact information for the Sherlock user

Type Default Details
cfn str contact first name
cln str contact last name
cem str contact email
cadd str contact address
cct str contact city
cst str contact state
cpc str contact postal code
ccn str contact country

source

Contact.is_valid

 Contact.is_valid ()

Check if the contact information is valid

info = {
    "first_name": "Test",
    "last_name": "User",
    "email": "test@example.com",
    "address": "123 Test St",
    "city": "Test City",
    "state": "CA",
    "country": "US",
    "postal_code": "12345",
}  

c = Contact(**info)
c, c.is_valid()
(Contact(first_name='Test', last_name='User', email='test@example.com', address='123 Test St', city='Test City', state='CA', postal_code='12345', country='US'),
 True)
r = s.set_contact_information(
    cfn=info['first_name'],
    cln=info['last_name'],
    cem=info['email'],
    cadd=info['address'],
    cct=info['city'],
    cst=info['state'],
    cpc=info['postal_code'],
    ccn=info['country']
)
r
{'message': 'Contact information updated successfully'}
r = s.get_contact_information()
r
{'first_name': 'Test',
 'last_name': 'User',
 'address': '123 Test St',
 'city': 'Test City',
 'state': 'CA',
 'postal_code': '12345',
 'country': 'US',
 'email': 'test@example.com'}

Purchase a domain

A purchase needs to be linked to a search id. The purchase flow implements the L402 protocol. The flow has two steps:

  1. Get available payment options for a domain
  2. Get payment details (checkout URL for credit card, invoice for Lightning Network) so it can be completed outband.
pd = _get_offers_payload("trakwiska.com", c, sr['id'])
pd
{'domain': 'trakwiska.com',
 'contact_information': {'first_name': 'Test',
  'last_name': 'User',
  'email': 'test@example.com',
  'address': '123 Test St',
  'city': 'Test City',
  'state': 'CA',
  'postal_code': '12345',
  'country': 'US'},
 'search_id': '49350e55-aaf1-4acd-93f1-304d33271207'}
r = httpx.post(get_offers_endpoint, json=pd, headers=_mk_headers(s.atok))
r, r.json()
(<Response [402 Payment Required]>,
 {'version': '0.2.1',
  'payment_request_url': 'https://api.sherlockdomains.com/api/v0/payments/l402/payment_request',
  'payment_context_token': '90ba884688884277e49080712f386eebc88806efa8345ca937f75fe80950156d',
  'offers': [{'id': '0c1e9f4a-8cc9-430e-9d40-1f74753ca8c5',
    'title': 'trakwiska.com',
    'description': 'Purchase trakwiska.com for 11.05 USD',
    'type': 'one-time',
    'amount': 1105,
    'currency': 'USD',
    'payment_methods': ['credit_card', 'lightning']}]})

source

Sherlock.get_purchase_offers

 Sherlock.get_purchase_offers (sid:str, domain:str, c:__main__.Contact)

Request available payment options for a domain.

Type Details
sid str search id
domain str domain
c Contact contact information

Requesting a purchase will return a list of available offers and payment methods.

ofs = s.get_purchase_offers(sr['id'], "trakwiska.com", c)
ofs
{'version': '0.2.1',
 'payment_request_url': 'https://api.sherlockdomains.com/api/v0/payments/l402/payment_request',
 'payment_context_token': '90ba884688884277e49080712f386eebc88806efa8345ca937f75fe80950156d',
 'offers': [{'id': 'dcaa88c0-e29f-4075-921f-83e6cde56ef3',
   'title': 'trakwiska.com',
   'description': 'Purchase trakwiska.com for 11.05 USD',
   'type': 'one-time',
   'amount': 1105,
   'currency': 'USD',
   'payment_methods': ['credit_card', 'lightning']}]}

In order to pay for the domain you will have to request the payment details of the offer you want to pay for.

data = {
    "offer_id": first(ofs['offers'])['id'],
    "payment_method": 'credit_card',
    "payment_context_token": ofs['payment_context_token']
}
r = httpx.post(ofs['payment_request_url'], json=data)
r, r.json()
(<Response [200 OK]>,
 {'payment_method': {'checkout_url': 'https://checkout.stripe.com/c/pay/cs_live_a1Om85Efvv1lgfE8BbhUNibQyzwoEfG8qvKPeOVoSt5tv0wx2rxcgiKofV#fidkdWxOYHwnPyd1blppbHNgWjA0S3VzXDdBbTFNVlJzfDVRQVQ2dVdBTnJTSH1QMGs2dHRsanJMbkY0PTxKbUtRaWowT2NwMGM8RlVBbGRqSWo3UFYwcVdqR3F9N2BtM2ZTPXc1Z3dQXGc2NTVPYVVSQkM8bycpJ2N3amhWYHdzYHcnP3F3cGApJ2lkfGpwcVF8dWAnPyd2bGtiaWBabHFgaCcpJ2BrZGdpYFVpZGZgbWppYWB3dic%2FcXdwYHgl',
   'lightning_invoice': None},
  'expires_at': '2025-01-14T04:04:35.484Z'})

source

Sherlock.get_payment_details

 Sherlock.get_payment_details (prurl:str, oid:str, pm:str, pct:str)

Get payment details for an offer.

Type Details
prurl str payment request url
oid str offer id
pm str payment method
pct str payment context token

source

Sherlock.request_payment_details

 Sherlock.request_payment_details (sid:str, domain:str,
                                   payment_method:str='credit_card',
                                   contact:__main__.Contact=None)

Request payment information for purchasing a domain. Returns the details needed to complete the payment (like a checkout URL).

Type Default Details
sid str search id
domain str domain
payment_method str credit_card payment method {‘credit_card’, ‘lightning’}
contact Contact None contact information

DNS methods


source

Sherlock.domains

 Sherlock.domains ()

List of domains owned by the authenticated user

ds = s.domains()
ds
[{'id': 'd9b2cc30-c15d-44b9-9d39-5d33da504484',
  'domain_name': 'h402.org',
  'created_at': '2024-12-28T18:58:49.899Z',
  'expires_at': '2024-12-31T18:58:42Z',
  'auto_renew': False,
  'locked': True,
  'private': True,
  'nameservers': [],
  'status': 'active'}]

source

Sherlock.dns_records

 Sherlock.dns_records (domain_id:str)

Get DNS records for a domain.

Type Details
domain_id str domain id
did = first(ds)['id']
rs = s.dns_records(did)
rs
{'domain': 'h402.org',
 'records': [{'id': '8c1df0e3ad7ff4b30695a11e20d84b72',
   'type': 'A',
   'name': 'h402.org',
   'value': '76.76.21.21',
   'ttl': 3600}]}

source

Sherlock.create_dns

 Sherlock.create_dns (domain_id:str, type:str='TXT', name:str='test',
                      value:str='test-1', ttl:int=3600)

Create a new DNS record

Type Default Details
domain_id str domain id
type str TXT type
name str test name
value str test-1 value
ttl int 3600 ttl
entry = s.create_dns(
    domain_id=did,
    type="TXT",
    name="test-sherlock",  # This will create test-sherlock.yourdomain.com
    value="hello-world",   # The actual text content
    ttl=3600              # Time to live in seconds
)

created_record_id = first(entry['records'])['id']
created_record_id, entry
('b22820c45b6f2a48461c3a52ca486b5a',
 {'domain': 'h402.org',
  'records': [{'id': 'b22820c45b6f2a48461c3a52ca486b5a',
    'type': 'TXT',
    'name': 'test-sherlock',
    'value': 'hello-world',
    'ttl': 3600}]})
s.dns_records(did)
{'domain': 'h402.org',
 'records': [{'id': '8c1df0e3ad7ff4b30695a11e20d84b72',
   'type': 'A',
   'name': 'h402.org',
   'value': '76.76.21.21',
   'ttl': 3600},
  {'id': 'b22820c45b6f2a48461c3a52ca486b5a',
   'type': 'TXT',
   'name': 'test-sherlock.h402.org',
   'value': 'hello-world',
   'ttl': 3600}]}

source

Sherlock.update_dns

 Sherlock.update_dns (domain_id:str, record_id:str, type:str='TXT',
                      name:str='test-2', value:str='test-2', ttl:int=3600)

Update a DNS record

Type Default Details
domain_id str domain id
record_id str record id
type str TXT type
name str test-2 name
value str test-2 value
ttl int 3600 ttl
updated_record = s.update_dns(
    domain_id=did,
    record_id=entry['records'][0]['id'],
    type="TXT",
    name="test-sherlock",
    value="hello-world-updated",
    ttl=3600
)
updated_record_id = first(updated_record['records'])['id']
updated_record_id, updated_record
('3944584c93667d49c774e7823a039cd8',
 {'domain': 'h402.org',
  'records': [{'id': '3944584c93667d49c774e7823a039cd8',
    'type': 'TXT',
    'name': 'test-sherlock',
    'value': 'hello-world-updated',
    'ttl': 3600}]})

source

Sherlock.delete_dns

 Sherlock.delete_dns (domain_id:str, record_id:str)

Delete a DNS record

Type Details
domain_id str domain id
record_id str record id
s.delete_dns(did, updated_record_id)
{'domain': 'h402.org', 'deleted_records': ['3944584c93667d49c774e7823a039cd8']}

We expose Sherlock’s core functionality as tools for AI agents. Note that payment handling for L402 offers requires additional tools like fewsats.Client().pay.


source

Sherlock.as_tools

 Sherlock.as_tools ()

Return the Sherlock class as a list of tools ready for agents to use

s.as_tools().map(lambda t: t.__name__)
(#10) ['_me','_set_contact_information','_get_contact_information','_search','_purchase_domain','_domains','_dns_records','_create_dns_record','_update_dns_record','_delete_dns_record']

CLI


source

Sherlock.as_cli

 Sherlock.as_cli ()

Return the Sherlock class as a list of tools ready for agents to use

You can use the Sherlock class as a CLI tool.

 sherlock
usage: sherlock [-h] {me,set_contact_information,get_contact_information,search,purchase_domain,domains,dns_records,create_dns,update_dns,delete_dns} ...

positional arguments:
  {me,set_contact_information,get_contact_information,search,purchase_domain,domains,dns_records,create_dns,update_dns,delete_dns}
    me                  Get authenticated user information
    set_contact_information
                        Set the contact information for the Sherlock user
    get_contact_information
                        Get the contact information for the Sherlock user.
    search              Search for domains with a query. Returns prices in USD cents.
    purchase_domain     Request payment information for purchasing a domain. Returns the details needed to complete the payment (like a checkout URL).
    domains             List of domains owned by the authenticated user
    dns_records         Get DNS records for a domain.
    create_dns          Create a new DNS record
    update_dns          Update a DNS record
    delete_dns          Delete a DNS record

options:
  -h, --help            show this help message and exit

source

main

 main ()

CLI interface for Sherlock