Plonki

Endpoints

Base URL https://plonki.com.au/v1. JSON bodies. Prices in AUD cents. Machine-readable version: /openapi.json.

GET/account
GET/prices
GET/domains/search
POST/domains/search
GET/domains/suggest
POST/domains
GET/domains
GET/domains/{domain}
POST/domains/{domain}/renew
PUT/domains/{domain}/nameservers
POST/domains/{domain}/point
GET/domains/{domain}/dns
POST/domains/{domain}/dns
DELETE/domains/{domain}/dns/{id}
GET/domains/{domain}/transfer-code
POST/transfers/check
POST/transfers
PUT/domains/{domain}/lock
GET/domains/{domain}/email-forwards
POST/domains/{domain}/email-forwards
DELETE/domains/{domain}/email-forwards/{id}
GET/domains/{domain}/url-forwards
POST/domains/{domain}/url-forwards
DELETE/domains/{domain}/url-forwards/{id}
GET/orders
GET/orders/{id}
GET/contacts
POST/contacts
POST/billing/topup

Account and prices

GET/account

Your account, mode and balance

See Authentication for the response.

GET/prices

Price per extension

Query tld (optional) filters to one extension, e.g. ?tld=com.au. Prices are per year for your account's plan.

json
{
  "currency": "AUD",
  "unit": "cents_per_year",
  "prices": [
    { "tld": "com.au", "currency": "AUD", "register": 2399, "renew": 2399, "min_years": 1, "max_years": 5 },
    { "tld": "com", "currency": "AUD", "register": 3399, "renew": 3399, "min_years": 1, "max_years": 10 }
  ]
}

Search

POST/domains/search

Check availability (JSON body)

FieldTypeDescription
querystringA domain (acme.com) or a name/phrase (Acme Coffee). Phrases are checked across popular extensions.
up to 200 chars
domainsarray of stringExact domains to check, up to 50
tldsarray of stringExtensions to try for a phrase, e.g. ['com','io','com.au']

GET/domains/suggest

Available domain ideas from keywords

FieldTypeDescription
keywords
required
stringWhat the site is about, e.g. 'dog grooming melbourne'
up to 200 chars
tldsarray of string
limitinteger
1 to 30, default 10
shell
curl "https://plonki.com.au/v1/domains/suggest?keywords=dog+grooming+melbourne&limit=5" \
  -H "Authorization: Bearer $PLONKI_KEY"
json
{
  "suggestions": [
    { "domain": "doggrooming.com.au", "available": true, "premium": false, "currency": "AUD",
      "price": { "register": 2399, "renew": 2399, "min_years": 1 } }
  ]
}

Only available names are returned, cheapest first, then shortest. Pass these as query parameters (tlds comma-separated).

Register and renew

POST/domains

Register a domain

Send an Idempotency-Key header (or idempotency_key in the body). Retrying with the same key returns the original order.

FieldTypeDescription
domain
required
stringThe domain to register, e.g. acme.com
yearsinteger
1 to 10, default 1
max_priceintegerMost you will pay, in AUD cents, for the whole order. Use total from search/quote. Order fails if the price is higher.
contact_idstringSaved registrant contact. Defaults to the account's default contact.
contactobjectRegistrant details, if there's no saved contact. Saved for next time.
contact.first_name
required
string
up to 60 chars
contact.last_name
required
string
up to 60 chars
contact.organisationstring
up to 120 chars
contact.email
required
email
contact.phone
required
stringMobile, e.g. 0412 345 678, +61 412 345 678 or +61.412345678
contact.address1
required
string
up to 120 chars
contact.address2string
up to 120 chars
contact.city
required
string
up to 60 chars
contact.state
required
stringFor Australia use the abbreviation: NSW, VIC, QLD, SA, WA, TAS, ACT, NT
up to 60 chars
contact.postcode
required
string
up to 12 chars
contact.country
required
stringISO 3166-1 alpha-2, e.g. AU, US, GB
up to 2 chars
au_eligibilityobjectRequired for .com.au, .net.au, .org.au, .id.au and .au names (auDA rules)
au_eligibility.registrant_name
required
stringLegal name of the registrant (company or person)
up to 255 chars
au_eligibility.registrant_id
required
stringABN, ACN or other ID number, digits only
up to 50 chars
au_eligibility.registrant_id_type
required
"ABN" | "ACN" | "OTHER"OTHER covers state business registration numbers and incorporated associations
au_eligibility.eligibility_type
required
string (see list)Entity type. Most businesses are 'Company' (Pty Ltd), 'Sole Trader' or 'Registered Business'. .id.au only allows 'Citizen/Resident'.
au_eligibility.eligibility_namestringTrading or business name the domain is based on, if different from registrant_name
up to 255 chars
au_eligibility.eligibility_idstringID that backs eligibility_name (e.g. a trademark number or state business number)
up to 50 chars
au_eligibility.eligibility_id_typestring (see list)
nameserversarray of stringCustom nameservers. Leave empty to use Plonki DNS (needed for the DNS tools).
payment"auto" | "balance" | "checkout"auto: use balance, or return a pay link if it's short. checkout: always return a pay link.
default "auto"
idempotency_keystringSame key returns the same order instead of buying twice
up to 100 chars
external_refstringYour own reference, e.g. your customer's ID
up to 200 chars

