Guides
Code examples
The API is plain HTTPS and JSON, so any HTTP client works. These examples use each language's standard tools.
Every request needs your API key in the Authorization header, and every error uses the same envelope, so the pattern is the same in every language: send the request, check the status, then read the JSON. See Errors for retry guidance.
cURL
curl -G "https://developers.ubhub.mn/v1/geocode" \
--data-urlencode "q=Sukhbaatar Square" \
-d limit=5 \
-H "Authorization: Bearer YOUR_API_KEY"JavaScript
Plain fetch, no dependencies. Works in Node.js 18+, Deno, Bun and server-side frameworks.
const params = new URLSearchParams({
q: "Sukhbaatar Square",
limit: "5",
});
const response = await fetch(`https://developers.ubhub.mn/v1/geocode?${params}`, {
headers: { Authorization: `Bearer ${process.env.GEO_API_KEY}` },
});
const body = await response.json();
if (!response.ok) {
// Every error uses the same envelope: { error: { code, message, details } }
throw new Error(`${body.error.code}: ${body.error.message}`);
}
for (const place of body.results) {
console.log(place.name, place.latitude, place.longitude);
}TypeScript
The same requests with response types. The types mirror the API reference; you can also generate them from the OpenAPI schema with any OpenAPI type generator.
type GeocodeResult = {
id: string;
name: string;
address: string | null;
latitude: number;
longitude: number;
type: string;
distance_meters?: number; // reverse lookups only
};
type GeocodeResponse = { query: string; results: GeocodeResult[]; count: number };
type ApiError = { error: { code: string; message: string; details?: Record<string, unknown> } };
const params = new URLSearchParams({
q: "Sukhbaatar Square",
limit: "5",
});
const response = await fetch(`https://developers.ubhub.mn/v1/geocode?${params}`, {
headers: { Authorization: `Bearer ${process.env.GEO_API_KEY}` },
});
if (!response.ok) {
const { error } = (await response.json()) as ApiError;
throw new Error(`${error.code}: ${error.message}`);
}
const body = (await response.json()) as GeocodeResponse;
for (const place of body.results) {
console.log(place.name, place.latitude, place.longitude);
}Python
Using httpx (pip install httpx); requests works the same way.
import os
import httpx
response = httpx.get(
"https://developers.ubhub.mn/v1/geocode",
params={"q": "Sukhbaatar Square", "limit": 5},
headers={"Authorization": f"Bearer {os.environ['GEO_API_KEY']}"},
timeout=10,
)
body = response.json()
if response.is_error:
raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
for place in body["results"]:
print(place["name"], place["latitude"], place["longitude"])Flutter / Dart
Using the http package (dart pub add http).
Do not ship keys in apps
Anything inside a mobile app can be extracted. In Flutter apps, call your own backend and let it call the API with the key.
import 'dart:convert';
import 'package:http/http.dart' as http;
/// Call the API from your backend, or from an app through your own server:
/// never ship an API key inside a mobile app.
Future<void> main() async {
const apiKey = String.fromEnvironment('GEO_API_KEY');
final uri = Uri.parse('https://developers.ubhub.mn/v1/geocode').replace(
queryParameters: {'q': 'Sukhbaatar Square', 'limit': '5'},
);
final response = await http.get(uri, headers: {'Authorization': 'Bearer $apiKey'});
final body = jsonDecode(response.body) as Map<String, dynamic>;
if (response.statusCode != 200) {
throw Exception('${body['error']['code']}: ${body['error']['message']}');
}
for (final place in body['results'] as List<dynamic>) {
print('${place['name']}: ${place['latitude']}, ${place['longitude']}');
}
}