logo
Getting started

Pricing Model

How multi-year pricing, operations, and currency units work

Domain prices are returned by the availability endpoints (client.search.checkAvailability / /search/availability) under pricingDetails. This page explains how to read those details and compute the charge for a given duration and operation.

All amounts are in USD.

Where pricing comes from

A successful availability check returns pricingDetails for the domain:

{
  "domain": "example.com",
  "availability": true,
  "pricingDetails": {
    "registrationPrice": { "type": "PER_YEAR", "price": { "amount": 12, "currency": "USD" } },
    "renewalPrice":      { "type": "PER_YEAR", "price": { "amount": 12, "currency": "USD" } },
    "importPrice":       { "type": "PER_YEAR", "price": { "amount": 8,  "currency": "USD" } }
  },
  "durationValidationInYears": { "min": 1, "max": 10 }
}

durationValidationInYears tells you the valid duration range for that specific domain. Across the platform durations are always integers between 1 and 10.

Operations

Each operation reads a different price from pricingDetails:

OperationPrice used
REGISTERregistrationPrice for every year.
RENEWrenewalPrice for every year.
IMPORTimportPrice for the first year, then renewalPrice for the rest.

The IMPORT split exists because an EPP transfer only adds a single year, so any additional years are charged at the renewal rate.

Pricing types

Each price (registrationPrice, renewalPrice, importPrice) is one of two shapes.

PER_YEAR

A flat per-year price. The total is simply the yearly amount times the duration.

{ "type": "PER_YEAR", "price": { "amount": 12, "currency": "USD" } }
total = price.amount * durationInYears

MULTI_YEAR

An explicit price map keyed by the number of years. Only the listed durations are valid — there is no interpolation, and a duration without an entry is rejected.

{
  "type": "MULTI_YEAR",
  "price": {
    "1": { "amount": 12, "currency": "USD" },
    "2": { "amount": 22, "currency": "USD" },
    "3": { "amount": 30, "currency": "USD" }
  }
}
total = price[durationInYears].amount   // must be an exact key match

Computing a charge

The logic below mirrors how the backend computes charges from pricingDetails, including the IMPORT first-year split.

type PriceWithCurrency = { amount: number; currency: 'USD' };
type PricingDetails =
  | { type: 'PER_YEAR'; price: PriceWithCurrency }
  | { type: 'MULTI_YEAR'; price: Record<string, PriceWithCurrency> };

function chargeForDuration(pricing: PricingDetails, years: number): number {
  if (!Number.isInteger(years) || years < 1 || years > 10) {
    throw new Error('Duration must be an integer between 1 and 10');
  }

  if (pricing.type === 'PER_YEAR') {
    return pricing.price.amount * years;
  }

  const entry = pricing.price[String(years)];
  if (!entry) {
    throw new Error(`No multi-year price for ${years} year(s)`);
  }
  return entry.amount;
}

function computeCharge(
  details: {
    registrationPrice: PricingDetails;
    renewalPrice: PricingDetails;
    importPrice: PricingDetails;
  },
  years: number,
  operation: 'REGISTER' | 'RENEW' | 'IMPORT',
): number {
  if (operation === 'REGISTER') {
    return chargeForDuration(details.registrationPrice, years);
  }
  if (operation === 'RENEW') {
    return chargeForDuration(details.renewalPrice, years);
  }

  // IMPORT: first year at importPrice, remaining years at renewalPrice.
  const firstYear = chargeForDuration(details.importPrice, 1);
  if (years === 1) {
    return firstYear;
  }
  return firstYear + chargeForDuration(details.renewalPrice, years - 1);
}

Currency and units

  • All prices are in USD.
  • USD amounts can carry fractional dollars, so convert to integer cents for payments or storage: cents = round(usd * 100) and back with usd = cents / 100.

End-to-end example

Fetch availability, then compute the register charge for 2 years:

import { createNamefiClient } from '@namefi/api-client';

const client = createNamefiClient({
  authentication: {
    apiKey: process.env.NAMEFI_API_KEY!,
    type: 'API_KEY',
  },
  logger: true,
});

const info = await client.search.checkAvailability({ domain: 'example.com' });

if (info.availability && info.pricingDetails) {
  const total = computeCharge(info.pricingDetails, 2, 'REGISTER');
  console.log(`2-year registration: $${total}`);
}

On this page