Subdomain API
Kuploy provides free *.kuploy.app subdomains for your applications. This API allows kuploy-cloud instances to provision and manage subdomains programmatically.
This documentation is for tenant operators integrating subdomain provisioning into their kuploy-cloud instances. End users typically interact with subdomains through the application UI, not directly via this API.
Overview
The subdomain API enables:
- Checking subdomain availability
- Reserving subdomains for instances
- Provisioning DNS records
- Releasing subdomains when no longer needed
All endpoints require authentication via your license key.
Configuration
Your kuploy-cloud instance should have these environment variables configured:
| Variable | Description |
|---|---|
LICENSE_HUB_URL | Base URL of the kuploy-app instance (e.g., https://kuploy.app) |
LICENSE_KEY | Your license key from kuploy-app |
Base URL
The subdomain API is available at:
{LICENSE_HUB_URL}/api/subdomain
For example: https://kuploy.app/api/subdomain
Authentication
All requests must include your LICENSE_KEY as the licenseKey in the request body:
{
"licenseKey": "{LICENSE_KEY}",
...
}
Endpoints
Check Availability
Check if a subdomain name is available.
POST /api/subdomain/check
Request:
{
"name": "my-app"
}
Response (available):
{
"available": true,
"name": "my-app",
"fqdn": "my-app.kuploy.app"
}
Response (unavailable):
{
"available": false,
"name": "my-app",
"fqdn": "my-app.kuploy.app",
"error": "This subdomain is already taken"
}
Reserve Subdomain
Reserve a subdomain for an instance. This does not create DNS records yet.
POST /api/subdomain/reserve
Request:
{
"name": "my-app",
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Response:
{
"success": true,
"subdomain": {
"id": "sub_xxxxxxxxxxxxxxxx",
"name": "my-app",
"fqdn": "my-app.kuploy.app",
"status": "pending"
}
}
Error (limit reached):
{
"success": false,
"error": "Subdomain limit reached (5). Upgrade your plan for more subdomains."
}
Provision DNS Record
Create the actual DNS record for a reserved subdomain.
POST /api/subdomain/provision
Request:
{
"subdomainId": "sub_xxxxxxxxxxxxxxxx",
"ipAddress": "203.0.113.50",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Response:
{
"success": true,
"subdomain": {
"id": "sub_xxxxxxxxxxxxxxxx",
"name": "my-app",
"fqdn": "my-app.kuploy.app",
"ipAddress": "203.0.113.50",
"status": "active"
}
}
DNS propagation is typically instant since Kuploy manages the authoritative DNS for kuploy.app.
Release Subdomain
Release a subdomain and delete its DNS record.
POST /api/subdomain/release
Request:
{
"subdomainId": "sub_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Response:
{
"success": true,
"message": "Subdomain my-app.kuploy.app has been released"
}
List Subdomains
List all subdomains for an instance.
POST /api/subdomain/list
Request:
{
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Response:
{
"success": true,
"subdomains": [
{
"id": "sub_xxxxxxxxxxxxxxxx",
"name": "my-app",
"fqdn": "my-app.kuploy.app",
"ipAddress": "203.0.113.50",
"status": "active",
"provisionedAt": "2025-01-10T12:00:00Z",
"createdAt": "2025-01-10T11:55:00Z"
}
]
}
Subdomain Status
| Status | Description |
|---|---|
pending | Reserved but DNS not yet provisioned |
active | DNS record created and live |
suspended | Temporarily disabled |
released | Previously used, now available |
Subdomain Naming Rules
Subdomains must follow these rules:
- Length: 3-63 characters
- Characters: Lowercase letters, numbers, and hyphens only
- Format: Cannot start or end with a hyphen
- Uniqueness: Must be unique across all Kuploy users
Reserved Names
The following subdomain names are reserved and cannot be used:
www, app, api, admin, mail, smtp, pop, imap, ftp, ssh,
ns1, ns2, dns, test, dev, staging, prod, production,
beta, alpha, status, help, support, docs, blog, cdn,
static, assets, media, images, img, dashboard, billing,
account, login, signup, register, auth, oauth, sso, kuploy
Error Codes
| HTTP Status | Error | Description |
|---|---|---|
| 400 | INVALID_SUBDOMAIN | Name doesn't meet naming rules |
| 400 | INVALID_IP | Invalid IPv4 address format |
| 403 | LIMIT_REACHED | Subdomain limit for plan exceeded |
| 404 | NOT_FOUND | Subdomain or instance not found |
| 409 | ALREADY_TAKEN | Subdomain already reserved by another user |
Integration Example
Here's a typical flow for provisioning a subdomain:
const LICENSE_HUB_URL = process.env.LICENSE_HUB_URL;
const LICENSE_KEY = process.env.LICENSE_KEY;
// 1. Check availability
const check = await fetch(`${LICENSE_HUB_URL}/api/subdomain/check`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'my-app' })
});
const { available } = await check.json();
if (!available) {
throw new Error('Subdomain not available');
}
// 2. Reserve the subdomain
const reserve = await fetch(`${LICENSE_HUB_URL}/api/subdomain/reserve`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: 'my-app',
instanceId: 'inst_xxx',
licenseKey: LICENSE_KEY
})
});
const { subdomain } = await reserve.json();
// 3. Provision DNS (once you know the IP)
const provision = await fetch(`${LICENSE_HUB_URL}/api/subdomain/provision`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
subdomainId: subdomain.id,
ipAddress: '203.0.113.50',
licenseKey: LICENSE_KEY
})
});
// Subdomain is now live at my-app.kuploy.app
Rate Limits
API requests are rate-limited per license:
| Operation | Limit |
|---|---|
| Check availability | 60/minute |
| Reserve/Provision/Release | 10/minute |
| List subdomains | 30/minute |
Exceeding limits returns HTTP 429 with a Retry-After header.