Responses:

201status: "completed". Paid from the balance and registered.
202awaiting_payment (send the payer to checkout_url) or processing (the registry is slow; poll the order).
400contact_required, au_eligibility_required, invalid_years, validation_error…
402insufficient_balance (only with payment: "balance").
409domain_unavailable or price_changed.

The order object is described under GET /orders/{id}. Full walkthrough: Register a domain.

POST/domains/{domain}/renew

Renew a domain

FieldTypeDescription
yearsinteger
1 to 10, default 1
max_priceinteger
payment"auto" | "balance" | "checkout"
default "auto"
idempotency_keystring
up to 100 chars

Returns an order, like registration. Renewal is priced at the extension's renew price.

Domains

GET/domains

Domains in your account

Query external_ref (optional) returns only domains tagged with that reference, e.g. one of your customers.

json
{
  "domains": [
    {
      "id": "dom_7q2w9e4r1t8y3u5i6o0p",
      "domain": "acmecoffee.com.au",
      "status": "active",
      "expires_at": "2027-11-08T01:23:45.000Z",
      "nameservers": ["ns1.nameserver.net.au", "ns2.nameserver.net.au", "ns3.nameserver.net.au"],
      "dns_managed_by_plonki": true,
      "auto_renew": false,
      "external_ref": "cust_8271",
      "test_mode": false
    }
  ]
}

GET/domains/{domain}

One domain, refreshed from the registry

Same fields as the list, plus registry_status (e.g. ok, clientTransferProhibited) and transfer_lock (null for .au, which has no lock).

GET/domains/{domain}/transfer-code

EPP / auth code to move the domain elsewhere

json
{ "domain": "acmecoffee.com", "auth_code": "Xy7#p2Lq9!" }

DNS and nameservers

POST/domains/{domain}/point

Point the domain at a website

FieldTypeDescription
target
required
stringWhere the site is hosted: an IPv4 address (76.76.21.21) or a hostname (myapp.vercel.app, myapp.pages.dev, myapp.netlify.app)
include_wwwboolean
default true
json
{
  "domain": "acmecoffee.com.au",
  "host": "Vercel",
  "records_created": [
    { "id": "1794051896320550", "name": "@", "type": "A", "content": "76.76.21.21", "ttl": 3600 },
    { "id": "1794051896321831", "name": "www", "type": "CNAME", "content": "acmecoffee.vercel.app", "ttl": 3600 }
  ],
  "records_replaced": 0,
  "next_steps": [
    "In Vercel: Project, Settings, Domains, add the domain.",
    "DNS changes usually take a few minutes, sometimes up to an hour."
  ]
}

Existing A, AAAA and CNAME records on @ and www are replaced. Hosts and the records used: Connect to your host.

PUT/domains/{domain}/nameservers

Use another DNS provider, or come back to Plonki DNS

