πŸš€ 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/geo-service

πŸ›°οΈ Geocoding API Specifications

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

GET /reverse

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"
}

πŸ”„ Developer Integration Flow

Understand how to integrate Kettu Geo-Data API into your infrastructure and completely automate data syncing. The entire pipeline consists of 4 direct phases:

1

Frontend: Capture Geographical Coordinates

When a user places a pin or clicks on the client map interface, the Map SDK (Google Maps, Mapbox, Leaflet) returns the exact geographical coordinate pair:

latitude: 41.182104, longitude: 70.709864
2

Request: Forward Coordinates to Kettu API

Your backend server targets Kettu's lightweight /reverse endpoint, appending the coordinate properties as safe query params:

GET https://thekettu.com/api/geo-service/reverse?lat=41.182104&long=70.709864
3

Response: Ingest the Immutable Natural Key (Slug)

Kettu handles the complex PostGIS multi-polygon calculations and maps the point to an immutable natural text string within milliseconds. No fragile string parsing or regex filtering needed:

region.slug ➑️ "namangan" | district.slug ➑️ "pap"
4

Database Match: Bind Relational Database Tables

Query your internal region and district tables matching the incoming slug string. Extract your local primary relational IDs, save the transaction entity, and execute your logic seamlessly.


πŸ—„οΈ Database Architectural Integration

Kettu API does not return internal primary numerical IDs because every individual enterprise database enforces its own isolated sequencing and auto-increment strategies. Instead, the ozo-yengil **`slug`** property acts as our system contract. To integrate smoothly, your application's target tables must contain a dedicated `slug` column configured with a unique index:

-- Enforce a unique index on your slug string columns for instant record matches:
CREATE TABLE enterprise_districts (
    id SERIAL PRIMARY KEY,
    slug VARCHAR(50) UNIQUE NOT NULL, -- The unique natural key matching Kettu responses πŸ”‘
    name_uz VARCHAR(100),
    region_id INT
);

CREATE UNIQUE INDEX idx_districts_slug ON enterprise_districts(slug);

Mapping an incoming Kettu slug (e.g., `pap` or `chilanzar`) into your operational relational entity tables is achieved cleanly with a standard sub-query statement:

-- 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-service/reverse', {
      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-service/reverse?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");
    }
}

πŸ’› Support Kettu Platform

While the vast majority of funds contributed to support this project are directed straight toward maintaining high API (performance) and server (stability), a minor portion goes into keeping my (coffee and refreshments) stash stocked. Because absolute honesty is deeply important to me, I want to be entirely transparent: this directly helps (fuel the late-night coding) sessions required to keep building open-source platforms for the community. Let's grow impactful local developer utilities together! πŸš€

Kettu API Support HUMO
9860 1701 1208 2806
Cardholder: Tursunali KH. UZB Only

Custom Integration?

For large enterprise request setups or inquiries regarding direct PostGIS batch table downloads, feel free to contact me directly.

Discuss via Telegram