πŸš€ Project Overview

Global platforms like Google Maps or Yandex treat local administrative data as second-class citizens. When passing coordinates to their legacy APIs, they return unstable, hard-to-parse unstructured text strings such as "Pap District" or "Папский Ρ€Π°ΠΉΠΎΠ½" depending on client locales. Processing these strings in your production backend leads to continuous regex parsing errors.

Kettu Geo-Data API solves this entirely. By matching client coordinates against precise spatial database MultiPolygon grids via PostGIS spatial indexes, it directly outputs a clean, immutable Universal Slug (e.g., pap, besharyk, sukh). This serves as a plug-and-play Natural Key for your database tables, completely bypassing expensive API pricing and vendor lock-in.

Production Base URL: https://thekettu.com/api

πŸ›°οΈ Geocoding API Specifications

Trigger a spatial intersection query from your mobile applications or server-side microservices instantly.

GET /geo-data

1. Request Query Parameters

Parameter Key Type Policy Spatial Context & Sample
lat Double REQUIRED Geographical Latitude coordinate point.
Example: 41.182104
long Double REQUIRED Geographical Longitude coordinate point.
Example: 70.709864

2. Global HTTP Request Headers

Header Property Supported Enums Localization Logic
Accept-Language uz | ru | en Renders localization values using mapped resource bundles.
Fallback Default: en

πŸ“¦ JSON Response Payloads

The system enforces a rigid, predictable response block optimized for real-time relational parsing:

🟒 200 OK β€” Point Inside Boundary Successfully Found
{
  "message": "Success",
  "data": {
    "point": {
      "latitude": 41.182104,
      "longitude": 70.709864
    },
    "region": {
      "id": 3,
      "slug": "namangan",
      "name": "Namangan viloyati"
    },
    "district": {
      "id": 49,
      "slug": "pap",
      "name": "Pop"
    }
  }
}
πŸ”΄ 404 Not Found β€” Point Out of Bounds / Spatial Miss
{
    "message": "Failed",
    "data": "District not found"
}

πŸ—„οΈ Database Architectural Integration

Because the API returns a predictable, immutable slug natural key instead of variable text blocks, updating relationship links within SQL engines like PostgreSQL or MySQL is safe and fast:

-- Direct relational foreign key linking without string manipulation or substring trimming
UPDATE app_users_profile 
SET localized_district_id = (SELECT id FROM enterprise_districts WHERE slug = :kettu_returned_slug)
WHERE user_session_id = :active_user_id;

πŸ“‚ Reference Data API

To seed your local databases or build dropdown menus in your UI, you can dynamically fetch all supported region and district slugs. These endpoints are heavily cached for ultra-fast response times.

GET /regions

Returns a list of all available region slugs. Use these values to query districts.

{
  "message": "Success",
  "data": [
    "fergana",
    "andijan",
    "namangan",
    "sirdaryo",
    "jizzakh",
    "samarkand",
    "kashkadarya",
    "surkhandarya",
    "bukhara",
    "navoi",
    "khorezm",
    "karakalpakstan",
    "tashkent",
    "tashkent-city"
  ]
}
GET /districts?region={region_slug}

Returns all district slugs associated with a specific region.

region REQUIRED Region slug to filter districts (e.g., tashkent-city)
{
  "message": "Success",
  "data": [
    "yangi-hayat",
    "yangi-tashkent",
    "khamza",
    "uchtepa",
    "shaykhantahur",
    "chilanzar",
    "mirabad",
    "yunusabad",
    "mirzo-ulugbek",
    "almazar",
    "yakkasaray",
    "sergeli",
    "bektemyr"
  ]
}

πŸ’» Zero-Configuration Client Integration

Clean integration templates for multiple runtime applications.

⚑ Node.js (Axios Client Async)

const axios = require('axios');

async function resolveUserSpatialPoint() {
  try {
    const response = await axios.get('https://thekettu.com/api/geo-data', {
      params: { lat: 41.182104, long: 70.709864 },
      headers: { 'Accept-Language': 'uz' }
    });
    
    // Direct output: "pap"
    console.log("Resolved Natural Key:", response.data.data.district.slug);
  } catch (error) {
    console.error("Spatial lookup failed:", error.message);
  }
}

β˜• Java (Spring RestTemplate)

import org.springframework.web.client.RestTemplate;
import org.springframework.http.*;
import java.util.Map;

public class SpatialResolver {
    public Map<String, Object> getGeoData(double lat, double lon) {
        String url = "https://thekettu.com/api/geo-data?lat={lat}&long={long}";
        RestTemplate restTemplate = new RestTemplate();
        
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept-Language", "uz");
        
        HttpEntity<String> entity = new HttpEntity<>(headers);
        ResponseEntity<Map> response = restTemplate.exchange(
            url, HttpMethod.GET, entity, Map.class, lat, lon
        );
        
        // Returns the inner "data" object containing point, region, and district
        return (Map<String, Object>) response.getBody().get("data");
    }
}