Skip to content

📝 DNS

DNS record management operations and types.

🚀 Quick Examples

List All Records

from oinker import AsyncPiglet

async with AsyncPiglet() as piglet:
    records = await piglet.dns.list("example.com")
    for record in records:
        print(f"{record.record_type} {record.name} -> {record.content}")

Get a Single Record by ID

async with AsyncPiglet() as piglet:
    record = await piglet.dns.get("example.com", record_id="123456")
    print(f"{record.record_type} {record.name} -> {record.content}")

Get Records by Name and Type

async with AsyncPiglet() as piglet:
    # Get all A records for www subdomain
    records = await piglet.dns.get_by_name_type(
        "example.com",
        record_type="A",
        subdomain="www"
    )
    for record in records:
        print(f"{record.name} -> {record.content}")

    # Get root domain A records (no subdomain)
    root_records = await piglet.dns.get_by_name_type(
        "example.com",
        record_type="A"
    )

Create Records

from oinker import AsyncPiglet, ARecord, MXRecord, TXTRecord

async with AsyncPiglet() as piglet:
    # A record for www subdomain
    record_id = await piglet.dns.create(
        "example.com",
        ARecord(content="1.2.3.4", name="www")
    )
    print(f"Created record: {record_id}")

    # MX record with priority
    await piglet.dns.create(
        "example.com",
        MXRecord(content="mail.example.com", priority=10)
    )

    # TXT record for SPF
    await piglet.dns.create(
        "example.com",
        TXTRecord(content="v=spf1 include:_spf.example.com ~all")
    )

Edit Records

from oinker import ARecord

async with AsyncPiglet() as piglet:
    # Edit by record ID
    await piglet.dns.edit(
        "example.com",
        record_id="123456",
        record=ARecord(content="5.6.7.8", name="www")
    )

    # Edit all matching records by name and type
    await piglet.dns.edit_by_name_type(
        "example.com",
        record_type="A",
        subdomain="www",
        content="5.6.7.8"
    )

Delete Records

async with AsyncPiglet() as piglet:
    # Delete by record ID
    await piglet.dns.delete("example.com", record_id="123456")

    # Delete all matching records by name and type
    await piglet.dns.delete_by_name_type(
        "example.com",
        record_type="A",
        subdomain="www"
    )

Operations

AsyncDNSAPI

oinker.dns.AsyncDNSAPI

AsyncDNSAPI(http: HttpClient)

Async DNS operations for the Porkbun API.

Accessed via piglet.dns.* methods.

Initialize DNS API.

Parameters:

Name Type Description Default
http HttpClient

The HTTP client for making requests.

required
Source code in src/oinker/dns/_api.py
def __init__(self, http: HttpClient) -> None:
    """Initialize DNS API.

    Args:
        http: The HTTP client for making requests.
    """
    self._http = http

list async

list(domain: str) -> builtins.list[DNSRecordResponse]

List all DNS records for a domain.

Parameters:

Name Type Description Default
domain str

The domain name (e.g., "example.com").

required

Returns:

Type Description
list[DNSRecordResponse]

List of DNS records.

Raises:

Type Description
AuthenticationError

If credentials are invalid.

NotFoundError

If domain is not found.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def list(self, domain: str) -> builtins.list[DNSRecordResponse]:
    """List all DNS records for a domain.

    Args:
        domain: The domain name (e.g., "example.com").

    Returns:
        List of DNS records.

    Raises:
        AuthenticationError: If credentials are invalid.
        NotFoundError: If domain is not found.
        APIError: If the request fails.
    """
    data = await self._http.post(f"/dns/retrieve/{domain}")
    records = data.get("records", [])
    return [DNSRecordResponse.from_api_response(r) for r in records]

get async

get(
    domain: str, record_id: str
) -> DNSRecordResponse | None

Get a specific DNS record by ID.

Parameters:

Name Type Description Default
domain str

The domain name.

required
record_id str

The record ID.

required

Returns:

Type Description
DNSRecordResponse | None

The DNS record, or None if not found.

Raises:

Type Description
AuthenticationError

