npm package: @startanaicompany/dns
Description: CLI tool for programmatic domain registration and DNS management — by Start An AI Company (SAAC)
Author: Start An AI Company
Latest version: 3.1.3

# @startanaicompany/saac_dns

Programmatic Domain Registration, DNS Management & CLI Toolkit by [Start An AI Company (SAAC)](https://start-an-ai-company-3l1xzm.adam.startanaicompany.com).

Powered by the SAAC backend at `https://start-an-ai-company-3l1xzm.adam.startanaicompany.com`.

---

## Installation

```bash
npm install @startanaicompany/saac_dns
# or
pnpm add @startanaicompany/saac_dns
```

Install the CLI globally:

```bash
npm install -g @startanaicompany/saac_dns
```

---

## Quick Start

```bash
npm install @startanaicompany/saac_dns
export SAAC_USER_API_KEY=your_api_key
export SAAC_USER_EMAIL=your@email.com
```

```js
const dns = require('@startanaicompany/saac_dns');

const results = await dns.search(['mycompany.com', 'mycompany.io']);
await dns.buy('mycompany.io', { years: 1, privacy: true, autoRenew: true });
```

---

## Environment Variables

| Variable | Description | Required |
|---|---|---|
| `SAAC_USER_API_KEY` | Your SAAC API key | Yes |
| `SAAC_USER_EMAIL` | Your SAAC account email | Yes |
| `SAAC_API_URL` | Override backend URL (default: production) | No |

---

## SDK API Reference

### Domain Search & Registration

#### `dns.search(domains)`

Search availability and pricing for one or more domains.

```js
const results = await dns.search(['mycompany.com', 'mycompany.io']);
// [{ fqdn, available, price, currency, tld }, ...]
```

#### `dns.buy(domain, opts?)`

Register a domain.

```js
await dns.buy('mycompany.io', {
  years: 1,       // default: 1
  privacy: true,  // WHOIS privacy, default: false
  autoRenew: true // default: true
});
```

#### `dns.list()`

List all domains on your account.

```js
const domains = await dns.list();
```

#### `dns.info(domain)`

Get full details for a domain.

```js
const domain = await dns.info('mycompany.io');
```

#### `dns.prices(tlds?)`

Get registration prices, optionally filtered by TLD.

```js
const all = await dns.prices();
const filtered = await dns.prices(['.com', '.io']);
```

#### `dns.renew(domain, years?)`

Renew a domain registration.

```js
await dns.renew('mycompany.io', 1);
```

#### `dns.quickBuy(domain, opts?)`

Search and buy in a single call — only registers if available.

```js
await dns.quickBuy('mycompany.io', { privacy: true });
```

#### `dns.setupWeb(domain, ip)`

Create an A record for `@` and a CNAME for `www` in one call.

```js
await dns.setupWeb('mycompany.io', '1.2.3.4');
```

#### `dns.exportRecords(domain)`

Export all DNS records for a domain as an array.

```js
const records = await dns.exportRecords('mycompany.io');
```

#### `dns.importRecords(domain, records)`

Bulk-import DNS records from an array.

```js
await dns.importRecords('mycompany.io', [
  { type: 'A', name: '@', value: '1.2.3.4', ttl: 300 },
  { type: 'MX', name: '@', value: 'mail.mycompany.io', priority: 10 }
]);
```

---

### DNS Records — `dns.records`

#### `dns.records.list(domain)`

```js
const recs = await dns.records.list('mycompany.io');
```

#### `dns.records.add(domain, record)`

```js
const rec = await dns.records.add('mycompany.io', {
  type: 'A',
  host: '@',   // or name
  value: '1.2.3.4',
  ttl: 300
});
```

Supported `type` values: `A`, `AAAA`, `CNAME`, `MX`, `TXT`, `NS`, `SRV`, `CAA`.

#### `dns.records.update(domain, id, record)`

```js
await dns.records.update('mycompany.io', 'record-id', { value: '5.6.7.8' });
```

#### `dns.records.delete(domain, id)`

```js
await dns.records.delete('mycompany.io', 'record-id');
```

---

### Nameservers — `dns.nameservers`

#### `dns.nameservers.set(domain, ns[])`

```js
await dns.nameservers.set('mycompany.io', ['ns1.cloudflare.com', 'ns2.cloudflare.com']);
```

#### `dns.nameservers.list(domain)`

```js
const ns = await dns.nameservers.list('mycompany.io');
```

---

### Contacts — `dns.contacts`

#### `dns.contacts.list()`

```js
const contacts = await dns.contacts.list();
```

#### `dns.contacts.add(contact)`

```js
const contact = await dns.contacts.add({
  first_name: 'Jane', last_name: 'Doe',
  email: 'jane@example.com',
  address: '123 Main St', city: 'Austin',
  state: 'TX', zip: '78701', country: 'US',
  phone: '+15125550100'
});
```

#### `dns.contacts.update(id, contact)`

```js
await dns.contacts.update('contact-id', { email: 'new@example.com' });
```

#### `dns.contacts.delete(id)`

```js
await dns.contacts.delete('contact-id');
```

#### `dns.contacts.associate(id, domain)`

```js
await dns.contacts.associate('contact-id', 'mycompany.io');
```

---

### Account — `dns.account`

#### `dns.account.me()`

```js
const user = await dns.account.me();
```

#### `dns.account.preferences(prefs)`

```js
await dns.account.preferences({ default_privacy: true, default_auto_renew: true });
```

#### `dns.account.audit(page?, limit?)`

```js
const log = await dns.account.audit(1, 50);
```

---

## CLI Reference

Set environment variables before using the CLI:

```bash
export SAAC_USER_API_KEY=your_api_key
export SAAC_USER_EMAIL=your@email.com
```

### Global Options

| Flag | Description |
|---|---|
| `--json` | Output raw JSON |
| `--quiet` | Minimal output |
| `--verbose` | Verbose output |

### Domain Commands

```bash
# Search domain availability
saac_dns search mycompany.com mycompany.io

# Register a domain
saac_dns buy mycompany.io --years 1 --privacy --auto-renew

# List all your domains
saac_dns list

# Get domain details
saac_dns info mycompany.io

# WHOIS lookup
saac_dns whois mycompany.io

# Renew a domain
saac_dns renew mycompany.io --years 1

# Show registration prices
saac_dns prices
saac_dns prices --tld com,io,dev

# Toggle auto-renewal
saac_dns auto-renew mycompany.io on
saac_dns auto-renew mycompany.io off

# Toggle WHOIS privacy
saac_dns privacy mycompany.io on

# Set up domain forwarding
saac_dns forward mycompany.io https://myapp.com
```

### DNS Record Commands

```bash
# List DNS records
saac_dns records list mycompany.io
saac_dns records list mycompany.io --type A

# Add a record
saac_dns records add mycompany.io A @ 1.2.3.4 --ttl 300
saac_dns records add mycompany.io MX @ mail.mycompany.io --priority 10
saac_dns records add mycompany.io TXT @ "v=spf1 include:sendgrid.net ~all"

# Bulk import from JSON file
saac_dns records add mycompany.io A @ 0.0.0.0 --file ./records.json

# Update a record
saac_dns records update mycompany.io <record-id> --value 5.6.7.8

# Delete a record
saac_dns records delete mycompany.io <record-id>
```

### Nameserver Commands

```bash
# List nameservers
saac_dns ns list mycompany.io

# Set nameservers
saac_dns ns set mycompany.io ns1.cloudflare.com ns2.cloudflare.com
```

### Contact Commands

```bash
# List contacts
saac_dns contacts list

# Add a contact
saac_dns contacts add --first-name Jane --last-name Doe \
  --email jane@example.com --country US --phone +15125550100

# Assign contact to domain
saac_dns contacts set mycompany.io --contact <contact-id>
```

### Account Commands

```bash
# View/set config and preferences
saac_dns config
saac_dns config --privacy on --auto-renew on --ttl 300
```

---

## Error Handling

The SDK throws typed errors you can catch and distinguish:

```js
const {
  AuthenticationError,
  DomainNotFoundError,
  DomainUnavailableError,
  ValidationError,
  InsufficientFundsError,
  SaacDnsError
} = require('@startanaicompany/saac_dns');

try {
  await dns.buy('taken.com');
} catch (err) {
  if (err instanceof DomainUnavailableError) {
    console.error('Domain is not available:', err.message);
  } else if (err instanceof InsufficientFundsError) {
    console.error('Top up your account balance:', err.message);
  } else if (err instanceof AuthenticationError) {
    console.error('Check SAAC_USER_API_KEY and SAAC_USER_EMAIL:', err.message);
  } else if (err instanceof SaacDnsError) {
    console.error(`Error (code ${err.code}):`, err.message);
  } else {
    throw err;
  }
}
```

| Error Class | Code | Trigger |
|---|---|---|
| `AuthenticationError` | 110 | Invalid or missing API key / email |
| `DomainNotFoundError` | 200 | Domain does not exist on the account |
| `DomainUnavailableError` | 261 | Domain is already registered |
| `ValidationError` | 108 | Bad request parameters |
| `InsufficientFundsError` | 280 | Insufficient account balance |
| `SaacDnsError` | varies | Other API errors |

---

## TypeScript

The package ships with full TypeScript definitions:

```ts
import * as dns from '@startanaicompany/saac_dns';
import type { SearchResult, Domain, DnsRecord } from '@startanaicompany/saac_dns';

const results: SearchResult[] = await dns.search(['mycompany.io']);
```

---

## License

MIT — Copyright (c) 2026 Start An AI Company (SAAC)