FieldTypeDescription
nameservers
required
array of stringHostnames, e.g. ['ns1.vercel-dns.com','ns2.vercel-dns.com']. Send an empty array to switch back to Plonki DNS.
json
{ "domain": "acmecoffee.com", "nameservers": ["ada.ns.cloudflare.com", "bob.ns.cloudflare.com"], "dns_managed_by_plonki": false }

While custom nameservers are set, Plonki's DNS endpoints return dns_not_hosted. Send an empty list to switch back.

GET/domains/{domain}/dns

DNS records

json
{
  "domain": "acmecoffee.com.au",
  "records": [
    { "id": "1794051896320550", "name": "@", "type": "A", "content": "76.76.21.21", "ttl": 3600 },
    { "id": "1794051896329911", "name": "@", "type": "MX", "content": "smtp.google.com", "ttl": 3600, "priority": 1 }
  ]
}

POST/domains/{domain}/dns

Add a DNS record

FieldTypeDescription
namestringHost label: '@' for the root, 'www', 'api', etc.
default "@"
type
required
"A" | "AAAA" | "CNAME" | "MX" | "TXT" | "SRV" | "CAA" | "NS"
content
required
string
up to 2048 chars
ttlinteger
300 to 86400, default 3600
priorityintegerMX and SRV only
0 to 65535

Types: AAAAACNAMEMXTXTSRVCAANS. MX and SRV default to priority 10. Recipes: DNS records.

shell
curl https://plonki.com.au/v1/domains/acmecoffee.com.au/dns \
  -H "Authorization: Bearer $PLONKI_KEY" -H "Content-Type: application/json" \
  -d '{"name": "@", "type": "TXT", "content": "google-site-verification=abc123"}'

DELETE/domains/{domain}/dns/{id}

Delete a DNS record

json
{ "domain": "acmecoffee.com.au", "deleted": "1794051896320550" }

Transfers in

POST/transfers/check

Check a domain can move to Plonki, and the price

FieldTypeDescription
domain
required
stringThe domain to move to Plonki, e.g. acme.com
auth_code
required
stringTransfer (EPP/auth) code from the current registrar
up to 100 chars
json
{
  "domain": "acmecoffee.com",
  "transferable": true,
  "amount": 3399,
  "currency": "AUD",
  "adds_a_year": true,
  "note": "The transfer adds a year to the registration."
}

Doesn't buy anything. Refusals come back as transfer_not_possible with the reason (wrong code, locked, too soon after registration).

POST/transfers

Transfer a domain in

FieldTypeDescription
domain
required
stringThe domain to move to Plonki, e.g. acme.com
auth_code
required
stringTransfer (EPP/auth) code from the current registrar
up to 100 chars
max_priceintegerMost you will pay, in AUD cents. Use the price from check_transfer.
contact_idstringSaved owner contact. Defaults to the account's default contact.
contactobjectOwner details, if there's no saved contact. Saved for next time.
contact.first_name
required
string
up to 60 chars
contact.last_name
required
string
up to 60 chars
contact.organisationstring
up to 120 chars
contact.email
required
email
contact.phone
required
stringMobile, e.g. 0412 345 678, +61 412 345 678 or +61.412345678
contact.address1
required
string
up to 120 chars
contact.address2string
up to 120 chars
contact.city
required
string
up to 60 chars
contact.state
required
stringFor Australia use the abbreviation: NSW, VIC, QLD, SA, WA, TAS, ACT, NT
up to 60 chars
contact.postcode
required
string
up to 12 chars
contact.country
required
stringISO 3166-1 alpha-2, e.g. AU, US, GB
up to 2 chars
payment"auto" | "balance" | "checkout"
default "auto"
idempotency_keystringSame key returns the same order instead of transferring twice
up to 100 chars
external_refstringYour own reference, e.g. your customer's ID
up to 200 chars

Returns 202 with an order in processing (or awaiting_payment with a checkout_url). See Transfer a domain in.

PUT/domains/{domain}/lock

Turn the transfer lock on or off

FieldTypeDescription
locked
required
booleantrue stops the domain being transferred away; false allows a transfer out
json
{ "domain": "acmecoffee.com", "transfer_lock": false }

.au domains have no lock and return lock_not_supported.

