Endpoints
Base URL https://plonki.com.au/v1. JSON bodies. Prices in AUD cents. Machine-readable version: /openapi.json.
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.
{
"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
GET/domains/search
Check availability and price
| Query | Description |
|---|---|
q | A domain (acme.com) or a phrase (acme coffee). A domain is checked along with the same name on five popular extensions. A phrase becomes one label and is tried across tlds. |
tlds | Comma-separated extensions for a phrase, e.g. com,com.au,io. Default: com, io, ai, app, co, dev, com.au, net, xyz. |
domains | Comma-separated exact domains, up to 50. |
curl "https://plonki.com.au/v1/domains/search?q=acme%20coffee&tlds=com,com.au,io" \ -H "Authorization: Bearer $PLONKI_KEY"
{
"results": [
{ "domain": "acmecoffee.com", "available": false, "premium": false, "currency": "AUD", "price": null },
{ "domain": "acmecoffee.com.au", "available": true, "premium": false, "currency": "AUD",
"price": { "register": 2399, "renew": 2399, "min_years": 1 } },
{ "domain": "acmecoffee.io", "available": true, "premium": false, "currency": "AUD",
"price": { "register": 10499, "renew": 10499, "min_years": 1 } }
]
}price.register is per year; the first payment is register × min_years. A note appears on .au names held for an existing .com.au or .net.au owner, and on premium names. Results are cached for 60 seconds; registration always re-checks live.
POST/domains/search
Check availability (JSON body)
| Field | Type | Description |
|---|---|---|
query | string | A domain (acme.com) or a name/phrase (Acme Coffee). Phrases are checked across popular extensions. up to 200 chars |
domains | array of string | Exact domains to check, up to 50 |
tlds | array of string | Extensions to try for a phrase, e.g. ['com','io','com.au'] |
GET/domains/suggest
Available domain ideas from keywords
| Field | Type | Description |
|---|---|---|
keywordsrequired | string | What the site is about, e.g. 'dog grooming melbourne' up to 200 chars |
tlds | array of string | |
limit | integer | 1 to 30, default 10 |
curl "https://plonki.com.au/v1/domains/suggest?keywords=dog+grooming+melbourne&limit=5" \ -H "Authorization: Bearer $PLONKI_KEY"
{
"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.
| Field | Type | Description |
|---|---|---|
domainrequired | string | The domain to register, e.g. acme.com |
years | integer | 1 to 10, default 1 |
max_price | integer | Most you will pay, in AUD cents, for the whole order. Use total from search/quote. Order fails if the price is higher. |
contact_id | string | Saved registrant contact. Defaults to the account's default contact. |
contact | object | Registrant details, if there's no saved contact. Saved for next time. |
contact.first_namerequired | string | up to 60 chars |
contact.last_namerequired | string | up to 60 chars |
contact.organisation | string | up to 120 chars |
contact.emailrequired | email | |
contact.phonerequired | string | Mobile, e.g. 0412 345 678, +61 412 345 678 or +61.412345678 |
contact.address1required | string | up to 120 chars |
contact.address2 | string | up to 120 chars |
contact.cityrequired | string | up to 60 chars |
contact.staterequired | string | For Australia use the abbreviation: NSW, VIC, QLD, SA, WA, TAS, ACT, NT up to 60 chars |
contact.postcoderequired | string | up to 12 chars |
contact.countryrequired | string | ISO 3166-1 alpha-2, e.g. AU, US, GB up to 2 chars |
au_eligibility | object | Required for .com.au, .net.au, .org.au, .id.au and .au names (auDA rules) |
au_eligibility.registrant_namerequired | string | Legal name of the registrant (company or person) up to 255 chars |
au_eligibility.registrant_idrequired | string | ABN, ACN or other ID number, digits only up to 50 chars |
au_eligibility.registrant_id_typerequired | "ABN" | "ACN" | "OTHER" | OTHER covers state business registration numbers and incorporated associations |
au_eligibility.eligibility_typerequired | 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_name | string | Trading or business name the domain is based on, if different from registrant_name up to 255 chars |
au_eligibility.eligibility_id | string | ID that backs eligibility_name (e.g. a trademark number or state business number) up to 50 chars |
au_eligibility.eligibility_id_type | string (see list) | |
nameservers | array of string | Custom 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_key | string | Same key returns the same order instead of buying twice up to 100 chars |
external_ref | string | Your own reference, e.g. your customer's ID up to 200 chars |
Responses:
201 | status: "completed". Paid from the balance and registered. |
202 | awaiting_payment (send the payer to checkout_url) or processing (the registry is slow; poll the order). |
400 | contact_required, au_eligibility_required, invalid_years, validation_error… |
402 | insufficient_balance (only with payment: "balance"). |
409 | domain_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
| Field | Type | Description |
|---|---|---|
years | integer | 1 to 10, default 1 |
max_price | integer | |
payment | "auto" | "balance" | "checkout" | default "auto" |
idempotency_key | string | 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.
{
"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
{ "domain": "acmecoffee.com", "auth_code": "Xy7#p2Lq9!" }DNS and nameservers
POST/domains/{domain}/point
Point the domain at a website
| Field | Type | Description |
|---|---|---|
targetrequired | string | Where the site is hosted: an IPv4 address (76.76.21.21) or a hostname (myapp.vercel.app, myapp.pages.dev, myapp.netlify.app) |
include_www | boolean | default true |
{
"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
| Field | Type | Description |
|---|---|---|
nameserversrequired | array of string | Hostnames, e.g. ['ns1.vercel-dns.com','ns2.vercel-dns.com']. Send an empty array to switch back to Plonki DNS. |
{ "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
{
"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
| Field | Type | Description |
|---|---|---|
name | string | Host label: '@' for the root, 'www', 'api', etc. default "@" |
typerequired | "A" | "AAAA" | "CNAME" | "MX" | "TXT" | "SRV" | "CAA" | "NS" | |
contentrequired | string | up to 2048 chars |
ttl | integer | 300 to 86400, default 3600 |
priority | integer | MX and SRV only 0 to 65535 |
Types: AAAAACNAMEMXTXTSRVCAANS. MX and SRV default to priority 10. Recipes: DNS records.
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
{ "domain": "acmecoffee.com.au", "deleted": "1794051896320550" }Transfers in
POST/transfers/check
Check a domain can move to Plonki, and the price
| Field | Type | Description |
|---|---|---|
domainrequired | string | The domain to move to Plonki, e.g. acme.com |
auth_coderequired | string | Transfer (EPP/auth) code from the current registrar up to 100 chars |
{
"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
| Field | Type | Description |
|---|---|---|
domainrequired | string | The domain to move to Plonki, e.g. acme.com |
auth_coderequired | string | Transfer (EPP/auth) code from the current registrar up to 100 chars |
max_price | integer | Most you will pay, in AUD cents. Use the price from check_transfer. |
contact_id | string | Saved owner contact. Defaults to the account's default contact. |
contact | object | Owner details, if there's no saved contact. Saved for next time. |
contact.first_namerequired | string | up to 60 chars |
contact.last_namerequired | string | up to 60 chars |
contact.organisation | string | up to 120 chars |
contact.emailrequired | email | |
contact.phonerequired | string | Mobile, e.g. 0412 345 678, +61 412 345 678 or +61.412345678 |
contact.address1required | string | up to 120 chars |
contact.address2 | string | up to 120 chars |
contact.cityrequired | string | up to 60 chars |
contact.staterequired | string | For Australia use the abbreviation: NSW, VIC, QLD, SA, WA, TAS, ACT, NT up to 60 chars |
contact.postcoderequired | string | up to 12 chars |
contact.countryrequired | string | ISO 3166-1 alpha-2, e.g. AU, US, GB up to 2 chars |
payment | "auto" | "balance" | "checkout" | default "auto" |
idempotency_key | string | Same key returns the same order instead of transferring twice up to 100 chars |
external_ref | string | Your 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
| Field | Type | Description |
|---|---|---|
lockedrequired | boolean | true stops the domain being transferred away; false allows a transfer out |
{ "domain": "acmecoffee.com", "transfer_lock": false }.au domains have no lock and return lock_not_supported.
Forwarding
GET/domains/{domain}/email-forwards
Email forwards
{ "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
| Field | Type | Description |
|---|---|---|
aliasrequired | string | The part before the @, e.g. hello for hello@yourdomain |
forward_torequired | email | Inbox that receives the mail, e.g. sam@gmail.com |
DELETE/domains/{domain}/email-forwards/{id}
Remove an email forward
{ "domain": "acmecoffee.com.au", "deleted": "4821" }GET/domains/{domain}/url-forwards
Redirects
{ "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
| Field | Type | Description |
|---|---|---|
host | string | @ for the domain itself, or a label like www default "@" |
destinationrequired | string | Full 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
{ "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
| Field | Description |
|---|---|
status | awaiting_payment, queued, processing, completed, failed, refunded or needs_review. |
payment | balance, checkout or free_test. |
amount | Total for the order in cents. |
checkout_url | Where the payer goes, while awaiting_payment. |
error | Why it failed, when it did. |
next_step | Plain-English instruction for the current status, written for agents. |
| Status | Meaning |
|---|---|
awaiting_payment | Waiting for the checkout link to be paid. Unpaid links expire after 24 hours. |
queued, processing | Paid; the registry is working on it. Usually seconds. |
completed | Done. The domain is in your account. |
failed | The registry refused it. Anything paid went back to your balance. |
needs_review | The 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
{
"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
| Field | Type | Description |
|---|---|---|
first_namerequired | string | up to 60 chars |
last_namerequired | string | up to 60 chars |
organisation | string | up to 120 chars |
emailrequired | email | |
phonerequired | string | Mobile, e.g. 0412 345 678, +61 412 345 678 or +61.412345678 |
address1required | string | up to 120 chars |
address2 | string | up to 120 chars |
cityrequired | string | up to 60 chars |
staterequired | string | For Australia use the abbreviation: NSW, VIC, QLD, SA, WA, TAS, ACT, NT up to 60 chars |
postcoderequired | string | up to 12 chars |
countryrequired | string | ISO 3166-1 alpha-2, e.g. AU, US, GB up to 2 chars |
make_default | boolean | Use this contact when an order doesn't name one default false |
Billing
POST/billing/topup
Checkout link to add balance
| Field | Type | Description |
|---|---|---|
amountrequired | integer | AUD cents, $10 to $10,000 1000 to 1000000 |
{ "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_...", "amount": 10000, "currency": "AUD" }