Skip to content

Prepare or check CDN setup

POST /api/v2/cdn/zones/{id}

Runs one CDN setup step for a zone. Send one action and no other fields, except hostnames with prepare_partial. The domain must be active. Otherwise the call returns 404 cdn_zone_not_found. Every step returns the full zone, as from GET /api/v2/cdn/zones/{id}.

There are two ways to put a domain behind the CDN.

Move to Hostup’s nameservers. While actions.canPrepareNameservers is allowed, Hostup’s nameservers do not answer for the zone yet. A nameserver change at that point takes the domain offline. Send prepare_nameservers first. It queues the zone on Hostup’s nameservers and never changes the domain’s nameservers. Publication runs in the background. Read GET /api/v2/cdn/zones/{id} every few seconds until actions.canPrepareNameservers.allowed is false. Then switch the domain to setup.expectedNameservers. For a domain registered with Hostup, use POST /api/v2/domains/{id}/nameservers. For a domain registered elsewhere, set them at that registrar. Repeating the step is safe. A zone that uses external DNS setup returns 409.

Keep your external DNS. prepare_partial prepares the zone and returns an ownership TXT record in setup.verification and one CNAME or ALIAS record per hostname in setup.routing. To choose the hostnames, send hostnames: 1 to 50 names at or below the zone, without wildcards, URL schemes or paths. It changes nothing at your DNS provider. Publish exactly the returned records there. An apex record needs ALIAS or CNAME flattening support at that provider. Then send check_partial to recheck verification, routing and the certificate.

HTTP 200 means the step ran, not that the CDN is live. pending_verification, pending_routing and pending_certificate name the work still open. Only setup.status: active means traffic and HTTPS run through the CDN. Settings such as proxying and security are changed with PATCH /api/v2/cdn/zones/{id}.

Authentication: An API key with the scopes write:cdn and write:domains. About keys and scopes

Request

Path parameters

idstringrequired
The CDN zone ID. From GET /api/v2/cdn/zones.

Body

actionstringrequired
Prepare the setup with your own DNS for the selected zone. One of prepare_partial.
hostnamesarray of string
Full hostnames equal to the zone or below it. Leave it out for the apex and www. Send 1 to 50 entries. Duplicates are merged. Wildcards, URL schemes and paths are rejected. Case, IDNs and a trailing dot are normalized. The current origins are read from your DNS records.

Example

POST /api/v2/cdn/zones/{id}
curl -X POST "https://cloud.hostup.se/api/v2/cdn/zones/cdn_01hxa3b4c5d6e7f8g9h0j1k2m3" \
-H "Authorization: Bearer $HOSTUP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action": "prepare_partial"
}'

Responses

200 The zone after the step. A pending setup state or an open canPrepareNameservers gate is a normal result.

