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
Generates a new custom 32-character API key for client applications.
POST /api/v1/keys/generate
Content-Type: application/json
{ "name": "My Web Application" }
Retrieve countries list with support for search, region filtering, field projection, sorting, and pagination.
GET /api/v1/countries?search=japan&limit=5
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
Filter countries by region (Asia, Europe, Americas, Africa, Oceania, Polar).
GET /api/v1/countries/region/Europe
Filter countries by capital city name.
GET /api/v1/countries/capital/Tokyo
Filter countries using a specific currency code (e.g. USD, EUR, JPY, GBP).
GET /api/v1/countries/currency/EUR
Filter countries by language ISO code or language name (e.g. eng, spa, fra, ara, deu).
GET /api/v1/countries/language/eng
Returns a single randomly selected country object.
GET /api/v1/countries/random
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
localStorageor server cache (Redis/Memory) to minimize API requests. - Use Field Filtering: Request only needed fields with
?fields=name,capital,populationto keep bandwidth low and responses ultra-fast. - Monitor Remaining Quota: Read the
X-RateLimit-Remainingheader in your client application to throttle traffic before hitting HTTP 429 errors.