If credentials are invalid.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def get(self, domain: str, record_id: str) -> DNSRecordResponse | None:
    """Get a specific DNS record by ID.

    Args:
        domain: The domain name.
        record_id: The record ID.

    Returns:
        The DNS record, or None if not found.

    Raises:
        AuthenticationError: If credentials are invalid.
        APIError: If the request fails.
    """
    data = await self._http.post(f"/dns/retrieve/{domain}/{record_id}")
    records = data.get("records", [])
    if records:
        return DNSRecordResponse.from_api_response(records[0])
    return None

get_by_name_type async

get_by_name_type(
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> builtins.list[DNSRecordResponse]

Get DNS records by subdomain and type.

Parameters:

Name Type Description Default
domain str

The domain name.

required
record_type str

The record type (A, AAAA, MX, etc.).

required
subdomain str | None

The subdomain (None for root).

None

Returns:

Type Description
list[DNSRecordResponse]

List of matching DNS records.

Raises:

Type Description
AuthenticationError

If credentials are invalid.

NotFoundError

If no records match.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def get_by_name_type(
    self,
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> builtins.list[DNSRecordResponse]:
    """Get DNS records by subdomain and type.

    Args:
        domain: The domain name.
        record_type: The record type (A, AAAA, MX, etc.).
        subdomain: The subdomain (None for root).

    Returns:
        List of matching DNS records.

    Raises:
        AuthenticationError: If credentials are invalid.
        NotFoundError: If no records match.
        APIError: If the request fails.
    """
    endpoint = f"/dns/retrieveByNameType/{domain}/{record_type}"
    if subdomain:
        endpoint = f"{endpoint}/{subdomain}"
    data = await self._http.post(endpoint)
    records = data.get("records", [])
    return [DNSRecordResponse.from_api_response(r) for r in records]

create async

create(domain: str, record: DNSRecord) -> str

Create a new DNS record.

Parameters:

Name Type Description Default
domain str

The domain name.

required
record DNSRecord

The DNS record to create.

required

Returns:

Type Description
str

The ID of the created record.

Raises:

Type Description
AuthenticationError

If credentials are invalid.

ValidationError

If record data is invalid.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def create(self, domain: str, record: DNSRecord) -> str:
    """Create a new DNS record.

    Args:
        domain: The domain name.
        record: The DNS record to create.

    Returns:
        The ID of the created record.

    Raises:
        AuthenticationError: If credentials are invalid.
        ValidationError: If record data is invalid.
        APIError: If the request fails.
    """
    body = self._record_to_api_body(record)
    data = await self._http.post(f"/dns/create/{domain}", body)
    return str(data.get("id", ""))

edit async

edit(
    domain: str, record_id: str, record: DNSRecord
) -> None

Edit an existing DNS record by ID.

Parameters:

Name Type Description Default
domain str

The domain name.

required
record_id str

The record ID to edit.

required
record DNSRecord

The new record data.

required

Raises:

Type Description
AuthenticationError

If credentials are invalid.

NotFoundError

If record is not found.

ValidationError

If record data is invalid.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def edit(self, domain: str, record_id: str, record: DNSRecord) -> None:
    """Edit an existing DNS record by ID.

    Args:
        domain: The domain name.
        record_id: The record ID to edit.
        record: The new record data.

    Raises:
        AuthenticationError: If credentials are invalid.
        NotFoundError: If record is not found.
        ValidationError: If record data is invalid.
        APIError: If the request fails.
    """
    body = self._record_to_api_body(record)
    await self._http.post(f"/dns/edit/{domain}/{record_id}", body)

edit_by_name_type async

edit_by_name_type(
    domain: str,
    record_type: str,
    subdomain: str | None = None,
    *,
    content: str,
    ttl: int | None = None,
    priority: int | None = None,
    notes: str | None = None,
) -> None

Edit all records matching subdomain and type.

Parameters:

Name Type Description Default
domain str

The domain name.

required
record_type str

The record type (A, AAAA, MX, etc.).

required
subdomain str | None

The subdomain (None for root).

None
content str

The new content value.

required
ttl int | None

Optional new TTL.

None
priority int | None

Optional new priority.

None
notes str | None

Optional new notes (empty string clears, None leaves unchanged).

None

Raises:

Type Description
AuthenticationError

If credentials are invalid.

NotFoundError

If no records match.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def edit_by_name_type(
    self,
    domain: str,
    record_type: str,
    subdomain: str | None = None,
    *,
    content: str,
    ttl: int | None = None,
    priority: int | None = None,
    notes: str | None = None,
) -> None:
    """Edit all records matching subdomain and type.

    Args:
        domain: The domain name.
        record_type: The record type (A, AAAA, MX, etc.).
        subdomain: The subdomain (None for root).
        content: The new content value.
        ttl: Optional new TTL.
        priority: Optional new priority.
        notes: Optional new notes (empty string clears, None leaves unchanged).

    Raises:
        AuthenticationError: If credentials are invalid.
        NotFoundError: If no records match.
        APIError: If the request fails.
    """
    endpoint = f"/dns/editByNameType/{domain}/{record_type}"
    if subdomain:
        endpoint = f"{endpoint}/{subdomain}"

    body: dict[str, Any] = {"content": content}
    if ttl is not None:
        body["ttl"] = str(ttl)
    if priority is not None:
        body["prio"] = str(priority)
    if notes is not None:
        body["notes"] = notes

    await self._http.post(endpoint, body)

delete async

delete(domain: str, record_id: str) -> None

Delete a DNS record by ID.

Parameters:

Name Type Description Default
domain str

The domain name.

required
record_id str

The record ID to delete.

required

Raises:

Type Description
AuthenticationError

If credentials are invalid.

NotFoundError

If record is not found.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def delete(self, domain: str, record_id: str) -> None:
    """Delete a DNS record by ID.

    Args:
        domain: The domain name.
        record_id: The record ID to delete.

    Raises:
        AuthenticationError: If credentials are invalid.
        NotFoundError: If record is not found.
        APIError: If the request fails.
    """
    await self._http.post(f"/dns/delete/{domain}/{record_id}")

delete_by_name_type async

delete_by_name_type(
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> None

Delete all records matching subdomain and type.

Parameters:

Name Type Description Default
domain str

The domain name.

required
record_type str

The record type (A, AAAA, MX, etc.).

required
subdomain str | None

The subdomain (None for root).

None

Raises:

Type Description
AuthenticationError

If credentials are invalid.

NotFoundError

If no records match.

APIError

If the request fails.

Source code in src/oinker/dns/_api.py
async def delete_by_name_type(
    self,
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> None:
    """Delete all records matching subdomain and type.

    Args:
        domain: The domain name.
        record_type: The record type (A, AAAA, MX, etc.).
        subdomain: The subdomain (None for root).

    Raises:
        AuthenticationError: If credentials are invalid.
        NotFoundError: If no records match.
        APIError: If the request fails.
    """
    endpoint = f"/dns/deleteByNameType/{domain}/{record_type}"
    if subdomain:
        endpoint = f"{endpoint}/{subdomain}"
    await self._http.post(endpoint)

SyncDNSAPI

oinker.dns.SyncDNSAPI

SyncDNSAPI(
    async_api: AsyncAPIType, runner: Callable[..., Any]
)

Bases: SyncAPIBase['AsyncDNSAPI']

Synchronous DNS operations for the Porkbun API.

Accessed via piglet.dns.* methods.

Source code in src/oinker/_sync_base.py
def __init__(
    self,
    async_api: AsyncAPIType,
    runner: Callable[..., Any],
) -> None:
    self._async_api = async_api
    self._run = runner

list

list(domain: str) -> builtins.list[DNSRecordResponse]

See :meth:AsyncDNSAPI.list.

Source code in src/oinker/dns/_sync.py
def list(self, domain: str) -> builtins.list[DNSRecordResponse]:
    """See :meth:`AsyncDNSAPI.list`."""
    return self._run(self._async_api.list(domain))

get

get(
    domain: str, record_id: str
) -> DNSRecordResponse | None

See :meth:AsyncDNSAPI.get.

Source code in src/oinker/dns/_sync.py
def get(self, domain: str, record_id: str) -> DNSRecordResponse | None:
    """See :meth:`AsyncDNSAPI.get`."""
    return self._run(self._async_api.get(domain, record_id))

get_by_name_type

get_by_name_type(
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> builtins.list[DNSRecordResponse]

See :meth:AsyncDNSAPI.get_by_name_type.

Source code in src/oinker/dns/_sync.py
def get_by_name_type(
    self,
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> builtins.list[DNSRecordResponse]:
    """See :meth:`AsyncDNSAPI.get_by_name_type`."""
    return self._run(self._async_api.get_by_name_type(domain, record_type, subdomain))

create

create(domain: str, record: DNSRecord) -> str

See :meth:AsyncDNSAPI.create.

Source code in src/oinker/dns/_sync.py
def create(self, domain: str, record: DNSRecord) -> str:
    """See :meth:`AsyncDNSAPI.create`."""
    return self._run(self._async_api.create(domain, record))

edit

edit(
    domain: str, record_id: str, record: DNSRecord
) -> None

See :meth:AsyncDNSAPI.edit.

Source code in src/oinker/dns/_sync.py
def edit(self, domain: str, record_id: str, record: DNSRecord) -> None:
    """See :meth:`AsyncDNSAPI.edit`."""
    self._run(self._async_api.edit(domain, record_id, record))

edit_by_name_type

edit_by_name_type(
    domain: str,
    record_type: str,
    subdomain: str | None = None,
    *,
    content: str,
    ttl: int | None = None,
    priority: int | None = None,
    notes: str | None = None,
) -> None

See :meth:AsyncDNSAPI.edit_by_name_type.

Source code in src/oinker/dns/_sync.py
def edit_by_name_type(
    self,
    domain: str,
    record_type: str,
    subdomain: str | None = None,
    *,
    content: str,
    ttl: int | None = None,
    priority: int | None = None,
    notes: str | None = None,
) -> None:
    """See :meth:`AsyncDNSAPI.edit_by_name_type`."""
    self._run(
        self._async_api.edit_by_name_type(
            domain,
            record_type,
            subdomain,
            content=content,
            ttl=ttl,
            priority=priority,
            notes=notes,
        )
    )

delete

delete(domain: str, record_id: str) -> None

See :meth:AsyncDNSAPI.delete.

Source code in src/oinker/dns/_sync.py
def delete(self, domain: str, record_id: str) -> None:
    """See :meth:`AsyncDNSAPI.delete`."""
    self._run(self._async_api.delete(domain, record_id))

delete_by_name_type

delete_by_name_type(
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> None

See :meth:AsyncDNSAPI.delete_by_name_type.

Source code in src/oinker/dns/_sync.py
def delete_by_name_type(
    self,
    domain: str,
    record_type: str,
    subdomain: str | None = None,
) -> None:
    """See :meth:`AsyncDNSAPI.delete_by_name_type`."""
    self._run(self._async_api.delete_by_name_type(domain, record_type, subdomain))

Record Types

All record types validate their content on construction.

ARecord

oinker.ARecord dataclass

ARecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

A record pointing to an IPv4 address.

Attributes:

Name Type Description
content str

IPv4 address (validated on init).

name str | None

Subdomain (None = root domain, "*" = wildcard).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record content.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record content."""
    # Validate and normalize the IP address
    ip = _validate_ipv4(self.content)
    object.__setattr__(self, "content", str(ip))
    _validate_ttl(self.ttl)

AAAARecord

oinker.AAAARecord dataclass

AAAARecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

AAAA record pointing to an IPv6 address.

Attributes:

Name Type Description
content str

IPv6 address (validated on init).

name str | None

Subdomain (None = root domain, "*" = wildcard).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record content.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record content."""
    ip = _validate_ipv6(self.content)
    object.__setattr__(self, "content", str(ip))
    _validate_ttl(self.ttl)

MXRecord

oinker.MXRecord dataclass

MXRecord(
    content: str,
    priority: int = 10,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

MX record for mail servers.

Attributes:

Name Type Description
content str

Mail server hostname.

priority int

Mail priority (lower = higher priority).

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_priority(self.priority)
    _validate_content_not_empty(self.content, "MX", "mail server")

TXTRecord

oinker.TXTRecord dataclass

TXTRecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

TXT record for arbitrary text data.

Attributes:

Name Type Description
content str

Text content.

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)

CNAMERecord

oinker.CNAMERecord dataclass

CNAMERecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

CNAME record pointing to another hostname.

Attributes:

Name Type Description
content str

Target hostname.

name str | None

Subdomain (None allowed, but may be rejected by API for root CNAMEs).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_content_not_empty(self.content, "CNAME", "target")

ALIASRecord

oinker.ALIASRecord dataclass

ALIASRecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

ALIAS record (ANAME) for root domain CNAME-like behavior.

Attributes:

Name Type Description
content str

Target hostname.

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_content_not_empty(self.content, "ALIAS", "target")

NSRecord

oinker.NSRecord dataclass

NSRecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

NS record delegating to a name server.

Attributes:

Name Type Description
content str

Nameserver hostname.

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_content_not_empty(self.content, "NS", "nameserver")

SRVRecord

oinker.SRVRecord dataclass

SRVRecord(
    content: str,
    priority: int = 10,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

SRV record for service discovery.

Content format: "weight port target" (e.g., "5 5060 sipserver.example.com")

Attributes:

Name Type Description
content str

SRV data in "weight port target" format.

priority int

Service priority (lower = higher priority).

name str | None

Service name (e.g., "_sip._tcp").

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_priority(self.priority)
    _validate_content_not_empty(self.content, "SRV")

TLSARecord

oinker.TLSARecord dataclass

TLSARecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

TLSA record for DANE TLS authentication.

Content format: "usage selector matching_type certificate_data"

Attributes:

Name Type Description
content str

TLSA data.

name str | None

Port and protocol prefix (e.g., "_443._tcp").

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_content_not_empty(self.content, "TLSA")

CAARecord

oinker.CAARecord dataclass

CAARecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

CAA record for certificate authority authorization.

Content format: 'flags tag "value"' (e.g., '0 issue "letsencrypt.org"')

Attributes:

Name Type Description
content str

CAA data.

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_content_not_empty(self.content, "CAA")

HTTPSRecord

oinker.HTTPSRecord dataclass

HTTPSRecord(
    content: str,
    priority: int = 1,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

HTTPS record for service binding.

Attributes:

Name Type Description
content str

HTTPS SVCB data.

priority int

Priority (0 = alias mode).

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_priority(self.priority)
    _validate_content_not_empty(self.content, "HTTPS")

SVCBRecord

oinker.SVCBRecord dataclass

SVCBRecord(
    content: str,
    priority: int = 1,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

SVCB record for general service binding.

Attributes:

Name Type Description
content str

SVCB data.

priority int

Priority (0 = alias mode).

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_priority(self.priority)
    _validate_content_not_empty(self.content, "SVCB")

SSHFPRecord

oinker.SSHFPRecord dataclass

SSHFPRecord(
    content: str,
    name: str | None = None,
    ttl: int = 600,
    notes: str | None = None,
)

SSHFP record for SSH fingerprint verification.

Content format: "algorithm fingerprint_type fingerprint"

Attributes:

Name Type Description
content str

SSHFP data.

name str | None

Subdomain (None = root domain).

ttl int

Time to live in seconds (min 600).

notes str | None

Optional notes for the record.

__post_init__

__post_init__() -> None

Validate the record.

Source code in src/oinker/dns/_records.py
def __post_init__(self) -> None:
    """Validate the record."""
    _validate_ttl(self.ttl)
    _validate_content_not_empty(self.content, "SSHFP")

Response Types

DNSRecordResponse

oinker.DNSRecordResponse dataclass

DNSRecordResponse(
    id: str,
    name: str,
    record_type: str,
    content: str,
    ttl: int,
    priority: int = 0,
    notes: str = "",
)

A DNS record as returned from the API.

Attributes:

Name Type Description
id str

Unique record identifier.

name str

Full domain name (e.g., "www.example.com").

record_type str

DNS record type (A, AAAA, etc.).

content str

Record content/answer.

ttl int

Time to live in seconds.

priority int

Record priority (for MX, SRV, etc.).

notes str

Optional notes.

from_api_response classmethod

from_api_response(
    data: dict[str, str],
) -> DNSRecordResponse

Create a DNSRecordResponse from API response data.

Parameters:

Name Type Description Default
data dict[str, str]

Dictionary from Porkbun API.

required

Returns:

Type Description
DNSRecordResponse

Parsed DNSRecordResponse.

Source code in src/oinker/dns/_records.py
@classmethod
def from_api_response(cls, data: dict[str, str]) -> DNSRecordResponse:
    """Create a DNSRecordResponse from API response data.

    Args:
        data: Dictionary from Porkbun API.

    Returns:
        Parsed DNSRecordResponse.
    """
    return cls(
        id=data.get("id", ""),
        name=data.get("name", ""),
        record_type=data.get("type", ""),
        content=data.get("content", ""),
        ttl=_safe_int(data.get("ttl", ""), 600),
        priority=_safe_int(data.get("prio", ""), 0),
        notes=data.get("notes", ""),
    )