Forwarding

GET/domains/{domain}/email-forwards

Email forwards

json
{ "domain": "acmecoffee.com.au", "forwards": [ { "id": "4821", "source": "hello@acmecoffee.com.au", "destination": "sam@gmail.com" } ] }

POST/domains/{domain}/email-forwards

Forward an address to an inbox

FieldTypeDescription
alias
required
stringThe part before the @, e.g. hello for hello@yourdomain
forward_to
required
emailInbox that receives the mail, e.g. sam@gmail.com

DELETE/domains/{domain}/email-forwards/{id}

Remove an email forward

json
{ "domain": "acmecoffee.com.au", "deleted": "4821" }

GET/domains/{domain}/url-forwards

Redirects

json
{ "domain": "acmecoffee.com.au", "forwards": [ { "id": "913", "hostname": "shop.acmecoffee.com.au", "destination": "https://instagram.com/acmecoffee", "type": "P" } ] }

POST/domains/{domain}/url-forwards

Redirect a hostname to a URL

FieldTypeDescription
hoststring@ for the domain itself, or a label like www
default "@"
destination
required
stringFull URL to send visitors to, e.g. https://instagram.com/acmecoffee

A permanent (301) redirect. Existing A, AAAA and CNAME records on that host are removed, because the redirect replaces any website there.

DELETE/domains/{domain}/url-forwards/{id}

Remove a redirect

json
{ "domain": "acmecoffee.com.au", "deleted": "913" }

Orders

GET/orders

Recent orders

Query limit (default 50, up to 200). Newest first.

GET/orders/{id}

One order

FieldDescription
statusawaiting_payment, queued, processing, completed, failed, refunded or needs_review.
paymentbalance, checkout or free_test.
amountTotal for the order in cents.
checkout_urlWhere the payer goes, while awaiting_payment.
errorWhy it failed, when it did.
next_stepPlain-English instruction for the current status, written for agents.
StatusMeaning
awaiting_paymentWaiting for the checkout link to be paid. Unpaid links expire after 24 hours.
queued, processingPaid; the registry is working on it. Usually seconds.
completedDone. The domain is in your account.
failedThe registry refused it. Anything paid went back to your balance.
needs_reviewThe outcome is unclear (for example the registry timed out, or a card payment was disputed). A person checks it; you don't need to do anything.

Contacts

GET/contacts

Saved domain owners

json
{
  "default_contact_id": "con_4f7h2k9m1q3w8e5r6t0y",
  "contacts": [
    {
      "id": "con_4f7h2k9m1q3w8e5r6t0y",
      "first_name": "Sam", "last_name": "Lee", "organisation": "Acme Coffee Pty Ltd",
      "email": "sam@acmecoffee.com.au", "phone": "+61.412345678",
      "address1": "1 Smith St", "address2": null, "city": "Melbourne", "state": "VIC", "postcode": "3000", "country": "AU",
      "au_eligibility": { "registrant_name": "Acme Coffee Pty Ltd", "registrant_id": "12345678901",
                          "registrant_id_type": "ABN", "eligibility_type": "Company" },
      "created_at": 1794051896000
    }
  ]
}

POST/contacts

Save a domain owner

FieldTypeDescription
first_name
required
string
up to 60 chars
last_name
required
string
up to 60 chars
organisationstring
up to 120 chars
email
required
email
phone
required
stringMobile, e.g. 0412 345 678, +61 412 345 678 or +61.412345678
address1
required
string
up to 120 chars
address2string
up to 120 chars
city
required
string
up to 60 chars
state
required
stringFor Australia use the abbreviation: NSW, VIC, QLD, SA, WA, TAS, ACT, NT
up to 60 chars
postcode
required
string
up to 12 chars
country
required
stringISO 3166-1 alpha-2, e.g. AU, US, GB
up to 2 chars
make_defaultbooleanUse this contact when an order doesn't name one
default false

Billing

POST/billing/topup

Checkout link to add balance

FieldTypeDescription
amount
required
integerAUD cents, $10 to $10,000
1000 to 1000000
json
{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_...", "amount": 10000, "currency": "AUD" }