Example: Registering a Name
This example shows how to programmatically register a .kin name via the daemon API.
Use case: Your application is a hosting service that provisions Kinetic names for users, or you want to automate name registration from a script.
The daemon handles the full registration pipeline internally as a background task: drand fetch → VDF computation → commitment broadcast → 32-second maturation → DHT publication. Your code only needs to start the task and poll for completion.
Long running — hours, not seconds
VDF computation takes 30 minutes to several hours depending on name length. The daemon's CPU will be fully loaded for this entire time. Design your application around this — use a job queue, a webhook, or a background worker. Do not block a user-facing request thread waiting for this.
One task at a time
The daemon enforces a limit of one active VDF task. Attempting to start a second returns HTTP 409. You must wait for the first to complete or fail before starting another.
TypeScript
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { Configuration, AuthenticatedApi } from '@kinetic/sdk-ts';
const tokenPath = path.join(os.homedir(), '.local', 'share', 'kinetic', 'api.token');
const token = fs.readFileSync(tokenPath, 'utf8').trim();
const config = new Configuration({
basePath: 'http://127.0.0.1:16002/api',
accessToken: token
});
const api = new AuthenticatedApi(config);
async function registerName(name: string): Promise<void> {
console.log(`Starting registration for ${name}...`);
// 1. Start the registration task in the daemon
const { task_id } = await api.vdfRegisterPost({ vdfRegisterRequest: { name } });
console.log(`Task started — ID: ${task_id}`);
console.log('The daemon is now computing the VDF. This will take a while.');
// 2. Poll every 5 minutes until done
// DO NOT poll every second — VDF progress is CPU-bound, not I/O-bound.
await pollUntilDone(task_id);
// 3. Clean up the completed task record from daemon memory
await api.vdfStatusTaskIdDelete({ taskId: task_id });
// 4. (Optional) Now update DNS records and publish the zone
// See the DNS Records example for how to do this.
console.log(`${name} is live. Edit your zone file, then call zoneNamePublishPost.`);
}
async function pollUntilDone(taskId: string): Promise<void> {
const POLL_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes
while (true) {
await sleep(POLL_INTERVAL_MS);
const task = await api.vdfStatusTaskIdGet({ taskId });
console.log(`[${task.status}] progress: ${task.progress}%`);
// The daemon uses exactly "Complete" (capital C) — never "completed"
if (task.status === 'Complete') {
console.log('Registration complete!');
return;
}
if (task.status === 'Failed') {
throw new Error(`Registration failed: ${task.error ?? 'unknown error'}`);
}
// Any other status means it is still running — keep polling
}
}
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Run
registerName('mycoolapp.kin').catch(console.error);Status string values
The task.status field is a human-readable string from the daemon. The only two terminal values are:
"Complete"— success, name is live on the network"Failed"— checktask.errorfor the reason
All other values ("Initializing", "Computing VDF...", etc.) mean the task is still running.
Rust
use std::fs;
use std::time::Duration;
use tokio::time::sleep;
use kinetic_sdk::apis::configuration::Configuration;
use kinetic_sdk::apis::authenticated_api;
use kinetic_sdk::models::VdfRegisterRequest;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read bearer token
let home = std::env::var("HOME")?;
let token = fs::read_to_string(format!("{}/.local/share/kinetic/api.token", home))?
.trim()
.to_string();
let mut config = Configuration::new();
config.base_path = "http://127.0.0.1:16002/api".to_string();
config.bearer_access_token = Some(token);
let name = "mycoolapp.kin";
// 1. Start the registration task
println!("Starting registration for {}...", name);
let req = VdfRegisterRequest { name: name.to_string() };
let task = authenticated_api::vdf_register_post(&config, req).await?;
let task_id = task.task_id;
println!("Task started — ID: {}", task_id);
// 2. Poll every 5 minutes
loop {
sleep(Duration::from_secs(5 * 60)).await;
let status = authenticated_api::vdf_status_task_id_get(&config, &task_id).await?;
println!("[{}] progress: {}%", status.status, status.progress);
// Exact string comparison — daemon uses "Complete" with capital C
if status.status == "Complete" {
println!("Registration complete! {} is live.", name);
// Clean up the task record
authenticated_api::vdf_status_task_id_delete(&config, &task_id).await?;
break;
}
if status.status == "Failed" {
let reason = status.error.unwrap_or_else(|| "unknown".to_string());
return Err(format!("Registration failed: {}", reason).into());
}
// Otherwise: still running, keep polling
}
Ok(())
}After Registration
When the task reaches "Complete", the name is registered with an empty DNS zone. To make the name actually resolve to something useful:
- Update the DNS zone via the API (see Publish DNS Records example)
- Or edit the zone file directly:
~/.local/share/kinetic/zones/mycoolapp.kin.json - Then call
zoneNamePublishPostto push the updated zone to the DHT
Application Design Notes
Because registration takes hours, do not build a synchronous flow around it. Instead:
- Store the
task_idin a database when you start registration - Background worker polls the status periodically and updates the record when done
- Notify the user via email, webhook, or push when the name is live
- Limit one active registration per daemon — if you need to register many names, queue them and process one at a time