L'API des sous-domaines et des domaines
Kuploy fournit des sous-domaines *.kuploy.app gratuits pour vos applications, l'enregistrement de domaines personnalisés, et l'achat de domaines. Cette API permet aux instances kuploy-cloud de mettre en service et de gérer tout cela par programme.
Cette documentation s'adresse aux exploitants qui intègrent la mise en service de sous-domaines à leurs instances kuploy-cloud. Les utilisateurs finaux manipulent d'ordinaire les sous-domaines depuis l'interface de l'application, et non directement par cette API.
Vue d'ensemble
L'API des sous-domaines permet de :
- vérifier la disponibilité d'un sous-domaine ;
- réserver des sous-domaines pour une instance ;
- mettre en service les enregistrements DNS ;
- libérer un sous-domaine lorsqu'il n'est plus nécessaire.
L'API des domaines personnalisés permet de :
- enregistrer des domaines personnalisés sur votre licence ;
- retirer ces enregistrements ;
- lister les domaines personnalisés d'une instance.
L'API des domaines achetés permet de :
- enregistrer des domaines achetés chez un bureau d'enregistrement ;
- retirer ces enregistrements ;
- lister les domaines achetés d'une instance.
Tous les points d'accès exigent une authentification par votre clé de licence.
La configuration
Votre instance kuploy-cloud doit avoir ces variables d'environnement définies :
| Variable | Description |
|---|---|
LICENSE_HUB_URL | L'URL de base de l'instance kuploy-app (par exemple https://kuploy.app) |
LICENSE_KEY | Votre clé de licence, obtenue sur kuploy-app |
L'URL de base
L'API des sous-domaines est disponible sur :
{LICENSE_HUB_URL}/api/subdomain
Par exemple : https://kuploy.app/api/subdomain
L'authentification
Toute requête doit comporter votre LICENSE_KEY, comme champ licenseKey du corps de la requête :
{
"licenseKey": "{LICENSE_KEY}",
...
}
Les points d'accès
Vérifier la disponibilité
Vérifie si un nom de sous-domaine est libre.
POST /api/subdomain/check
Requête :
{
"name": "my-app"
}
Réponse (disponible) :
{
"available": true,
"name": "my-app",
"fqdn": "my-app.kuploy.app"
}
Réponse (indisponible) :
{
"available": false,
"name": "my-app",
"fqdn": "my-app.kuploy.app",
"error": "This subdomain is already taken"
}
Réserver un sous-domaine
Réserve un sous-domaine pour une instance. Cela ne crée pas encore d'enregistrement DNS.
POST /api/subdomain/reserve
Requête :
{
"name": "my-app",
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"success": true,
"subdomain": {
"id": "sub_xxxxxxxxxxxxxxxx",
"name": "my-app",
"fqdn": "my-app.kuploy.app",
"status": "pending"
}
}
Erreur (limite atteinte) :
{
"success": false,
"error": "Subdomain limit reached (5). Upgrade your plan for more subdomains."
}
Mettre en service l'enregistrement DNS
Crée l'enregistrement DNS effectif d'un sous-domaine réservé.
POST /api/subdomain/provision
Requête :
{
"subdomainId": "sub_xxxxxxxxxxxxxxxx",
"ipAddress": "203.0.113.50",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"success": true,
"subdomain": {
"id": "sub_xxxxxxxxxxxxxxxx",
"name": "my-app",
"fqdn": "my-app.kuploy.app",
"ipAddress": "203.0.113.50",
"status": "active"
}
}
La propagation DNS est d'ordinaire instantanée, Kuploy gérant le DNS autoritaire de kuploy.app.
Libérer un sous-domaine
Libère un sous-domaine et supprime son enregistrement DNS.
POST /api/subdomain/release
Requête :
{
"subdomainId": "sub_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"success": true,
"message": "Subdomain my-app.kuploy.app has been released"
}
Lister les sous-domaines
Liste tous les sous-domaines d'une instance.
POST /api/subdomain/list
Requête :
{
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"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"
}
]
}
L'état d'un sous-domaine
| État | Description |
|---|---|
pending | Réservé, mais le DNS n'est pas encore mis en service |
active | L'enregistrement DNS est créé et actif |
suspended | Temporairement désactivé |
released | Autrefois utilisé, désormais libre |
Les règles de nommage des sous-domaines
Un sous-domaine doit respecter ces règles :
- Longueur : de 3 à 63 caractères
- Caractères : uniquement des lettres minuscules, des chiffres et des traits d'union
- Forme : ne peut ni commencer ni finir par un trait d'union
- Unicité : doit être unique parmi tous les utilisateurs de Kuploy
Les noms réservés
Les sous-domaines suivants sont réservés et ne peuvent pas être utilisés :
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
Les codes d'erreur
| Statut HTTP | Erreur | Description |
|---|---|---|
| 400 | INVALID_SUBDOMAIN | Le nom ne respecte pas les règles de nommage |
| 400 | INVALID_IP | Le format de l'adresse IPv4 est invalide |
| 403 | LIMIT_REACHED | La limite de sous-domaines de l'offre est dépassée |
| 404 | NOT_FOUND | Le sous-domaine ou l'instance est introuvable |
| 409 | ALREADY_TAKEN | Le sous-domaine est déjà réservé par un autre utilisateur |
Un exemple d'intégration
Voici un enchaînement typique, pour mettre un sous-domaine en service :
const LICENSE_HUB_URL = process.env.LICENSE_HUB_URL;
const LICENSE_KEY = process.env.LICENSE_KEY;
// 1. Vérifier la disponibilité
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. Réserver le sous-domaine
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. Mettre le DNS en service, une fois l'adresse IP connue
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
})
});
// Le sous-domaine est désormais actif sur my-app.kuploy.app
Les limites de débit
Les requêtes à l'API sont limitées en débit, licence par licence :
| Opération | Limite |
|---|---|
| Vérifier la disponibilité | 60 par minute |
| Réserver, mettre en service, libérer | 10 par minute |
| Lister les sous-domaines | 30 par minute |
Dépasser ces limites renvoie un HTTP 429, avec un en-tête Retry-After.
L'API des domaines personnalisés
Les domaines personnalisés permettent à vos utilisateurs de rattacher leurs propres domaines — app.example.com, par exemple — à leurs applications. Ces points d'accès enregistrent et gèrent ces domaines auprès du centre de licences.
Les domaines personnalisés exigent une offre Starter ou supérieure. Une requête émise depuis l'offre Hobby renvoie une erreur 403.
L'URL de base
{LICENSE_HUB_URL}/api/custom-domain
Enregistrer un domaine personnalisé
Enregistre un domaine personnalisé pour une instance. Les interrupteurs de fonctionnalités et les limites de domaines de l'offre sont appliqués côté serveur.
POST /api/custom-domain/register
Requête :
{
"host": "app.example.com",
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse (succès) :
{
"success": true,
"customDomain": {
"id": "cd_xxxxxxxxxxxxxxxx",
"host": "app.example.com",
"status": "active"
}
}
Erreur (l'offre ne comprend pas les domaines personnalisés) :
{
"error": "Custom domains are not available on your plan. Upgrade to Starter or higher."
}
Erreur (limite atteinte) :
{
"error": "Custom domain limit reached (10). Upgrade your plan for more custom domains."
}
Retirer un domaine personnalisé
Retire l'enregistrement d'un domaine personnalisé et libère une place.
POST /api/custom-domain/remove
Requête :
{
"customDomainId": "cd_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"success": true,
"message": "Custom domain app.example.com has been removed"
}
Lister les domaines personnalisés
Liste tous les domaines personnalisés enregistrés pour une instance.
POST /api/custom-domain/list
Requête :
{
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"success": true,
"customDomains": [
{
"id": "cd_xxxxxxxxxxxxxxxx",
"host": "app.example.com",
"status": "active",
"createdAt": "2025-01-10T12:00:00Z"
}
]
}
Les codes d'erreur des domaines personnalisés
| Statut HTTP | Erreur | Description |
|---|---|---|
| 400 | INVALID_HOST | Le format du domaine est invalide |
| 403 | FEATURE_DISABLED | L'offre ne comprend pas les domaines personnalisés |
| 403 | LIMIT_REACHED | La limite de domaines personnalisés de l'offre est dépassée |
| 403 | LICENSE_SUSPENDED | La licence est suspendue |
L'API des domaines achetés
Les domaines achetés sont ceux acquis par l'intégration de la plateforme à un bureau d'enregistrement — Namecheap, par exemple. Ces points d'accès les font suivre par le centre de licences, pour l'application des limites d'offre.
L'achat de domaines exige que l'interrupteur domainPurchase soit activé — soit par votre licence de plateforme (Enterprise, par exemple), soit par l'offre souscrite par l'utilisateur (Pro ou Business, par exemple). Une requête dépourvue de cette fonctionnalité renvoie une erreur 403. L'instance kuploy-cloud applique une vérification licence d'abord, offre en recours avant d'appeler cette API. Voir Administrer les domaines — le contrôle d'accès pour le détail.
L'URL de base
{LICENSE_HUB_URL}/api/purchased-domain
Enregistrer un domaine acheté
Enregistre un domaine acquis chez le bureau d'enregistrement. L'interrupteur domainPurchase et la limite purchasableDomains sont appliqués côté serveur. L'appel est idempotent : réenregistrer le même hôte pour la même instance renvoie l'enregistrement existant.
POST /api/purchased-domain/register
Requête :
{
"host": "example.com",
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx",
"registrarId": "12345",
"expiresAt": "2027-01-15T00:00:00Z",
"autoRenew": true
}
| Champ | Obligatoire | Description |
|---|---|---|
host | Oui | Le nom du domaine acheté |
instanceId | Oui | L'instance qui possède ce domaine |
licenseKey | Oui | La clé de licence, pour l'autorisation |
registrarId | Non | L'identifiant du domaine chez le bureau d'enregistrement |
expiresAt | Non | La date d'expiration du domaine, au format ISO 8601 |
autoRenew | Non | L'activation du renouvellement automatique (par défaut : true) |
Réponse (succès) :
{
"success": true,
"purchasedDomain": {
"id": "pd_xxxxxxxxxxxxxxxx",
"host": "example.com",
"status": "active"
}
}
Erreur (fonctionnalité indisponible) :
{
"success": false,
"error": "Domain purchasing is not available on your plan. Upgrade to a plan with domain purchase enabled."
}
Erreur (limite atteinte) :
{
"success": false,
"error": "Purchased domain limit reached (10). Upgrade your plan for more purchasable domains."
}
Retirer un domaine acheté
Retire l'enregistrement d'un domaine acheté et libère une place. Cela ne résilie pas le domaine chez le bureau d'enregistrement : seul le suivi par le centre de licences disparaît.
POST /api/purchased-domain/remove
Requête :
{
"purchasedDomainId": "pd_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"success": true,
"message": "Purchased domain has been removed"
}
Lister les domaines achetés
Liste tous les domaines achetés actifs d'une instance.
POST /api/purchased-domain/list
Requête :
{
"instanceId": "inst_xxxxxxxxxxxxxxxx",
"licenseKey": "lic_xxxxxxxxxxxxxxxx"
}
Réponse :
{
"success": true,
"purchasedDomains": [
{
"id": "pd_xxxxxxxxxxxxxxxx",
"host": "example.com",
"status": "active",
"registrarId": "12345",
"expiresAt": "2027-01-15T00:00:00Z",
"autoRenew": true,
"createdAt": "2026-01-15T12:00:00Z"
}
]
}
Les codes d'erreur des domaines achetés
| Statut HTTP | Erreur | Description |
|---|---|---|
| 400 | MISSING_FIELDS | Des champs obligatoires manquent dans la requête |
| 403 | FEATURE_DISABLED | L'offre ne comprend pas l'achat de domaines |
| 403 | LIMIT_REACHED | La limite de domaines achetés de l'offre est dépassée |
| 403 | LICENSE_SUSPENDED | La licence est suspendue |
| 404 | NOT_FOUND | Le domaine ou l'instance est introuvable |