Point a domain at your server
4 steps · Checked against the API code 3 November 2026
A guide does one task from start to finish. Every endpoint, with all its fields and cases, is in the API reference.
A domain reaches your server through two records: an A record with the server’s IPv4 address and an AAAA record with its IPv6 address. You find the domain’s DNS zone, look at what the names point at now, change the records that exist and create the ones that are missing. Do it for the domain itself (@) and for www.
Before you start
Section titled “Before you start”- The requests use your key from
$HOSTUP_API_KEY(Quickstart). The key needs the scopewrite:dns. It coversread:dnsas well. Keys and scopes - The server’s IPv4 and IPv6 addresses. A server without IPv6 needs only the A records.
- The domain uses Hostup’s nameservers, for example
primary.ns.hostup.seandsecondary.ns.hostup.se. Records in a Hostup zone are saved either way. They only answer once the domain is delegated to those nameservers. Change a domain’s nameservers shows how.
For a Hostup VPS, Get VPS network state prints both addresses. It needs read:vm, read:network and read:services. The first line is the IPv4 address. The second is the IPv6 address.
export VPS_ID="vps_…" # your VPS: List VPS instancescurl -s "https://cloud.hostup.se/api/v2/vps/$VPS_ID/network" \ -H "Authorization: Bearer $HOSTUP_API_KEY" \ | jq -r '.primaryIP, (.interfaces[].ip[]? | select(.type == "ipv6" and .isPrivate == false) | .ip)'1. Find the DNS zone
Section titled “1. Find the DNS zone”Ask for the zone by the domain name. Send the domain itself, not www.example.com.
curl "https://cloud.hostup.se/api/v2/dns-zones?name=example.com" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "data": [ { "id": "zone_01hxa3b4c5d6e7f8g9h0j1k2m3", "name": "example.com", "status": "active", "isDnsOnly": false, "kind": "linked" } ], "hasMore": false, "nextCursor": null}Keep the zone ID. Every record call below uses it.
export ZONE_ID="zone_…" # data[0].id aboveIf data is empty
Section titled “If data is empty”The account has no DNS zone with that name. The same empty list comes back when the key is limited to other DNS zones. Then use a key that may manage this zone.
For a domain registered with Hostup that uses Hostup’s nameservers, reading the domain’s DNS creates the missing zone. That read needs read:domains as well. Find the domain ID first:
curl "https://cloud.hostup.se/api/v2/domains?name=example.com" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "data": [ { "id": "dom_01hxa3b4c5d6e7f8g9h0j1k2m3", "name": "example.com", "…": "…" } ], "hasMore": false, "nextCursor": null}export DOMAIN_ID="dom_…" # data[0].id aboveThen read the domain’s DNS with List a domain’s DNS records:
curl "https://cloud.hostup.se/api/v2/domains/$DOMAIN_ID/dns" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "zone": { "id": "zone_01hxa3b4c5d6e7f8g9h0j1k2m3", "name": "example.com", "status": "active", "…": "…" }, "…": "…"}export ZONE_ID="zone_…" # zone.id aboveWhen zone is still null, create the zone from the domain’s DNS page in the client area. Do the same for a domain registered elsewhere.
2. See what the names point at now
Section titled “2. See what the names point at now”To do steps 2 and 3 in one go, use the script in All four records with one script.
List the records at each name. For name, send @ for the domain itself. A label such as www and a full name such as www.example.com both work. Without a type, ?name=www also shows a CNAME.
curl "https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records?type=A&name=@" \ -H "Authorization: Bearer $HOSTUP_API_KEY"curl "https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records?type=AAAA&name=@" \ -H "Authorization: Bearer $HOSTUP_API_KEY"curl "https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records?name=www" \ -H "Authorization: Bearer $HOSTUP_API_KEY"The answer for the A record at @:
{ "zone": { "id": "zone_01hxa3b4c5d6e7f8g9h0j1k2m3", "name": "example.com", "status": "active", "recordCount": 1, "…": "…" }, "records": [ { "id": "drr_01hxa3b4c5d6e7f8g9h0j1k2m3", "type": "A", "name": "example.com", "value": "198.51.100.7", "ttl": 3600 } ]}When a record comes back, it exists. Step 3 changes it by its id. An empty records means the record is missing. Step 3 creates it.
export RECORD_ID="drr_…" # records[0].id of the record you change firstFour cases need a decision:
- Several A or AAAA records at a name. All of them answer. Change one in step 3 and delete the others. An old AAAA record left at the previous server sends IPv6 visitors there. Change it. Delete it if your server has no IPv6 address.
wwwis a CNAME. A CNAME that points atexample.comalready follows the domain. Leave it and skipwww. A CNAME that points somewhere else has to go. A CNAME cannot share its name with other records. Delete it before you create the A and AAAA records.- Moving a live site. Lower the TTL first. Send the PUT from step 3 with the old
valueand"ttl": 300. Wait until the old TTL shown here has run out (3600 seconds in the example). Then send the PUT with the new address. Visitors then move over within five minutes. - The domain shows Hostup’s parking page. The A record at
@belongs to the parking page. Change it like any other A record.
3. Change or create each record
Section titled “3. Change or create each record”Do this for the A and AAAA records at @ and at www. Change a record that step 2 returned. Create one that is missing.
If the record exists
Section titled “If the record exists”Send the whole record to its ID from step 2.
curl -X PUT "https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records/$RECORD_ID" \ -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" \ -d '{"type": "A", "name": "@", "value": "192.0.2.10", "ttl": 3600}'{ "id": "drr_01hxa3b4c5d6e7f8g9h0j1k2m3", "type": "A", "name": "example.com", "value": "192.0.2.10", "ttl": 3600}PUT replaces the whole record. Without ttl it goes back to 3600 seconds.
If the record pointed at Hostup web hosting
Section titled “If the record pointed at Hostup web hosting”Moving the record off a Hostup web hosting address switches CDN proxying off for the name. The response then has "proxied": false. That switch needs write:cdn on the key. Add it before you send the PUT. Without it the PUT answers 401 although the record changed (Errors you may hit). Put the CDN in front turns proxying back on.
Keeping the domain’s email on the web hosting? Connect a domain’s email to Hostup web hosting sets its mail records.
If the record is missing
Section titled “If the record is missing”Create one record per call. Here the domain had no AAAA record.
curl -X POST "https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records" \ -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" \ -d '{"type": "AAAA", "name": "@", "value": "2001:db8::10"}'{ "id": "drr_01hxa3b4c5d6e7f8g9h0j1k2m5", "type": "AAAA", "name": "example.com", "value": "2001:db8::10", "ttl": 3600, "warnings": [ { "code": "same_name_address_records", "records": [ { "id": "drr_01hxa3b4c5d6e7f8g9h0j1k2m3", "type": "A", "name": "example.com", "value": "192.0.2.10" } ], "…": "…" } ]}warnings lists the other A and AAAA records at the name. Here it is the A record changed above, which points at the same server. If one points at the old server, change or delete it.
A new A or AAAA record at a name that shows Hostup’s parking page removes the parking record.
Creating never replaces a record. The same call creates MX, TXT, CNAME and the other record types. Create a DNS record has an example for each type. It also says what happens when you send the same record twice.
4. Check the result
Section titled “4. Check the result”List the A records again.
curl "https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records?type=A" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "zone": { "id": "zone_01hxa3b4c5d6e7f8g9h0j1k2m3", "name": "example.com", "status": "active", "recordCount": 2, "…": "…" }, "records": [ { "id": "drr_01hxa3b4c5d6e7f8g9h0j1k2m3", "type": "A", "name": "example.com", "value": "192.0.2.10", "ttl": 3600 }, { "id": "drr_01hxa3b4c5d6e7f8g9h0j1k2m6", "type": "A", "name": "www.example.com", "value": "192.0.2.10", "ttl": 3600 } ]}Ask the same with type=AAAA to check the IPv6 records.
To see what Hostup’s nameservers answer, ask one of them directly:
dig +short example.com A @primary.ns.hostup.seA proxied name answers with the CDN’s addresses instead of your server’s.
All four records with one script
Section titled “All four records with one script”The script does steps 2 and 3 for all four records. It changes each record that exists and creates each one that is missing. It needs jq and ZONE_ID from step 1.
API="https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records"
point() { # name type value BODY=$(jq -n --arg n "$1" --arg t "$2" --arg v "$3" \ '{type: $t, name: $n, value: $v, ttl: 3600}') LIST=$(curl -s "$API?type=$2&name=$1" \ -H "Authorization: Bearer $HOSTUP_API_KEY") if [ "$(echo "$LIST" | jq '.records | length')" -gt 1 ]; then echo "More than one $2 record at $1. Delete the extra ones, then run this again." return 1 fi ID=$(echo "$LIST" | jq -r '.records[0].id // empty') if [ -n "$ID" ]; then curl -s -X PUT "$API/$ID" -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" -d "$BODY" else curl -s -X POST "$API" -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" -d "$BODY" fi echo}
point @ A 192.0.2.10point @ AAAA 2001:db8::10point www A 192.0.2.10point www AAAA 2001:db8::10The script stops at a name that has more than one record of the type. Delete the extra records first. Leave out the www lines when www is a CNAME you keep. Leave out the AAAA lines when the server has no IPv6 address. Check the result as in step 4.
Put the CDN in front
Section titled “Put the CDN in front”This part is optional. With proxying on, traffic to the name reaches your server through the CDN, with its cache and security filters. Without it, traffic goes straight to the server. The key needs write:cdn on top of write:dns. Without it the record PATCH below answers 403 forbidden.
1. Check that the CDN is on for the domain
Section titled “1. Check that the CDN is on for the domain”List the domains that can use the CDN. This needs read:domains as well.
curl "https://cloud.hostup.se/api/v2/cdn/zones" \ -H "Authorization: Bearer $HOSTUP_API_KEY"{ "data": [ { "id": "cdn_01hxa3b4c5d6e7f8g9h0j1k2m3", "domain": "example.com", "domainId": "dom_01hxa3b4c5d6e7f8g9h0j1k2m3", "status": "active", "proxied": true, "…": "…" } ], "hasMore": false, "nextCursor": null}Find the entry whose domain is your domain. proxied true means the CDN is on. The list covers domains registered elsewhere too. Their domainId is null.
export CDN_ID="cdn_…" # data[].id of your domain aboveIf the CDN is off
Section titled “If the CDN is off”Turn the CDN on for the domain. This needs write:domains instead of read:domains.
curl -X PATCH "https://cloud.hostup.se/api/v2/cdn/zones/$CDN_ID" \ -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" \ -d '{"proxied": true}'{ "id": "cdn_01hxa3b4c5d6e7f8g9h0j1k2m3", "domain": "example.com", "proxied": true, "…": "…"}Update CDN zone settings explains the other settings. While the CDN is off, the record PATCH below answers 409 dns_record_proxy_blocked.
2. Turn proxying on for each record
Section titled “2. Turn proxying on for each record”These names can’t be proxied:
- a name an MX record points at
- mail names such as
mailandwebmail - names two levels below the domain, such as
a.b.example.com
curl -X PATCH "https://cloud.hostup.se/api/v2/dns-zones/$ZONE_ID/records/$RECORD_ID" \ -H "Authorization: Bearer $HOSTUP_API_KEY" \ -H "Content-Type: application/json" \ -d '{"proxied": true}'{ "id": "drr_01hxa3b4c5d6e7f8g9h0j1k2m3", "type": "A", "name": "example.com", "value": "192.0.2.10", "ttl": 3600, "proxied": true, "actions": { "canChangeProxy": { "allowed": true, "reason": null } }}Do the same for each A and AAAA record that should go through the CDN. Set RECORD_ID to that record’s ID first. {"proxied": false} turns it off again. You can also send proxied in the PUT body of step 3. A new record cannot carry it. Create the record first. Then send the PATCH.
A later PUT that changes only the address or the TTL keeps the record proxied. Moving off Hostup web hosting is the exception (step 3). Update a DNS record says what other changes do.
To see which records go through the CDN, list them with List a domain’s DNS records and the domainId from the CDN list. It shows proxied and actions.canChangeProxy for each record. It hides the records Hostup manages, such as the parking page.
What happens next
Section titled “What happens next”The record is saved when the call returns. There is no job to follow. Nothing is billed and no e-mail goes out. Hostup’s nameservers usually answer with the new record within a minute or two.
Resolvers that looked the name up before the change keep the old answer until the old record’s TTL runs out. With the default 3600 seconds, that is up to an hour. If the domain moved to Hostup’s nameservers recently, the records answer only once resolvers follow that move.
Next: Set up MX, SPF, DKIM and DMARC for a domain
Errors you may hit
Section titled “Errors you may hit”- 404
dns_zone_not_found: the zone ID does not exist. Take the ID from step 1. - 404
dns_record_not_found: the record ID is not in the zone. List the records again (step 2) and use the ID that comes back. - 409
dns_conflict: the name has a CNAME record. An A or AAAA record cannot sit next to it. Keep the CNAME if it points at your domain. Otherwise delete it and send the request again. - 400
invalid_request: the body was refused. For a TTL outside 60 to 86400, a missing field orproxiedin a create request,detailnames the field. A value the record type can’t take gets a generaldetail. The usual cause is an IPv6 address in an A record or an IPv4 address in an AAAA record. - 401
external_provider_failedon a PUT: the record pointed at Hostup web hosting and the key lackswrite:cdn. The record did change. List it (step 4) to check. Addwrite:cdnto the key before you change such a record again. - 409
dns_record_proxy_blocked: the CDN is not on for the domain. The same code comes back for a name that can’t be proxied.detailsays which. - 403
forbidden: the key lacks a scope or is limited to other DNS zones. When a key is refused