Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example code to use the (unofficial, unsupported, undocumented) hover.com DNS API.
import requests
class HoverException(Exception):
pass
class HoverAPI(object):
def __init__(self, username, password):
params = {"username": username, "password": password}
r = requests.post("https://www.hover.com/api/login", params=params)
if not r.ok or "hoverauth" not in r.cookies:
raise HoverException(r)
self.cookies = {"hoverauth": r.cookies["hoverauth"]}
def call(self, method, resource, data=None):
url = "https://www.hover.com/api/{0}".format(resource)
r = requests.request(method, url, data=data, cookies=self.cookies)
if not r.ok:
raise HoverException(r)
if r.content:
body = r.json()
if "succeeded" not in body or body["succeeded"] is not True:
raise HoverException(body)
return body
# connect to the API using your account
client = HoverAPI("myusername", "mypassword")
# get details of a domains without DNS records
client.call("get", "domains")
# get all domains and DNS records
client.call("get", "dns")
# notice the "id" field of domains in response to the above calls - that's needed
# to address the domains individually, like so:
# get details of a specific domain without DNS records
client.call("get", "domains/dom123456")
# get DNS records of a specific domain:
client.call("get", "domains/dom123456/dns")
# create a new A record:
record = {"name": "mysubdomain", "type": "A", "content": "127.0.0.1"}
client.call("post", "domains/dom123456/dns", record)
# create a new SRV record
# note that content is "{priority} {weight} {port} {target}"
record = {"name": "mysubdomain", "type": "SRV", "content": "10 10 123 __service"}
client.call("post", "domains/dom123456/dns", record)
# create a new MX record
# note that content is "{priority} {host}"
record = {"name": "mysubdomain", "type": "MX", "content": "10 mail"}
client.call("post", "domains/dom123456/dns", record)
# notice the "id" field of DNS records in the above calls - that's
# needed to address the DNS records individually, like so:
# update an existing DNS record
client.call("put", "dns/dns1234567", {"content": "127.0.0.1"})
# delete a DNS record:
client.call("delete", "dns/dns1234567")
#!/usr/bin/python
"""
bulkhover.py 1.1
This is a command-line script to import and export DNS records for a single
domain into or out of a hover account.
Usage:
bulkhover.py [options] (import|export) <domain> <dnsfile>
bulkhover.py (-h | --help)
bulkhover.py --version
Options:
-h --help Show this screen
--version Show version
-c --conf=<conf> Path to conf
-u --username=<user> Your hover username
-p --password=<pass> Your hover password
-f --flush Delete all existing records before importing
Examples:
The DNS file should have one record per line, in the format:
{name} {type} {content}
For example:
www A 127.0.0.1
@ MX 10 example.com
Since the script output is in the same format as its input, you can use shell
pipelines to do complex operations.
Copy all DNS records from one domain to another:
bulkhover.py -c my.conf export example.com - | ./bulkhover.py -c my.conf -f import other.com -
Copy only MX records from one domain to another:
./bulkhover.py -c my.conf export foo.com - | awk '$2 == "MX" {print $0}' | ./bulkhover.py -c my.conf import bar.com -
To avoid passing your username and password in the command-line, you can use
a conf file that contains them instead:
[hover]
username=YOUR_USERNAME
password=YOUR_PASSWORD
"""
import ConfigParser
import docopt
import requests
import sys
class HoverException(Exception):
pass
class HoverAPI(object):
def __init__(self, username, password):
params = {"username": username, "password": password}
r = requests.post("https://www.hover.com/api/login", params=params)
if not r.ok or "hoverauth" not in r.cookies:
raise HoverException(r)
self.cookies = {"hoverauth": r.cookies["hoverauth"]}
def call(self, method, resource, data=None):
url = "https://www.hover.com/api/{0}".format(resource)
r = requests.request(method, url, data=data, cookies=self.cookies)
if not r.ok:
raise HoverException(r)
if r.content:
body = r.json()
if "succeeded" not in body or body["succeeded"] is not True:
raise HoverException(body)
return body
def import_dns(username, password, domain, filename, flush=False):
try:
client = HoverAPI(username, password)
except HoverException as e:
raise HoverException("Authentication failed")
if flush:
records = client.call("get", "domains/{0}/dns".format(domain))["domains"][0]["entries"]
for record in records:
client.call("delete", "dns/{0}".format(record["id"]))
print "Deleted {name} {type} {content}".format(**record)
domain_id = client.call("get", "domains/{0}".format(domain))["domain"]["id"]
if filename == "-": filename = "/dev/stdin"
with open(filename, "r") as f:
for line in f:
parts = line.strip().split(" ", 2)
record = {"name": parts[0], "type": parts[1], "content": parts[2]}
client.call("post", "domains/{0}/dns".format(domain), record)
print "Created {name} {type} {content}".format(**record)
def export_dns(username, password, domain, filename):
try:
client = HoverAPI(username, password)
except HoverException as e:
raise HoverException("Authentication failed")
records = client.call("get", "domains/{0}/dns".format(domain))["domains"][0]["entries"]
if filename == "-": filename = "/dev/stdout"
with open(filename, "w") as f:
for record in records:
f.write("{name} {type} {content}\n".format(**record))
def main(args):
def get_conf(filename):
config = ConfigParser.ConfigParser()
config.read(filename)
items = dict(config.items("hover"))
return items["username"], items["password"]
if args["--conf"] is None:
if not all((args["--username"], args["--password"])):
print("You must specifiy either a conf file, or a username and password")
return 1
else:
username, password = args["--username"], args["--password"]
else:
username, password = get_conf(args["--conf"])
try:
if args["import"]:
import_dns(username, password, args["<domain>"], args["<dnsfile>"], args["--flush"])
elif args["export"]:
export_dns(username, password, args["<domain>"], args["<dnsfile>"])
except HoverException as e:
print "Unable to update DNS: {0}".format(e)
return 1
if __name__ == "__main__":
version = __doc__.strip().split("\n")[0]
args = docopt.docopt(__doc__, version=version)
status = main(args)
sys.exit(status)
#!/usr/bin/env python
"""
dynhover.py 1.2
This tool will update an A record for given (sub)domain in your hover.com
with your IP, or an IP that you specify
Usage:
dynhover.py (-c <conf> | -u <user> -p <password>) <domain>
dynhover.py (-h | --help)
dynhover.py --version
Options:
-h --help Show this screen
--version Show version
-c --conf=<conf> Path to conf
-u --username=<user> Your hover username
-p --password=<pass> Your hover password
-i --ip=<ip> An IP to set (auto-detected by default)
"""
import ConfigParser
import docopt
import requests
import sys
class HoverException(Exception):
pass
class HoverAPI(object):
def __init__(self, username, password):
params = {"username": username, "password": password}
r = requests.post("https://www.hover.com/api/login", params=params)
if not r.ok or "hoverauth" not in r.cookies:
raise HoverException(r)
self.cookies = {"hoverauth": r.cookies["hoverauth"]}
def call(self, method, resource, data=None):
url = "https://www.hover.com/api/{0}".format(resource)
r = requests.request(method, url, data=data, cookies=self.cookies)
if not r.ok:
raise HoverException(r)
if r.content:
body = r.json()
if "succeeded" not in body or body["succeeded"] is not True:
raise HoverException(body)
return body
def get_public_ip():
return requests.get("http://ifconfig.me/ip").content
def update_dns(username, password, fqdn, ip):
try:
client = HoverAPI(username, password)
except HoverException as e:
raise HoverException("Authentication failed")
dns = client.call("get", "dns")
dns_id = None
for domain in dns["domains"]:
if fqdn == domain["domain_name"]:
fqdn = "@.{domain_name}".format(**domain)
for entry in domain["entries"]:
if entry["type"] != "A": continue
if "{0}.{1}".format(entry["name"], domain["domain_name"]) == fqdn:
dns_id = entry["id"]
break
if dns_id is None:
raise HoverException("No DNS record found for {0}".format(fqdn))
response = client.call("put", "dns/{0}".format(dns_id), {"content": my_ip})
if "succeeded" not in response or response["succeeded"] is not True:
raise HoverException(response)
def main(args):
if args["--username"]:
username, password = args["--username"], args["--password"]
else:
config = ConfigParser.ConfigParser()
config.read(args["--conf"])
items = dict(config.items("hover"))
username, password = items["username"], items["password"]
domain = args["<domain>"]
ip = args["--ip"] or get_public_ip()
try:
update_dns(username, password, domain, ip)
except HoverException as e:
print "Unable to update DNS: {0}".format(e)
return 1
return 0
if __name__ == "__main__":
version = __doc__.strip().split("\n")[0]
args = docopt.docopt(__doc__, version=version)
status = main(args)
sys.exit(status)
#!/bin/bash
[[ $# -lt 3 ]] && echo "Usage: $0 USERNAME PASSWORD DNS_ID"
USERNAME=${1}
PASSWORD=${2}
DNS_ID=${3}
# find your DNS ID here: https://www.hover.com/api/domains/yourdomain.com/dns/
# (replace "yourdomain.com" with your actual domain, and look for the record
# you want to change. The ID looks like: dns1234567)
IP=$(curl "http://ifconfig.me/ip" -s)
curl "https://www.hover.com/api/dns/${DNS_ID}" \
-X PUT \
-d "content=${IP}" \
-s \
-b <(curl "https://www.hover.com/api/login" \
-X POST \
-G \
-d "username=${USERNAME}" \
-d "password=${PASSWORD}" \
-s \
-o /dev/null \
-c -)
echo
@ericdfields

This comment has been minimized.

Copy link

@ericdfields ericdfields commented May 23, 2013

Thanks for this! Perfect timing. I'm getting an error when I try to execute the dynhover though. Here's the trace:

./dynhover.py -c ~/.hoverconfig mydomain.com
Traceback (most recent call last):
  File "./dynhover.py", line 108, in <module>
    main()
  File "./dynhover.py", line 103, in main
    update_dns(username, password, domain)
  File "./dynhover.py", line 51, in update_dns
    client = HoverAPI(username, password)
  File "./dynhover.py", line 29, in __init__
    r = requests.post("https://www.hover.com/signin", params=params)
  File "/usr/local/lib/python2.7/dist-packages/requests-1.2.2-py2.7.egg/requests/api.py", line 88, in post
    return request('post', url, data=data, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests-1.2.2-py2.7.egg/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests-1.2.2-py2.7.egg/requests/sessions.py", line 335, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests-1.2.2-py2.7.egg/requests/sessions.py", line 438, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests-1.2.2-py2.7.egg/requests/adapters.py", line 327, in send
    raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.hover.com', port=443): Max retries exceeded with url: /signin?username=myusername&password=mypassword (Caused by <class 'socket.error'>: [Errno 104] Connection reset by peer)

Any help would be appreciated. Thanks.

@ericdfields

This comment has been minimized.

Copy link

@ericdfields ericdfields commented May 23, 2013

It's certainly the actual auth attempt at line 29. I can't get it to work in the python console either.

@dankrause

This comment has been minimized.

Copy link
Owner Author

@dankrause dankrause commented May 23, 2013

interesting - I can't duplicate that. If I intentionally use bad auth, I get the "Unable to update DNS: Authentication failed" error. The "Connection reset by peer" error is something you're actually getting from Hover. Try using curl to duplicate the error:

curl "https://www.hover.com/signin"      \
               -X POST                   \
               -G                        \
               -d "username=${USERNAME}" \
               -d "password=${PASSWORD}" \
               -s                        \
               -o /dev/null              \
               -D -

If you get the same error, the problem doesn't live in the code. If the curl command works (you'll see output includnig a hover_session cookie), I'll see if I can keep digging.

Edit: Just added a bash version of the dynhover script, just in case.

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Jul 28, 2013

I have an almost similar problem. If i run the _example.py script (I uncommented everything after the first two client.calls). Result is:

Traceback (most recent call last):
  File "test.py", line 27, in <module>
    client = HoverAPI("name", "pass")
  File "test.py", line 10, in __init__
    r = requests.post("https://www.hover.com/signin", params=params)
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 85, in post
    return request('post', url, data=data, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 40, in request
    return s.request(method=method, url=url, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 229, in request
    r.send(prefetch=prefetch)
  File "/usr/lib/python2.7/dist-packages/requests/models.py", line 605, in send
    raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.hover.com', port=443): Max retries exceeded with url: /signin?username=name&password=pass

When using curl as above, I don't get any output at all.

Can you please point me to the cause? I would appreciate it, because your scripts are exactly what I need.

@rmorlang

This comment has been minimized.

Copy link

@rmorlang rmorlang commented Oct 30, 2013

Thanks for the code. Looks like Hover changed the signin URL to /api/login. Fork with update at https://gist.github.com/rleemorlang/7225451

@dankrause

This comment has been minimized.

Copy link
Owner Author

@dankrause dankrause commented Jan 20, 2014

Thanks @rleemorlang - I've updated the gist. Sorry for the belated reply. Apparently, I'm not getting notifications for comments on gists.

@jeffhigham

This comment has been minimized.

Copy link

@jeffhigham jeffhigham commented May 9, 2014

api.exip.org appears to have disabled this feature.
IP=$(curl "http://api.exip.org/?call=ip" -s)

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented May 15, 2014

@jeffhigham you can replace the url with http://ifconfig.me

@dankrause

This comment has been minimized.

Copy link
Owner Author

@dankrause dankrause commented Aug 13, 2014

I've updated the code to use http://ifconfig.me/ip instead of http://api.exip.org/?call=ip

@neonspectra

This comment has been minimized.

Copy link

@neonspectra neonspectra commented Dec 23, 2014

The bash version of the script worked for me in the past, but as of now I'm getting an error when it tries to update:

{"succeeded":false,"error_code":"login","error":"You must login first"}

I think hover might have changed their login api again, but I can't seem to find any usage notes on the api, so I'm unsure how to fix it.

@worldofchris

This comment has been minimized.

Copy link

@worldofchris worldofchris commented Jun 2, 2015

This is excellent.

I used it as the basis of a Python Module and an Ansible Module which I'm using to automate the configuration of DNS records for a big AWS deployment.

Have retained your commit history and given you credit in the READMEs.

@wanderleyteixeira

This comment has been minimized.

Copy link

@wanderleyteixeira wanderleyteixeira commented Jun 19, 2015

Meissa, were you able to fix the bash script?

@benjaminchodroff

This comment has been minimized.

Copy link

@benjaminchodroff benjaminchodroff commented Aug 6, 2015

Anyone else noticing this is broken? I think there may have been security changes at Hover regarding an incident. I'm receiving the following error on attempting a login:
requests.exceptions.ConnectionError: ('Connection aborted.', error(54, 'Connection reset by peer'))

@barcoboy

This comment has been minimized.

Copy link

@barcoboy barcoboy commented Aug 6, 2015

Yes, I'm seeing the same behavior. My scripts started failing at around 5:00pm Tuesday night (August 4th). On one of my servers I am getting the same message, and another one which I believe is running a different version of Python, is giving me the error:
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.hover.com', port=443): Max retries exceeded with url: /api/login?username=xxxxxxxx&password=yyyyyyyy

@benjaminchodroff

This comment has been minimized.

Copy link

@benjaminchodroff benjaminchodroff commented Aug 7, 2015

This might be how to fix it but I'm not quite certain how to handle the redirects when signing in. Hope it helps

class HoverAPI(object):
    def __init__(self, username, password):
        params = {"username": username, "password": password}
        r = requests.post("https://www.hover.com/signin", params=params)
        if not r.ok or not len(r.history)>0 or "hoverauth"  not in r.history[0].cookies:
            raise HoverException(r)
        self.cookies = {"hoverauth": r.history[0].cookies["hoverauth"]}
    def call(self, method, resource, data=None):
        url = "https://www.hover.com/api/{0}".format(resource)
        r = requests.request(method, url, data=data, cookies=self.cookies)
        if not r.ok:
            raise HoverException(r)
        if r.content:
            body = r.json()
            if "succeeded" not in body or body["succeeded"] is not True:
                raise HoverException(body)
            return body
@barcoboy

This comment has been minimized.

Copy link

@barcoboy barcoboy commented Aug 7, 2015

Getting logged in now, but now when I try to use client.call("get", "dns"), I get this error:

Traceback (most recent call last):
File "/usr/local/bin/update-hover-dns.py", line 65, in
result = client.call("get", "dns")
File "/usr/local/bin/update-hover-dns.py", line 35, in call
body = r.json()
TypeError: 'dict' object is not callable

@barcoboy

This comment has been minimized.

Copy link

@barcoboy barcoboy commented Aug 10, 2015

Found the solution to my problem here:

http://love-python.blogspot.ca/2013/03/dict-object-is-not-callable-on-json.html

In short, changed body = r.json() to body = r.json solved it.

@addisflava

This comment has been minimized.

Copy link

@addisflava addisflava commented Nov 6, 2015

How could i make the bash script add a wildcard record so i could point all my sub-domain to the same ip address . right now its adding @ record in host field for the root domain only . i want it to add like the following

image

@twiztedindian

This comment has been minimized.

Copy link

@twiztedindian twiztedindian commented Feb 22, 2016

@addisflava, assuming you're just running the script via CRON just do multiple calls one for @ and one for * since they both have their own dnsID

@maximino

This comment has been minimized.

Copy link

@maximino maximino commented Feb 28, 2016

Assuming this is still active, @meissa, @wbtf, anyone, have you guys resolved the:

{"succeeded":false,"error_code":"login","error":"You must login first"}

Error/problem with the bash version?

Thanks!

@CalebMcDonald

This comment has been minimized.

Copy link

@CalebMcDonald CalebMcDonald commented Sep 5, 2016

I'm also getting this issue and can't find a fix...

{"succeeded":false,"error_code":"login","error":"You must login first"}

@shillem

This comment has been minimized.

Copy link

@shillem shillem commented Sep 26, 2016

Same here

@DavidKep

This comment has been minimized.

Copy link

@DavidKep DavidKep commented Oct 22, 2016

So using this it seems to authenticate (If I use the wrong password I can reliably get an authentication error) but I get this result:

[22:59 david@plex ~] > python dynhover.py -u d#####t -p N######a k######x.com
Traceback (most recent call last):
  File "dynhover.py", line 100, in <module>
    status = main(args)
  File "dynhover.py", line 89, in main
    update_dns(username, password, domain, ip)
  File "dynhover.py", line 70, in update_dns
    response = client.call("put", "dns/{0}".format(dns_id), {"content": my_ip})
NameError: global name 'my_ip' is not defined

any thoughts?

@eaghra

This comment has been minimized.

Copy link

@eaghra eaghra commented Apr 5, 2017

I modified the bash script dynhover.sh to fit my needs and also fixed the "You must login first" error. It seemed Curl wasn't using cookies to save the login session. So I changed it to first login, and then run the subsequent dns updates. It might not be as elegant as the simple script above (I'm not a bash coder by any means), but I also made it do a bit more.

I'm using it on a router (EdgeRouter X), so I have easy access to what my current IP is via ethernet interfaces instead of relying on external websites. In this case I parsed the output of the app ip to get the address. Then the address is stored in a file next to the script so that the next time it runs it doesn't have to do any external calls or update hover if it doesn't have to by simply comparing the current ip to one used the last time hover was updated. If it needs updating, it runs the curl commands and writes the new address back to the file. If you want to use it, you'll probably have to change the location of apps used (or the apps themselves, or even go back to using external sites for the ip variable) and storage locations, but if you're on EdgeOS, it should work as is if you stick it in /config/scripts. It also no longer looks for variables passed to it and instead hardcodes them, so if you want that back you can change those relevant lines back to the ones above.

#!/bin/bash

# find your DNS ID here: https://www.hover.com/api/domains/yourdomain.com/dns/
# (replace "yourdomain.com" with your actual domain, and look for the record
# you want to change. The ID looks like: dns1234567)
USERNAME=usernamehere
PASSWORD=passwordhere
DNS_ID=dnsrecord1 # put dns record here for A record @
DNS_ID2=dnsrecord2 # put dns record here for A record *
firstrun=0
ipfile="/config/scripts/lastip"

# get current ip
IP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)

# check for file to store last ip and if it doesn't exist, create it and write current ip to it
if [ ! -e "$ipfile" ] ; then
	echo "lastip file doesn't exist. creating now."
	touch "$ipfile"
	if [ ! -w "$ipfile" ] ; then
		echo "cannot write to $ipfile"
		exit 1
	else
		# can write to new file, so insert variable
		echo "lastip=$IP" > $ipfile
		echo "wrote current ip into new file $ipfile"
		firstrun=1
	fi
fi


# get ip last time script ran
source $ipfile
# compare ip in file to current
if [ $IP != $lastip ] || [ $firstrun = 1 ]
then
	# not the same or first time running script.  login, get cookie, then update.
	echo "logging in to hover"
	curl "https://www.hover.com/api/login" \
		-X POST                   \
		-G                        \
		-d "username=${USERNAME}" \
		-d "password=${PASSWORD}" \
		-s                        \
		-o /dev/null              \
		--cookie "cookies.txt" \
		--cookie-jar "cookies.txt"
	echo -e "\nupdating first dns entry"
	curl "https://www.hover.com/api/dns/${DNS_ID}" \
		-X PUT            \
		-d "content=${IP}" \
		-s                \
		--cookie "cookies.txt" \
		--cookie-jar "cookies.txt"
	echo -e "\nupdating second dns entry"
	curl "https://www.hover.com/api/dns/${DNS_ID2}" \
		-X PUT            \
		-d "content=${IP}" \
		-s                \
		--cookie "cookies.txt" \
		--cookie-jar "cookies.txt" \
	# save this new ip to file
	echo "lastip=$IP" > $ipfile
	echo
else
	echo "ip hasn't changed"
fi
@macteo

This comment has been minimized.

Copy link

@macteo macteo commented Apr 12, 2018

I got the "You must login first error" again, this is my current simple version

#!/bin/bash

[[ $# -lt 3 ]] && echo "Usage: $0 USERNAME PASSWORD DNS_ID"

USERNAME=${1}
PASSWORD=${2}
DNS_ID=${3}

# find your DNS ID here: https://www.hover.com/api/domains/yourdomain.com/dns/

# (replace "yourdomain.com" with your actual domain, and look for the record
# you want to change. The ID looks like: dns1234567)

IP=$(curl "https://api.ipify.org" -s)

curl -X "POST" "https://www.hover.com/api/login" \
     --data-urlencode "username=${USERNAME}" \
     --data-urlencode "password=${PASSWORD}" \
     --cookie "cookies.txt"    \
     --cookie-jar "cookies.txt"

curl "https://www.hover.com/api/dns/${DNS_ID}" \
    -X PUT            \
    -d "content=${IP}" \
    -s                \
    --cookie "cookies.txt" \
    --cookie-jar "cookies.txt"

echo
@appinator

This comment has been minimized.

Copy link

@appinator appinator commented Jun 4, 2018

Any chance you guys have the 2FA activated? I had mine active. Disabling it, let me login.

@mwoffenden

This comment has been minimized.

Copy link

@mwoffenden mwoffenden commented Jan 4, 2019

Anyone have an example of calling this from Powershell?

@mope1

This comment has been minimized.

Copy link

@mope1 mope1 commented Jan 16, 2019

it looks like they changed where they post the username/password json, line 10:

r = requests.post("https://www.hover.com/signin/auth.json", params=params)
@bkanuka

This comment has been minimized.

Copy link

@bkanuka bkanuka commented Jan 30, 2019

I cannot get any PUT to work. I always get back: {"succeeded":false,"error":"Can not update attributes: dn"} Has anyone been able to fix this?

@l0cutis

This comment has been minimized.

Copy link

@l0cutis l0cutis commented May 23, 2019

As the API is entirely un-documented and un-supported, it appears they've made some changes recently :)

The API URL for a DNS update is now
https://www.hover.com/api/control_panel/dns

and the minimum JSON required to perform an update is
{"domain":{"id":"domain-YOURDOMAIN.COM","dns_records":[{"id":"dns12345678"}]},"fields":{"content":"127.0.0.1"}}

For anyone interested @mwoffenden , I've pulled this together into a powershell script which will update a single record.
The script demonstrates the bare essentials, nothing clever - but it does what I need it to for now :)

#Update which Hover record?
$dnsID =     "dns12345678"
$dnsdomain = "YOURDOMAIN.com"
$username = "Username"
$password = "Password"


#Get current public IP (pretty cool little trick, don't adjust this line)
$myIP = Resolve-DnsName -Name myip.opendns.com -Server resolver1.opendns.com

#Connect to HoverAPI
$Headers = @{   "accept"="application/json";
                "content-type"="application/json"}
$params = @{    "username"=$username;
                "password"=$password}

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$loginResult = Invoke-WebRequest -Uri "https://www.hover.com/api/login" -Method POST -Body ($params|ConvertTo-Json) -Headers $Headers -SessionVariable WebSession

#Check the login was successful
if($loginResult.Headers.'Set-Cookie' -notmatch "hoverauth" -or $loginResult.StatusDescription -ne "OK")
{
    Write-Host "There has been a problem"
}
else
{
    #update the record
    $jsonRequest = '{"domain":{"id":"domain-' + $dnsdomain + '","dns_records":[{"id":"'+$dnsID+'"}]},"fields":{"content":"' + $myIP.IPAddress + '"}}'
    $updateResult = Invoke-WebRequest -Uri "https://www.hover.com/api/control_panel/dns" -Method put -Body $jsonRequest -WebSession $WebSession
}

Cheers!
Nat

@lorenzo95

This comment has been minimized.

Copy link

@lorenzo95 lorenzo95 commented May 10, 2020

Does anyone have a working solution to create/delete a txt record for _acme-challenge using curl at the moment?

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment