About SolvyAtlas API
SolvyAtlas API provides comprehensive geographic data for countries, governorates, and cities in both English and Arabic. Access structured location data with bilingual support, perfect for building address forms, location pickers, shipping calculators, and regional analytics applications.
📍 Currently Available
🚀 More countries coming soon! Stay tuned for updates.
🎉 Free Access
The SolvyAtlas API is currently completely free to use during our launch period. Get your API credentials and start building today!
ℹ️ Please note: Subscription fees may be introduced in the future. Early adopters will receive special benefits and advance notice of any pricing changes.
API Overview
SolvyAtlas API uses secure HMAC-SHA256 authentication for all client endpoints. After requesting access, you will receive your API credentials for free.
Base URL
https://atlasapi.solvytix.com
API Keys Format
You will receive two types of keys:
pk_aB3xYz9mN7qWe8rT5yU2iO4pL6kJ1hG0• Sent in request headers to identify your application
• Can be logged and exposed (not sensitive)
sk_dE6fG8hJ2kL4mN9oP1qR3sT5uV7wX0yZ• ⚠️ MUST BE KEPT SECRET - Used locally to sign requests
• ⚠️ NEVER sent to server or exposed in client-side code
Language Selection
Specify your preferred language by including the Accept-Language header:
Accept-Language: en // For English
Accept-Language: ar // For Arabic
Endpoints without /with-translations return data in the language specified in the header. Endpoints with /with-translations return data in both English and Arabic simultaneously.
All endpoints return application/json.
🔐 HMAC Authentication
SolvyAtlas API uses HMAC-SHA256 for secure request authentication. Each request must include three authentication headers.
Required Headers
Every authenticated request MUST include these headers:
| Header | Description | Example |
|---|---|---|
X-Api-PublicKey |
Your public key | pk_aB3xYz... |
X-Api-Timestamp |
Unix timestamp (seconds) | 1704451800 |
X-Api-Signature |
HMAC-SHA256 signature (Base64) | 8mF3nQ5pR7t... |
How HMAC Authentication Works
- Client receives Public Key and Secret Key
- For each request, Client creates a signature using:
- Current Unix timestamp (seconds)
- Secret Key
- Client sends request with Public Key, Timestamp, and Signature
- Server validates:
- Public Key exists and is active
- Timestamp is within 5-minute window
- Signature matches expected value
Signature Calculation
Generate the signature using this algorithm:
Step 1: Get Current Timestamp
timestamp = current Unix time in seconds
Step 2: Create Payload
payload = timestamp (as string)
Step 3: Compute HMAC-SHA256
signature_bytes = HMAC-SHA256(secret_key, payload)
Step 4: Encode to Base64
signature = Base64Encode(signature_bytes)
Step 5: Send Request with Headers
X-Api-PublicKey: your_public_key
X-Api-Timestamp: timestamp
X-Api-Signature: signature
Accept-Language: en or ar
⚠️ Important Rules
- Timestamp Format: Unix timestamp in seconds (not milliseconds)
- Time Window: Must be within 5 minutes of server time
- All Client Requests: Payload = timestamp only (all endpoints are GET)
Error Responses
| Status Code | Error | Cause |
|---|---|---|
| 401 | Unauthorized | Missing/invalid headers, inactive key, wrong signature |
| 401 | Timestamp too old | Request timestamp >5 minutes old |
| 429 | Rate limit exceeded | Too many requests per minute |
Country Endpoints
Response Example:
[
{
"id": 1,
"code": "EG",
"name": "Egypt"
}
]
Response Example:
[
{
"id": 1,
"code": "EG",
"translations": [
{
"language": "en",
"name": "Egypt"
},
{
"language": "ar",
"name": "مصر"
}
]
}
]
Parameters:
id (path) - Country ID (integer)Response Example:
{
"id": 1,
"code": "EG",
"name": "Egypt"
}
Governorate Endpoints
Response Example:
[
{
"id": 1,
"countryId": 1,
"name": "Cairo"
}
]
Response Example:
[
{
"id": 1,
"countryId": 1,
"translations": [
{
"language": "en",
"name": "Cairo"
},
{
"language": "ar",
"name": "القاهرة"
}
]
}
]
Parameters:
id (path) - Governorate ID (integer)Response Example:
{
"id": 1,
"countryId": 1,
"name": "Cairo"
}
City Endpoints
Response Example:
[
{
"id": 1,
"governorateId": 1,
"name": "Nasr City"
}
]
Response Example:
[
{
"id": 1,
"governorateId": 1,
"translations": [
{
"language": "en",
"name": "Nasr City"
},
{
"language": "ar",
"name": "مدينة نصر"
}
]
}
]
Parameters:
governrateId (path) - Governorate ID (integer)Response Example:
[
{
"id": 1,
"governorateId": 1,
"translations": [
{
"language": "en",
"name": "Nasr City"
},
{
"language": "ar",
"name": "مدينة نصر"
}
]
}
]
Parameters:
governorateId (path) - Governorate ID (integer)Response Example:
[
{
"id": 1,
"governorateId": 1,
"name": "Nasr City"
}
]
Parameters:
id (path) - City ID (integer)Response Example:
{
"id": 1,
"governorateId": 1,
"name": "Nasr City"
}
Usage Examples
// Browser JavaScript - HMAC-SHA256 Authentication using Web Crypto API
class AtlasApiClient {
constructor(publicKey, secretKey) {
this.publicKey = publicKey;
this.secretKey = secretKey;
this.baseURL = 'https://atlasapi.solvytix.com/api/client';
}
async generateSignature(timestamp, body = '') {
const payload = `${timestamp}${body}`;
const encoder = new TextEncoder();
// Convert secret key to crypto key
const keyData = encoder.encode(this.secretKey);
const key = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
// Sign the payload
const messageData = encoder.encode(payload);
const signature = await crypto.subtle.sign('HMAC', key, messageData);
// Convert to Base64
return btoa(String.fromCharCode(...new Uint8Array(signature)));
}
async getCountries(language = 'en') {
try {
const timestamp = Math.floor(Date.now() / 1000);
const signature = await this.generateSignature(timestamp);
const response = await fetch(`${this.baseURL}/countries`, {
headers: {
'X-Api-PublicKey': this.publicKey,
'X-Api-Timestamp': timestamp.toString(),
'X-Api-Signature': signature,
'Accept-Language': language // 'en' for English, 'ar' for Arabic
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error fetching countries:', error);
throw error;
}
}
async getCitiesByGovernorate(governorateId, language = 'en') {
try {
const timestamp = Math.floor(Date.now() / 1000);
const signature = await this.generateSignature(timestamp);
const response = await fetch(
`${this.baseURL}/cities/governorate/${governorateId}`,
{
headers: {
'X-Api-PublicKey': this.publicKey,
'X-Api-Timestamp': timestamp.toString(),
'X-Api-Signature': signature,
'Accept-Language': language
}
}
);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error fetching cities:', error);
throw error;
}
}
}
// Example usage
const client = new AtlasApiClient(
'pk_aB3xYz9mN7qWe8rT5yU2iO4pL6kJ1hG0',
'sk_dE6fG8hJ2kL4mN9oP1qR3sT5uV7wX0yZ'
);
// Get countries
client.getCountries('en')
.then(data => console.log('Countries:', data))
.catch(err => console.error(err));
using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
public class AtlasApiClient
{
private readonly HttpClient _httpClient;
private readonly string _publicKey;
private readonly string _secretKey;
public AtlasApiClient(string publicKey, string secretKey)
{
_publicKey = publicKey;
_secretKey = secretKey;
_httpClient = new HttpClient();
}
private string GenerateSignature(long timestamp, string body = "")
{
var payload = $"{timestamp}{body}";
var keyBytes = Encoding.UTF8.GetBytes(_secretKey);
var messageBytes = Encoding.UTF8.GetBytes(payload);
using var hmac = new HMACSHA256(keyBytes);
var hashBytes = hmac.ComputeHash(messageBytes);
return Convert.ToBase64String(hashBytes);
}
private long GetUnixTimestamp()
{
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
}
public async Task<string> GetCountriesAsync(string language = "en")
{
var timestamp = GetUnixTimestamp();
var signature = GenerateSignature(timestamp);
var request = new HttpRequestMessage(HttpMethod.Get,
"https://atlasapi.solvytix.com/api/client/countries");
request.Headers.Add("X-Api-PublicKey", _publicKey);
request.Headers.Add("X-Api-Timestamp", timestamp.ToString());
request.Headers.Add("X-Api-Signature", signature);
request.Headers.Add("Accept-Language", language);
var response = await _httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
// Example usage
var client = new AtlasApiClient(
"pk_aB3xYz9mN7qWe8rT5yU2iO4pL6kJ1hG0",
"sk_dE6fG8hJ2kL4mN9oP1qR3sT5uV7wX0yZ"
);
var countries = await client.GetCountriesAsync("en");
import hmac
import hashlib
import base64
import time
import requests
class AtlasApiClient:
def __init__(self, public_key, secret_key):
self.public_key = public_key
self.secret_key = secret_key
self.base_url = "https://atlasapi.solvytix.com/api/client"
def _generate_signature(self, timestamp, body=''):
"""Generate HMAC-SHA256 signature"""
payload = f"{timestamp}{body}"
signature = hmac.new(
self.secret_key.encode('utf-8'),
payload.encode('utf-8'),
hashlib.sha256
).digest()
return base64.b64encode(signature).decode('utf-8')
def _get_timestamp(self):
"""Get current Unix timestamp in seconds"""
return int(time.time())
def get_countries(self, language='en'):
"""
Get countries list
language: 'en' for English, 'ar' for Arabic
"""
timestamp = self._get_timestamp()
signature = self._generate_signature(timestamp)
headers = {
'X-Api-PublicKey': self.public_key,
'X-Api-Timestamp': str(timestamp),
'X-Api-Signature': signature,
'Accept-Language': language
}
response = requests.get(
f'{self.base_url}/countries',
headers=headers
)
response.raise_for_status()
return response.json()
# Example usage
client = AtlasApiClient(
'pk_aB3xYz9mN7qWe8rT5yU2iO4pL6kJ1hG0',
'sk_dE6fG8hJ2kL4mN9oP1qR3sT5uV7wX0yZ'
)
countries = client.get_countries('en')
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.URI;
import java.time.Instant;
import java.util.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class AtlasApiClient {
private final HttpClient httpClient;
private final String publicKey;
private final String secretKey;
private static final String BASE_URL =
"https://atlasapi.solvytix.com/api/client";
public AtlasApiClient(String publicKey, String secretKey) {
this.publicKey = publicKey;
this.secretKey = secretKey;
this.httpClient = HttpClient.newHttpClient();
}
private String generateSignature(long timestamp, String body)
throws Exception {
String payload = timestamp + body;
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(
secretKey.getBytes("UTF-8"), "HmacSHA256"
);
hmac.init(keySpec);
byte[] hash = hmac.doFinal(payload.getBytes("UTF-8"));
return Base64.getEncoder().encodeToString(hash);
}
public String getCountries(String language) throws Exception {
long timestamp = Instant.now().getEpochSecond();
String signature = generateSignature(timestamp, "");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(BASE_URL + "/countries"))
.header("X-Api-PublicKey", publicKey)
.header("X-Api-Timestamp", String.valueOf(timestamp))
.header("X-Api-Signature", signature)
.header("Accept-Language", language)
.GET()
.build();
HttpResponse<String> response = httpClient.send(
request, HttpResponse.BodyHandlers.ofString()
);
return response.body();
}
public static void main(String[] args) throws Exception {
AtlasApiClient client = new AtlasApiClient(
"pk_aB3xYz9mN7qWe8rT5yU2iO4pL6kJ1hG0",
"sk_dE6fG8hJ2kL4mN9oP1qR3sT5uV7wX0yZ"
);
String countries = client.getCountries("en");
System.out.println(countries);
}
}
const crypto = require('crypto');
const axios = require('axios');
class AtlasApiClient {
constructor(publicKey, secretKey) {
this.publicKey = publicKey;
this.secretKey = secretKey;
this.baseURL = 'https://atlasapi.solvytix.com/api/client';
}
generateSignature(timestamp, body = '') {
const payload = `${timestamp}${body}`;
const signature = crypto
.createHmac('sha256', this.secretKey)
.update(payload)
.digest('base64');
return signature;
}
async getCountries(language = 'en') {
try {
const timestamp = Math.floor(Date.now() / 1000);
const signature = this.generateSignature(timestamp);
const response = await axios.get(`${this.baseURL}/countries`, {
headers: {
'X-Api-PublicKey': this.publicKey,
'X-Api-Timestamp': timestamp.toString(),
'X-Api-Signature': signature,
'Accept-Language': language
}
});
return response.data;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
throw error;
}
}
async getCitiesByGovernorate(governorateId, language = 'en') {
try {
const timestamp = Math.floor(Date.now() / 1000);
const signature = this.generateSignature(timestamp);
const response = await axios.get(
`${this.baseURL}/cities/governorate/${governorateId}`,
{
headers: {
'X-Api-PublicKey': this.publicKey,
'X-Api-Timestamp': timestamp.toString(),
'X-Api-Signature': signature,
'Accept-Language': language
}
}
);
return response.data;
} catch (error) {
console.error('Error:', error.response?.data || error.message);
throw error;
}
}
}
// Example usage
const client = new AtlasApiClient(
'pk_aB3xYz9mN7qWe8rT5yU2iO4pL6kJ1hG0',
'sk_dE6fG8hJ2kL4mN9oP1qR3sT5uV7wX0yZ'
);
// Get countries
client.getCountries('en')
.then(data => console.log('Countries:', data))
.catch(err => console.error(err));
Request Access
Get started with SolvyAtlas API for free! Submit your request below, and you'll receive your Public Key and Secret Key credentials at no cost.
📋 What you'll receive:
• Public Key - Used to identify your application
• Secret Key - Used for secure authentication (keep confidential)
• Free access to all API endpoints listed above
• Early adopter benefits for future updates
💡 Pricing: Currently free. Subscription fees may apply in the future, but early users will receive advance notice and special consideration.