2// Moniker Domain Registration API
3// Documentation: https://testapi.moniker.com
5const axios = require('axios');
7// Configure API credentials and base URL
12 const isProduction = process.env.NODE_ENV === 'production';
14 // Moniker requires UserKey and ApiKey for authentication
15 const userKey = process.env.MONIKER_USER_KEY || 'monikeruser';
16 const apiKey = process.env.MONIKER_API_KEY || 'monikerapi';
17 const apiPassword = process.env.MONIKER_API_PASSWORD;
18 const baseURL = process.env.MONIKER_BASE_URL || 'https://testapi.moniker.com';
20 if (userKey === 'monikeruser' && apiKey === 'monikerapi') {
21 console.log('[Moniker] Using TEST API with default credentials');
22 } else if (isProduction) {
23 console.log('[Moniker] Using PRODUCTION API');
25 console.log('[Moniker] Using configured API credentials');
37 * Make a request to the Moniker API
38 * @param {string} endpoint - API endpoint (e.g., 'Domain/Check')
39 * @param {object} params - Additional query parameters
40 * @returns {Promise<object>} - API response
42async function makeRequest(endpoint, params = {}) {
43 const config = getConfig();
46 const requestParams = {
47 UserKey: config.userKey,
48 ApiKey: config.apiKey,
52 // Add ApiPassword if available (some endpoints may need it)
53 if (config.apiPassword) {
54 requestParams.ApiPassword = config.apiPassword;
57 const response = await axios.get(`${config.baseURL}/${endpoint}`, {
58 params: requestParams,
62 // Moniker API returns key=value pairs, one per line
63 // Parse this format into an object
65 const lines = response.data.split('\n');
67 for (const line of lines) {
68 const trimmed = line.trim();
69 if (trimmed && trimmed.includes('=')) {
70 const [key, ...valueParts] = trimmed.split('=');
71 data[key] = valueParts.join('='); // Rejoin in case value contains =
77 console.error(`[Moniker] API Error on ${endpoint}:`, error.message);
79 console.error('[Moniker] Response:', error.response.data);
87 * Check domain availability
88 * @param {string} domain - Domain name to check
89 * @returns {Promise<object>} - Availability info
91async function checkDomain(domain) {
93 const result = await makeRequest('Domain/Check', {
97 // Moniker API response fields:
98 // status=AVAILABLE or UNAVAILABLE
100 // price_ispremium=YES/NO
101 const available = result.status === 'AVAILABLE';
104 domain: result.domain || domain,
105 available: available,
106 status: result.status || 'unknown',
107 isPremium: result.price_ispremium === 'YES',
108 minRegPeriod: result.minregperiod,
109 maxRegPeriod: result.maxregperiod,
110 price: null, // Pricing requires separate API call
115 console.error('[Moniker] Error checking domain:', error.message);
121 * Check multiple domains at once
122 * @param {Array<string>} domains - Array of domain names
123 * @returns {Promise<Array<object>>} - Array of availability info
125async function checkDomains(domains) {
127 // Check domains sequentially for test API
128 const results = await Promise.all(
129 domains.map(domain => checkDomain(domain))
133 console.error('[Moniker] Error checking multiple domains:', error.message);
140 * @param {object} params - Registration parameters
141 * @returns {Promise<object>} - Registration result
143async function registerDomain(params) {
155 throw new Error('Owner contact information is required');
159 // Note: Test API may not support actual registration
160 // This is a placeholder for the production implementation
161 const result = await makeRequest('Domain/Register', {
164 // Add contact and nameserver parameters based on Moniker API docs
169 status: result.Status || 'pending',
170 registration_date: new Date().toISOString(),
171 expiration_date: new Date(Date.now() + (years * 365 * 24 * 60 * 60 * 1000)).toISOString(),
172 registrar: 'moniker',
176 console.error('[Moniker] Error registering domain:', error.message);
184 * @param {string} domain - Domain name
185 * @returns {Promise<object>} - Domain information
187async function getDomainInfo(domain) {
189 const result = await makeRequest('Domain/Info', {
195 status: result.Status || 'unknown',
196 registration_date: result.CreatedDate || null,
197 expiration_date: result.ExpirationDate || null,
198 nameservers: result.Nameservers || [],
199 registrar: 'moniker',
203 console.error('[Moniker] Error getting domain info:', error.message);
209 * Update domain nameservers
210 * @param {string} domain - Domain name
211 * @param {Array<string>} nameservers - Array of nameserver hostnames
212 * @returns {Promise<object>} - Update result
214async function updateNameservers(domain, nameservers) {
216 const result = await makeRequest('Domain/UpdateNameservers', {
218 Nameservers: nameservers.join(',')
223 nameservers: nameservers,
228 console.error('[Moniker] Error updating nameservers:', error.message);
234 * Get DNS zone records
235 * @param {string} domain - Domain name
236 * @returns {Promise<Array>} - DNS records
238async function getDNSRecords(domain) {
240 const result = await makeRequest('DNS/List', {
244 // Convert API response to standard format
245 return result.Records || [];
247 console.error('[Moniker] Error getting DNS records:', error.message);
248 // Return empty array if zone doesn't exist
254 * Update DNS zone record
255 * @param {string} domain - Domain name
256 * @param {object} record - DNS record
257 * @returns {Promise<object>} - Update result
259async function updateDNSRecord(domain, record) {
261 const result = await makeRequest('DNS/Update', {
266 TTL: record.ttl || 3600,
267 Priority: record.priority
277 console.error('[Moniker] Error updating DNS record:', error.message);
284 * @param {object} params - Transfer parameters
285 * @returns {Promise<object>} - Transfer result
287async function transferDomain(params) {
296 throw new Error('Authorization code (EPP code) is required for transfer');
300 const result = await makeRequest('Domain/Transfer', {
308 status: 'transfer_pending',
309 registrar: 'moniker',
313 console.error('[Moniker] Error transferring domain:', error.message);
320 * @param {string} domain - Domain name
321 * @param {number} years - Years to renew for
322 * @returns {Promise<object>} - Renewal result
324async function renewDomain(domain, years = 1) {
326 const result = await makeRequest('Domain/Renew', {
334 expiration_date: result.ExpirationDate || null,
338 console.error('[Moniker] Error renewing domain:', error.message);
344 * Lock domain (enable transfer lock)
345 * @param {string} domain - Domain name
346 * @returns {Promise<object>} - Lock result
348async function lockDomain(domain) {
350 const result = await makeRequest('Domain/SetLock', {
362 console.error('[Moniker] Error locking domain:', error.message);
368 * Unlock domain (disable transfer lock)
369 * @param {string} domain - Domain name
370 * @returns {Promise<object>} - Unlock result
372async function unlockDomain(domain) {
374 const result = await makeRequest('Domain/SetLock', {
386 console.error('[Moniker] Error unlocking domain:', error.message);
392 * Get domain auth/transfer code (EPP code)
393 * @param {string} domain - Domain name
394 * @returns {Promise<object>} - Auth code result
396async function getAuthCode(domain) {
398 const result = await makeRequest('Domain/GetAuthCode', {
404 auth_code: result.AuthCode || result.EPPCode || null,
409 console.error('[Moniker] Error getting auth code:', error.message);
415 * Enable/disable auto-renew
416 * @param {string} domain - Domain name
417 * @param {boolean} enabled - Enable or disable auto-renew
418 * @returns {Promise<object>} - Auto-renew update result
420async function setAutoRenew(domain, enabled) {
422 const result = await makeRequest('Domain/SetAutoRenew', {
424 AutoRenew: enabled ? 'true' : 'false'
434 console.error('[Moniker] Error setting auto-renew:', error.message);
440 * Get domain contact information
441 * @param {string} domain - Domain name
442 * @returns {Promise<object>} - Contact information
444async function getContacts(domain) {
446 const result = await makeRequest('Domain/GetContacts', {
452 registrant: result.Registrant || null,
453 admin: result.Admin || null,
454 tech: result.Tech || null,
455 billing: result.Billing || null,
459 console.error('[Moniker] Error getting contacts:', error.message);
465 * Get all domains in the Moniker account
466 * @returns {Promise<Array>} - List of all domains
468async function getAllDomains() {
470 console.log('[Moniker] Fetching all domains from account');
472 // Moniker API endpoint to list all domains
473 const result = await makeRequest('Domain/GetDomains', {});
475 if (!result || !result.Domains) {
476 console.log('[Moniker] No domains found or unexpected response format');
480 // Handle both single domain (object) and multiple domains (array)
482 if (Array.isArray(result.Domains.Domain)) {
483 domains = result.Domains.Domain;
484 } else if (result.Domains.Domain) {
485 domains = [result.Domains.Domain];
488 console.log(`[Moniker] Found ${domains.length} domains`);
490 // Map to consistent format with domain name
491 return domains.map(domain => ({
492 name: domain.Name || domain.DomainName,
493 status: domain.Status,
494 expiration_date: domain.ExpirationDate,
495 registration_date: domain.RegistrationDate,
496 auto_renew: domain.AutoRenew === 'true',
497 locked: domain.Locked === 'true',
501 console.error('[Moniker] Error getting all domains:', error.message);
502 // Return empty array on error rather than throwing