Registration
Register, transfer and renew domains, and check the owner details the registry needs.
Registering, transferring and renewing a domain charge your wallet. Prices are the ones in the price list, VAT included. WHOIS protection is priced the same everywhere: the whois_protection price, currently Rp 20,000 per year.
Owner details
The registry needs real owner (registrant) details for every domain. Helipod never sends placeholder data, so registration and transfer are refused until these fields are filled in your account:
| Field | Label in messages |
|---|---|
name | nama |
phone | nomor telepon |
addressLine1 | alamat |
city | kota |
state | provinsi |
countryCode | negara |
postalCode | kode pos |
Organization is optional (the name is used when it is empty). Set them once with PATCH /domains/registrant or in the Helipod dashboard. The current details are used for every new registration or transfer, so edits apply to domains you add afterwards.
/domains/registrantcurl https://api.helipod.io/api/domains/registrant \
-H "Authorization: Bearer hel_your_key"{
"success": true,
"data": { "complete": false, "missing": ["phone", "postalCode"] }
}missing lists the field names from the table above. It is empty when complete is true.
Set owner details
/domains/registrantProp
Type
curl -X PATCH https://api.helipod.io/api/domains/registrant \
-H "Authorization: Bearer hel_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Ana Putri",
"phone": "+6281234567890",
"addressLine1": "Jl. Sudirman No. 1",
"city": "Jakarta Selatan",
"state": "DKI Jakarta",
"countryCode": "ID",
"postalCode": "12190"
}'{
"success": true,
"data": {
"complete": true,
"missing": [],
"updated": ["name", "phone", "addressLine1", "city", "state", "countryCode", "postalCode"]
}
}The response never repeats the details themselves: updated names the fields you sent, and complete and missing say what is still needed. An empty body answers 422 VALIDATION_ERROR; a value the profile rejects answers 400 INVALID_REGISTRANT. Once the details are complete, any pending profile domain from a purchase is registered for you.
Check the price first
Register, transfer and renew accept ?dryRun=true. Nothing is charged or sent to the registry; the response shows the price and your wallet after it:
curl -X POST "https://api.helipod.io/api/domains/register?dryRun=true" \
-H "Authorization: Bearer hel_your_key" \
-H "Content-Type: application/json" \
-d '{ "name": "example.com", "period": 1, "whoisProtection": true }'{
"success": true,
"data": {
"dryRun": true,
"price": 219000,
"currency": "IDR",
"billing": { "ppn": 21703, "registration": 199000, "whoisProtection": 20000, "total": 219000 },
"walletBalance": 500000,
"walletBalanceAfter": 281000,
"enoughBalance": true
}
}A dry run makes the same checks as the real call (supported extension, name free, owner details complete), so it fails with the same codes. billing has the same fields as the real call's billing, without depositCharged; a transfer has ppn and charged, and a renewal also returns the domain and its current expiresAt.
Supported extensions
New registrations and transfers are accepted for these extensions:
.com .id .dev .app .net .in .biz .link .biz.id .my.id .web.id .ai.id
Any other extension returns 400 TLD_NOT_SUPPORTED. Subdomains (for example shop.example.com) cannot be registered.
Register a domain
/domains/registercharges your walletdryRunProp
Type
curl -X POST https://api.helipod.io/api/domains/register \
-H "Authorization: Bearer hel_your_key" \
-H "Content-Type: application/json" \
-d '{
"name": "example.com",
"period": 1,
"nameservers": ["ns1.example-dns.net", "ns2.example-dns.net"],
"whoisProtection": false
}'{
"success": true,
"data": {
"name": "example.com",
"status": 1,
"status_label": "Active",
"nameserver_1": "ns1.example-dns.net",
"nameserver_2": "ns2.example-dns.net",
"expired_at": "2027-10-16 00:00:00",
"created_at": "2026-10-16 09:12:44"
},
"billing": {
"ppn": 18730,
"registration": 199000,
"whoisProtection": 0,
"total": 199000,
"depositCharged": 199000
}
}data describes the registration as reported by the registry (name, status, nameservers, expiry). It does not contain the Helipod domain id: call GET /domains/mine to get the id used by every other endpoint.
billing field | Description |
|---|---|
ppn | VAT included in registration. |
registration | One-year registration price, VAT included. |
whoisProtection | Amount added for WHOIS protection (the whois_protection price), 0 when not requested. |
total | Total charged to your wallet. |
depositCharged | Amount taken from your deposit balance (equal to total). |
special_price | true when the extension's special price was applied. |
promo | Name of the promotion applied, when one was running. |
What is checked, in order
- The name is not premium (
400 PREMIUM_NOT_SUPPORTEDwhenincludePremiumistrue). - The extension is supported (
400 TLD_NOT_SUPPORTEDotherwise). periodis1(422 VALIDATION_ERRORotherwise).- The name is not already held:
409 DOMAIN_UNAVAILABLEwhen it belongs to another account,409 DOMAIN_ALREADY_IN_ACCOUNTwhen it is already in yours. Your own pending profile domain or failed transfer for the same name can be registered. - A valid price exists for the extension (
400 PRICE_UNAVAILABLEotherwise). - Your owner details are complete (
400 REGISTRANT_INCOMPLETE, with amissinglist). - Your wallet balance covers the total (
402 INSUFFICIENT_BALANCEotherwise).
Nothing is charged when one of these fails. After the charge, the request goes to the registry. If the registry rejects it (for example the name was taken in the meantime, or it is a premium name), the response is 422 REGISTRAR_REJECTED; if the registry cannot be reached, it is 502 REGISTRAR_ERROR. In both cases the full amount is refunded to your wallet.
If the registry registered the domain but Helipod could not record it, the response is still 201, with code: "DOMAIN_SAVE_PENDING" and a message asking you to contact support. The domain is yours and nothing is refunded; do not retry. See Delivered but not yet recorded.
{
"success": false,
"error": "Lengkapi data pemilik domain dulu: nomor telepon, kode pos",
"code": "REGISTRANT_INCOMPLETE",
"missing": ["phone", "postalCode"]
}Search the name first. A registration for a name that is not available is refused and refunded, but you still spend a request.
Transfer a domain
/domains/transfercharges your walletdryRunProp
Type
curl -X POST https://api.helipod.io/api/domains/transfer \
-H "Authorization: Bearer hel_your_key" \
-H "Content-Type: application/json" \
-d '{ "name": "example.net", "authCode": "Xy7#k2Lp9q", "period": 1 }'{
"success": true,
"data": {
"name": "example.net",
"status": 5,
"status_label": "Pending Transfer",
"nameserver_1": "ns1.example-dns.net",
"nameserver_2": "ns2.example-dns.net"
},
"billing": {
"ppn": 20216,
"charged": 214000,
"depositCharged": 214000
}
}With "whoisProtection": true the response also carries a notice:
{
"notice": "WHOIS protection is not included in a transfer. Enable it from the domain page once the transfer is complete."
}- Only the supported extensions can be transferred (
400 TLD_NOT_SUPPORTED). periodmust be1(400 PERIOD_NOT_SUPPORTED).- Your owner details must be complete (
400 REGISTRANT_INCOMPLETE, with amissinglist). - The name must not already be held:
409 DOMAIN_UNAVAILABLEor409 DOMAIN_ALREADY_IN_ACCOUNT. - WHOIS protection is not included. Enable it once the transfer is complete.
- The charge is the extension's one-year
transferprice from the price list (billing.charged).402 INSUFFICIENT_BALANCEwhen the balance is too low. Nothing is charged when one of these checks fails. - Before you start, unlock the domain at your current registrar and get its auth code.
- A wrong auth code or a locked domain is refused by the registry:
422 REGISTRAR_REJECTED, and the charge is refunded. A registry outage is502 REGISTRAR_ERROR, also refunded. - If the transfer was accepted but Helipod could not record it, the response is
201withcode: "DOMAIN_SAVE_PENDING". Contact support and do not retry.
The domain appears in GET /domains/mine with status pending_transfer. Its status is synced from the registry when you list or read your domains, and once a day, so it becomes active on its own when the transfer completes (or transfer_failed if it does not).
Renew a domain
/domains/{id}/renewcharges your walletdryRun{id} is the domain id from GET /domains/mine.
Prop
Type
curl -X POST https://api.helipod.io/api/domains/42/renew \
-H "Authorization: Bearer hel_your_key" \
-H "Content-Type: application/json" \
-d '{ "period": 1 }'{
"success": true,
"message": "Domain renewed for 1 year(s)",
"data": { "expiresAt": "2028-10-16T00:00:00.000Z" },
"billing": {
"ppn": 20216,
"renewal": 214000,
"whoisProtection": 0,
"total": 214000,
"depositCharged": 214000
}
}- The charge is the one-year
renewalprice, plus thewhois_protectionprice when protection is enabled on the domain. data.expiresAtis the new expiry date. It is never earlier than the previous one.- While the renewal runs, the domain's status is
renewing; a second renewal of the same domain answers409 RENEW_IN_PROGRESSand charges nothing. 402 INSUFFICIENT_BALANCEwhen the balance is too low,400 DOMAIN_NOT_LINKEDwhen the domain is not active at the registry yet (nothing charged in either case).- If the registry refuses the renewal, you get
422 REGISTRAR_REJECTED; if it cannot be reached,502 REGISTRAR_ERROR. The charge is refunded in both cases. - If the renewal went through but Helipod could not record it, the response is
200withcode: "DOMAIN_SAVE_PENDING"and amessageasking you to contact support. Do not retry.
Auto-renew
Domains with autoRenew: true (see GET /domains/mine) are renewed automatically:
- The check runs every day at 09:00 WIB.
- A domain that expires within the next 7 days is renewed for 1 year.
- The charge is the same as a manual renewal: the normal
renewalprice, plus thewhois_protectionprice when protection is on, taken from your wallet. - If the wallet cannot cover it, the domain is not renewed and you get a notification in the dashboard. The next day's run tries again, every day until the domain is renewed or a few days past its expiry.
- A domain is never renewed twice for the same period, even when you also renew it by hand.
Top up your wallet before the 7 day window to make sure your domains renew on time.
Pending profile domains
A free domain that comes with a purchase (for example a VPS bundle) is created with status pending_profile when your owner details are not complete yet. It is reserved for you but not registered at the registry.
- It is listed by
GET /domains/mineand readable withGET /domains/{id}. The list includesbonusDeadline: the date by which it must be activated. - Every other endpoint on that domain (renew, DNS, nameservers, WHOIS protection, child nameservers) returns
409:
{
"success": false,
"error": "Domain ini belum aktif: lengkapi data pemilik domain untuk mengaktifkannya.",
"code": "DOMAIN_PENDING_PROFILE"
}To activate it, complete your owner details with PATCH /domains/registrant or in the Helipod dashboard before bonusDeadline. After the deadline the reservation is released and the domain disappears from your list.