{
"id": "cdn_01hxa3b4c5d6e7f8g9h0j1k2m3",
"domain": "example.com",
"domainId": "dom_01hxa3b4c5d6e7f8g9h0j1k2m3",
"status": "pending",
"reason": "Add the verification TXT record at your DNS provider.",
"proxied": false,
"securityLevel": "medium",
"ssl": {
"status": "pending",
"expiresAt": null
},
"ruleCount": 2,
"security": {
"level": "medium",
"sslMode": "full",
"alwaysUseHttps": true,
"minTlsVersion": "1.2",
"botProtection": true,
"blockBadCrawlers": true,
"blockBadBots": true,
"wpLoginProtection": true,
"wpAdminChallenge": true,
"blockedCrawlers": []
},
"performance": {
"earlyHints": true,
"alwaysOnline": true
},
"cache": {
"purgeCache": false
},
"waf": {
"skipEnabled": false,
"challengeGeoEnabled": true,
"visitorProfileMode": "challenge",
"ipAllowlist": [
"198.51.100.10"
],
"uaAllowlist": [
"ExampleMonitor/1.0"
],
"pathAllowlist": [
"/health"
],
"uaBlocklist": [],
"ipBlocklist": []
},
"geoRestriction": {
"enabled": true,
"whitelistCountries": [
"SE"
],
"mode": "whitelist",
"standardCountries": [],
"additionalCountries": [
"SE"
],
"combinedCountries": [
"SE"
]
},
"activity": {
"lastChangeDetectedAt": "2026-04-27T12:00:00.000Z",
"lastCheckedAt": "2026-04-27T12:00:00.000Z",
"settingsUpdatedAt": "2026-04-27T12:00:00.000Z"
},
"actions": {
"canEnableProxy": {
"allowed": false,
"reason": "Add the verification TXT record at your DNS provider."
},
"canIssueCertificate": {
"allowed": true,
"reason": null
},
"canChangeMode": {
"allowed": true,
"reason": null
},
"canActivate": {
"allowed": false,
"reason": "Add the verification TXT record at your DNS provider."
},
"canDeactivate": {
"allowed": false,
"reason": "CDN is not active for this domain."
},
"canPreparePartial": {
"allowed": false,
"reason": "External DNS setup is already prepared. Check its current status."
},
"canCheckPartial": {
"allowed": true,
"reason": null
},
"canPrepareNameservers": {
"allowed": false,
"reason": "External DNS setup is prepared for this domain."
}
},
"records": null,
"setup": {
"mode": "partial",
"status": "pending_verification",
"reason": "Add the verification TXT record at your DNS provider.",
"verification": {
"type": "TXT",
"name": "cdn-verification.example.com",
"value": "example-verification-value",
"status": "pending"
},
"routing": [
{
"hostname": "www.example.com",
"currentOrigin": [
{
"type": "A",
"value": "198.51.100.10"
}
],
"record": {
"type": "CNAME",
"name": "www.example.com",
"value": "www.example.com.cdn.example.net"
},
"status": "pending",
"reason": null
}
],
"certificate": {
"status": "pending",
"hosts": []
},
"checkedAt": "2026-04-27T12:00:00.000Z",
"currentNameservers": [
"ns1.example.net",
"ns2.example.net"
],
"expectedNameservers": [
"primary.ns.hostup.se",
"secondary.ns.hostup.se"
],
"registrarRelation": "hostup",
"nameserverManagementUrl": "/domains/example.com?tab=nameservers"
}
}
Response fields
setupobject
How the CDN is set up for the zone: with Hostup’s nameservers or with your own DNS. Read status and reason as returned. A prepared partial setup is not active until the verification, the routing and the HTTPS certificate are confirmed. Copy the DNS names and values as returned. Don’t build them yourself.
modestring
full: the domain uses Hostup’s nameservers. partial: your own DNS stays authoritative and chosen hostnames are routed through the CDN. currentNameservers shows the nameservers seen now. One of full, partial, unknown.
statusstring
Overall readiness. A pending_… status names the next setup step. unavailable means the state could not be read. It does not mean that DNS or the certificate is wrong. One of not_configured, pending_verification, pending_routing, pending_certificate, active, unavailable.
reasonstring or null
The setup state in words. Null when nothing needs explaining.
verificationobject or null
The TXT record that proves ownership, to publish at your DNS provider. Null when none is needed or available. Copy the name and value exactly.
routingarray of object
The chosen hostnames with the origin values kept when the setup was prepared. Each row has the DNS change it needs at your DNS provider. Publish the routing record without other, conflicting record types at the same name. A row with status: unsupported is not set up.
hostnamestring
currentOriginarray of object
typestring
One of A, AAAA, CNAME.
valuestring
recordobject or null
The exact routing record to publish at your DNS provider. Null when none is available. Use ALIAS only when your provider supports a flattened alias at the zone apex. Don’t replace an apex with a plain CNAME when that conflicts with the other records at the apex.
statusstring
One of pending, verified, unsupported, unknown.
reasonstring or null
certificateobject
statusstring
One of active, pending, error, unknown.
hostsarray of string
Hostnames on the CDN’s HTTPS certificate.
checkedAtstring or null
When the setup was last checked, in UTC. Null when unknown.
currentNameserversarray of string
expectedNameserversarray of string
Hostup’s nameservers, for a full setup. A partial setup does not need them.
registrarRelationstring
Where the registration of the domain is managed. It does not depend on the CDN setup mode. One of hostup, external, unknown.
nameserverManagementUrlstring or null
Link to change the nameservers in the client area, when the domain is registered with Hostup. Otherwise null. To use Hostup’s nameservers then, set expectedNameservers at your registrar.
idstring or null
The CDN zone ID (cdn_…). Set even before the CDN is set up. Null only when the zone cannot be identified.
domainstring
domainIdstring or null
The domain ID (dom_…) for a domain registered with Hostup. null for a DNS-only zone.
statusstring
One of active, pending, misconfigured, missing, disabled.
reasonstring or null
proxiedboolean
securityLevelstring
One of off, low, medium, high.
sslobject
statusstring
One of active, pending, error.
expiresAtstring or null
ruleCountinteger
securityobject
levelstring
Overall CDN security level. One of off, low, medium, high.
sslModestring
The TLS mode between visitors, the CDN and your origin server. One of off, flexible, full, strict.
alwaysUseHttpsboolean
minTlsVersionstring
One of 1.0, 1.1, 1.2, 1.3.
botProtectionboolean
blockBadCrawlersboolean
blockBadBotsboolean
wpLoginProtectionboolean
Protect the WordPress login pages.
wpAdminChallengeboolean
Challenge requests to the WordPress admin paths.
blockedCrawlersarray of string
Crawler catalogue IDs that are blocked before every other rule, verified-bot exemptions included. Examples: baiduspider, gptbot, claudebot, ahrefsbot. Lowercase IDs only. The crawler catalogue has the full list. Empty unless crawlers were chosen. Separate from blockBadCrawlers, the general check for bad crawlers.
performanceobject
earlyHintsboolean
alwaysOnlineboolean
cacheobject
purgeCacheboolean
The saved cache-purge setting.
wafobject
skipEnabledboolean
Whether your own WAF skip rules are on.
challengeGeoEnabledboolean
Whether the country challenge of the visitor profile is on.
visitorProfileModestring
challenge: visitors from outside the allowed countries must pass a challenge. block: they are blocked. off: the visitor profile does nothing. One of off, challenge, block.
ipAllowlistarray of string
IP addresses or CIDR ranges that skip the custom WAF checks.
uaAllowlistarray of string
User-agent substrings that skip the custom WAF checks.
pathAllowlistarray of string
Path prefixes that skip the custom WAF checks.
uaBlocklistarray of string
User-agent substrings that are blocked before every allowlist and verified-bot exemption. Entries equal to or contained in ordinary browser tokens, such as Mozilla, Chrome or bot, are rejected with invalid_request. They would block ordinary visitors.
ipBlocklistarray of string
IPv4 or IPv6 addresses or CIDR ranges that are blocked before every allowlist and verified-bot exemption.
geoRestrictionobject
enabledboolean
whitelistCountriesarray of string
Older field with the allowed country codes, in capitals. Use combinedCountries instead.
modestring
off: no country limit. whitelist: only the countries in combinedCountries are allowed. One of off, whitelist.
standardCountriesarray of string
Countries that are always allowed. You cannot remove them.
additionalCountriesarray of string
Country codes you added on top of standardCountries.
combinedCountriesarray of string
The allowed countries: standardCountries plus additionalCountries.
activityobject
lastChangeDetectedAtstring or null
lastCheckedAtstring or null
settingsUpdatedAtstring or null
actionsobject
canEnableProxyobject
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
canIssueCertificateobject
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
canChangeModeobject
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
canActivateobject
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
canDeactivateobject
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
canPreparePartialobject
Whether you can prepare a setup with your own DNS. The request also checks the current delegation. A full setup that is delegated now cannot be converted with this action.
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
canCheckPartialobject
Whether an existing partial setup can be checked now.
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
canPrepareNameserversobject
Whether the zone still has to be published on Hostup’s nameservers before you switch the domain to them. Allowed while it is not published there. Then send prepare_nameservers to POST /api/v2/cdn/zones/{id}. Read the zone until this gate closes. Only then change the nameservers. Not allowed when the zone is already published, when it uses your own DNS or when readiness was not checked.
allowedboolean
reasonstring or null
codestring or null
A machine-readable code for why the action is blocked.
recordsarray of any or null
null unless you send includeRecords=true.

Errors

Errors are Problem Details with a stable code. Branch on the code, not on the text.

400The action is missing or unknown, hostnames is invalid or the body has other fields.
401Unauthorized. Authentication is required.
403Forbidden. The caller lacks a required scope or does not own the resource.
404No CDN zone with this ID on the account. The domain may also not be active.
409prepare_nameservers does not apply. Either the zone uses external DNS setup or another account holds the domain’s DNS zone.
429Rate limited. Retry after the limit resets. 429 responses include Retry-After seconds plus X-RateLimit-* headers.
500Internal error. Retry later or contact support if the issue persists.
502The setup step returned no usable result. Read the zone before you retry.
503The setup step cannot run right now. Try again later.