1. API Overview

The Countries REST API provides rich, structured JSON data for 250 global countries and territories. Features include ISO code search, continent/region filtering, capital lookup, currency & language filtering, population stats, random country generator, and rate-limiting security.


Base URL: https://freecountries.vercel.app/api/v1

2. Authentication

All data endpoints require an API Key. You can pass your key via HTTP Header (Recommended) or Query Parameter:

Method Format Example
HTTP Header x-api-key: KEY x-api-key: demo-key-12345
Query Parameter ?apiKey=KEY https://freecountries.vercel.app/api/v1/countries?apiKey=demo-key-12345

Default Demo Key: demo-key-12345

3. Complete API Endpoint Reference

POST /api/v1/keys/generate

Generates a new custom 32-character API key for client applications.

POST /api/v1/keys/generate
Content-Type: application/json

{ "name": "My Web Application" }
GET /api/v1/countries

Retrieve countries list with support for search, region filtering, field projection, sorting, and pagination.

GET /api/v1/countries?search=japan&limit=5
GET /api/v1/countries/code/:code

Get single country details by ISO Alpha-2, ISO Alpha-3, Numeric Code, or common name (e.g. USA, US, 840, Japan).

GET /api/v1/countries/code/JPN
GET /api/v1/countries/region/:region

Filter countries by region (Asia, Europe, Americas, Africa, Oceania, Polar).

GET /api/v1/countries/region/Europe
GET /api/v1/countries/capital/:capital

Filter countries by capital city name.

GET /api/v1/countries/capital/Tokyo
GET /api/v1/countries/currency/:currency

Filter countries using a specific currency code (e.g. USD, EUR, JPY, GBP).

GET /api/v1/countries/currency/EUR
GET /api/v1/countries/language/:lang

Filter countries by language ISO code or language name (e.g. eng, spa, fra, ara, deu).

GET /api/v1/countries/language/eng
GET /api/v1/countries/random

Returns a single randomly selected country object.

GET /api/v1/countries/random
GET /api/v1/countries/stats

Get global metrics: total 250 countries count, 8.01B total population, land area totals, continent breakdown, and top 5 populated countries.

GET /api/v1/countries/stats

4. Query Parameters Guide

Parameter Type Description Example
search String Search name, capital, or ISO code ?search=japan
region String Filter by continent/region ?region=Asia
subregion String Filter by subregion ?subregion=Western Europe
landlocked Boolean Filter landlocked countries ?landlocked=true
sort String Sort field (name, population, area) ?sort=population
order String Sort direction (asc or desc) ?order=desc
page Number Page number (Default: 1) ?page=1
limit Number Items per page (Default: 10, Max: 300) ?limit=250
fields String Comma-separated field projection ?fields=name,capital,population

5. Language Filter Codes List

You can filter countries by language code or language name via /api/v1/countries/language/:lang:

eng βž” English (92 Countries)
fra βž” French (46 Countries)
ara βž” Arabic (29 Countries)
spa βž” Spanish (24 Countries)
por βž” Portuguese (10 Countries)
deu βž” German (5 Countries)
zho βž” Chinese (3 Countries)
ita βž” Italian (4 Countries)
rus βž” Russian (5 Countries)
jpn βž” Japanese (1 Country)

6. Postman & Integration Guide

JavaScript Fetch API

fetch('http://localhost:3000/api/v1/countries?limit=250', {
  headers: {
    'x-api-key': 'demo-key-12345'
  }
})
  .then(res => res.json())
  .then(data => console.log(data));

Axios

import axios from 'axios';

axios.get('http://localhost:3000/api/v1/countries?limit=250', {
  headers: {
    'x-api-key': 'demo-key-12345'
  }
})
  .then(response => console.log(response.data));

Postman Setup Instructions

Method 1: Headers Tab (Recommended)

  • Key: x-api-key
  • Value: demo-key-12345

Method 2: Params Tab

  • Key: apiKey
  • Value: demo-key-12345

7. Response Status & Error Codes

Status Code Error Code Description
200 OK - Successful request execution
201 Created - API Key created via POST /keys/generate
401 Unauthorized MISSING_API_KEY API Key header or query param is missing
403 Forbidden INVALID_API_KEY API Key is invalid or expired
404 Not Found NOT_FOUND / COUNTRY_NOT_FOUND Endpoint or resource not found
429 Too Many Requests RATE_LIMIT_EXCEEDED Exceeded rate limit (100 reqs / 15 mins)

8. Rate Limiting & Quotas Guide

To guarantee high availability, system stability, and fair usage across all applications, the Countries API enforces IP-based rate limiting on all /api/* endpoints.

Quota Parameter Limit Value Scope
Maximum Requests 100 requests Per IP address per window
Window Duration 15 minutes (900,000 ms) Sliding time window

Response Headers

Every response returned by the API contains HTTP response headers indicating your remaining request quota in real-time:

Header Name Description Example
X-RateLimit-Limit Maximum allowed requests per 15-minute window 100
X-RateLimit-Remaining Remaining requests available in the current window 98
X-RateLimit-Reset Unix timestamp (seconds) when your limit resets 1770894900
Retry-After Returned when rate limit is exceeded (seconds to wait) 900

HTTP 429 Error Structure

When an application exceeds the 100 requests limit within 15 minutes, the API responds with HTTP 429 Too Many Requests and the following JSON payload:

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests from this IP, please try again after 15 minutes."
  }
}

Handling Rate Limits in Frontend & Backend Code

JavaScript Fetch API (Handling 429 & Retry):

async function fetchCountriesWithRetry(endpoint, apiKey, retries = 3) {
  for (let attempt = 0; attempt < retries; attempt++) {
    const res = await fetch(endpoint, {
      headers: { 'x-api-key': apiKey }
    });

    if (res.status === 429) {
      const retryAfterSeconds = parseInt(res.headers.get('Retry-After') || '60', 10);
      console.warn(`Rate limit reached. Retrying in ${retryAfterSeconds}s...`);
      await new Promise(resolve => setTimeout(resolve, retryAfterSeconds * 1000));
      continue;
    }

    return await res.json();
  }
  throw new Error('Max retries exceeded due to rate limits.');
}

Axios Interceptor Handling:

axios.interceptors.response.use(
  response => response,
  async error => {
    if (error.response && error.response.status === 429) {
      const waitSeconds = error.response.headers['retry-after'] || 60;
      await new Promise(r => setTimeout(r, waitSeconds * 1000));
      return axios.request(error.config);
    }
    return Promise.reject(error);
  }
);

Best Practices

  • Cache API Responses: Static country information (e.g., capitals, ISO codes) rarely changes. Store results in localStorage or server cache (Redis/Memory) to minimize API requests.
  • Use Field Filtering: Request only needed fields with ?fields=name,capital,population to keep bandwidth low and responses ultra-fast.
  • Monitor Remaining Quota: Read the X-RateLimit-Remaining header in your client application to throttle traffic before hitting HTTP 429 errors.