Cloud
banshee/cloud-collection/cloud/ovh/https/
domains
The days before expiry, the renewal and the service status of each OVHcloud domain name of an account, by the OVHcloud API.
by banshee0 installations1 version
Published on October 27, 2026. First version.
// The domain names of an OVHcloud account, by the OVHcloud API with an application's keys: for each domain, the
// days left before it expires, how it is renewed, and the status of its service.
// Reads GET <api>/domain, then for each domain GET <api>/domain/<name>/serviceInfos, each signed by ovh.sign.
need('protocol:http');
need('protocol:ovh');
$endpoint = need('protocol:ovh:endpoint');
per('domain', 'Domains');
output('days-left', 'number', array('label' => 'Before expiry', 'unit' => 'd', 'per' => 'domain'));
output('renewal', 'text', array('label' => 'Renewal', 'per' => 'domain'));
output('status', 'text', array('label' => 'Service status', 'per' => 'domain'));
watch.below('expiring', 'Domain expiring', 'days-left', array('warning' => 30, 'critical' => 7));
watch.state('not-renewed', 'Domain deleted at expiry', 'renewal', array(
'help' => 'Raises when the domain is set to be deleted at its expiry rather than renewed.',
'warning' => array('delete-at-expiration'),
));
watch.state('service', 'Domain service unpaid or expired', 'status', array('critical' => array('expired', 'unPaid', 'pendingDebt')));
watch.missing('missing', 'Domain missing', 'days-left', array('enabled' => false));
// The address of the API set on the probe, checked: https:// only, its host and its version, without a final
// slash, https://eu.api.ovh.com/1.0. The signed headers go there and nowhere else.
function ovh_api($endpoint) {
if (list.count(text.match($endpoint, '^https://[A-Za-z0-9.-]+/[0-9.]+$')) == 0) {
fail('misconfigured', 'The address of the OVHcloud API is not written https://<host>/<version>',
'For instance https://eu.api.ovh.com/1.0, https://ca.api.ovh.com/1.0 or https://api.us.ovhcloud.com/1.0.');
}
return $endpoint;
}
// One signed GET on the OVHcloud API: ovh.sign gives the headers that carry the application key, the consumer
// key and the signature; the application secret never leaves.
function ovh_get($api, $path, $what) {
$url = $api . $path;
$answer = http.get($url, headers=ovh.sign('GET', $url, ''));
if ($answer['status'] == 401) {
fail('misconfigured', 'OVHcloud refuses the keys, code 401',
'The application key, its secret or the consumer key is wrong, expired or revoked, or the clock of the poller is off.');
}
if ($answer['status'] == 403) {
fail('misconfigured', 'The consumer key may not read ' . $what . ', code 403',
'Its access rules must allow GET on the routes the documentation of the collector names.');
}
if ($answer['status'] == 400 || $answer['status'] == 404) {
fail('misconfigured', 'OVHcloud refuses to read ' . $what . ', code ' . $answer['status']);
}
if ($answer['status'] != 200) {
fail('unreachable', 'OVHcloud answers the reading of ' . $what . ' with code ' . $answer['status']);
}
return json.read($answer['body']);
}
$api = ovh_api($endpoint);
// ["example.com", …], then for each domain {"expiration": "2027-03-14", "status": "ok", "renew": {"automatic":
// true, "deleteAtExpiration": false, "forced": false, "manualPayment": false, "period": 12}, …}. expiration is a
// date without a time: it is read as midnight UTC. status is autorenewInProgress, expired, inCreation, ok,
// pendingDebt or unPaid. renew may be null, read as '': the renewal is then unknown.
$now = time.now();
foreach (ovh_get($api, '/domain', 'the domains') as $name) {
$service = ovh_get($api, '/domain/' . url.encode($name) . '/serviceInfos', 'the service of ' . $name);
$expiration = time.parse($service['expiration'] . 'T00:00:00Z', 'rfc3339');
value('days-left', number.round(($expiration - $now) / 86400, 1), $name);
$renew = list.get($service, 'renew', '');
$renewal = 'unknown';
if (list.is($renew)) {
if (list.get($renew, 'deleteAtExpiration', false)) {
$renewal = 'delete-at-expiration';
} elseif (list.get($renew, 'automatic', false)) {
$renewal = 'automatic';
} else {
$renewal = 'manual';
}
}
value('renewal', $renewal, $name);
value('status', $service['status'], $name);
}