Integration Guide

Usage & Integration Guide

Learn how to integrate UnifiedAPI into your website, script, or application — with examples for cURL, PHP, JavaScript, Node.js, Python, Laravel, WHMCS, and WordPress.

This guide covers how to integrate UnifiedAPI into your website, script, or application. The API provides the complete administrative geographic data of Bangladesh — divisions, districts, upazilas, and unions.

Base URL:

text
https://unifiedapi.pages.dev/api/geo/v1.0

Available Endpoints:

GET /divisionsAll 8 divisions
GET /districtsAll 64 districts
GET /districts/{id}Districts in a division
GET /upazilasAll 495 upazilas
GET /upazilas/{id}Upazilas in a district
GET /unions/{id}Unions in an upazila
GET /search/{query}Search by name (EN/BN), optional ?type=

Every response returns a consistent JSON format: success (boolean), data (array of objects), count (number of results), message (status description), api_version ("1.0"), timestamp (ISO 8601).

This API requires no authentication. Simply make a GET request and receive the data. No execution steps needed — get results directly.

Test and use the API directly from your terminal or any HTTP client. The simplest way to verify responses before integrating into code.

Basic cURL Examples

bash
# Get all divisions
curl -s "https://unifiedapi.pages.dev/api/geo/v1.0/divisions" | jq .

# Get districts by division ID (Dhaka = 6)
curl -s "https://unifiedapi.pages.dev/api/geo/v1.0/districts/6" | jq .

# Get upazilas by district ID
curl -s "https://unifiedapi.pages.dev/api/geo/v1.0/upazilas/26" | jq .

# Get unions by upazila ID
curl -s "https://unifiedapi.pages.dev/api/geo/v1.0/unions/52" | jq .

# Search by name (English or Bengali)
curl -s "https://unifiedapi.pages.dev/api/geo/v1.0/search/dhaka" | jq .
curl -s "https://unifiedapi.pages.dev/api/geo/v1.0/search/ঢাকা" | jq .

Parameters & Response Info

bash
# Search with type filter
curl -s "https://unifiedapi.pages.dev/api/geo/v1.0/search/dhaka?type=district" | jq .

# Response structure:
# {
#   "success": true,
#   "data": [ { "id": 6, "name": "Dhaka", "bn_name": "ঢাকা", ... } ],
#   "count": 1,
#   "message": "Data retrieved successfully",
#   "api_version": "1.0",
#   "timestamp": "2025-01-01T00:00:00Z"
# }
Use | jq . to pretty-print JSON (install: sudo apt install jq). Add -v flag for full HTTP headers and timing info.

Use the API in any PHP application — from simple file_get_contents to production-ready cURL with error handling.

Basic file_get_contents

php
<?php
$url = "https://unifiedapi.pages.dev/api/geo/v1.0/divisions";
$response = file_get_contents($url);
$data = json_decode($response, true);

if ($data['success']) {
    foreach ($data['data'] as $division) {
        echo $division['name'] . ' (' . $division['bn_name'] . ')\n';
    }
}
// Output: Dhaka (ঢাকা), Chattagram (চট্টগ্রাম), ...

Production cURL with Error Handling

php
<?php
function fetchBDGeo($endpoint) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => "https://unifiedapi.pages.dev/api/geo/v1.0" . $endpoint,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_HTTPHEADER     => ['Accept: application/json'],
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode === 200) {
        return json_decode($response, true);
    }
    return ['success' => false, 'message' => 'API request failed'];
}

// Get districts of Dhaka division (ID: 6)
$districts = fetchBDGeo('/districts/6');
if ($districts['success']) {
    foreach ($districts['data'] as $dist) {
        echo $dist['name'] . ' \n';
    }
}

// Search by Bengali name
$results = fetchBDGeo('/search/কুমিল্লা');
echo "Found " . $results['count'] . " results";

Dropdown Generator Helper

php
<?php
// Generate <option> HTML for a dropdown
function getOptions($endpoint) {
    $data = fetchBDGeo($endpoint);
    if (!$data['success']) return '';
    $html = '<option value="">-- Select --</option>';
    foreach ($data['data'] as $item) {
        $html .= sprintf(
            '<option value="%s">%s (%s)</option>',
            htmlspecialchars($item['id']),
            htmlspecialchars($item['name']),
            htmlspecialchars($item['bn_name'])
        );
    }
    return $html;
}

// Usage:
// echo '<select name="division">' . getOptions('/divisions') . '</select>';
Always use cURL in production for timeout control and HTTP status checking.

A complete standalone HTML file with cascading dropdowns — Division → District → Upazila → Union. Uses fetch API and shows JSON output.

Complete Example (Copy & Paste)

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BD Geo Example</title>
    <style>
        body { font-family: system-ui; max-width: 600px; margin: 2rem auto; padding: 0 1rem; }
        select { width: 100%; padding: 10px; margin: 8px 0; border: 1px solid #ccc; border-radius: 6px; }
        .result { background: #f1f5f9; padding: 12px; border-radius: 6px; margin-top: 12px;
                   font-family: monospace; font-size: 13px; white-space: pre-wrap; max-height: 300px; overflow-y: auto; }
    </style>
</head>
<body>
    <h2>📍 Bangladesh Geo Explorer</h2>

    <label><strong>Division</strong></label>
    <select id="division" onchange="loadDistricts(this.value)">
        <option value="">-- Select Division --</option>
    </select>

    <label><strong>District</strong></label>
    <select id="district" onchange="loadUpazilas(this.value)">
        <option value="">-- Select District --</option>
    </select>

    <label><strong>Upazila</strong></label>
    <select id="upazila" onchange="loadUnions(this.value)">
        <option value="">-- Select Upazila --</option>
    </select>

    <div class="result" id="output">Select a division to start...</div>

    <script>
        const API = "https://unifiedapi.pages.dev/api/geo/v1.0";
        async function fetchAPI(ep) { return (await fetch(API + ep)).json(); }

        function fill(sel, data) {
            const el = document.getElementById(sel);
            el.innerHTML = '<option value="">-- Select --</option>';
            if (data.success) data.data.forEach(i => {
                el.innerHTML += '<option value="'+i.id+'">'+i.name+' ('+i.bn_name+')</option>';
            });
        }

        async function loadDivisions() { fill('division', await fetchAPI('/divisions')); }
        async function loadDistricts(id) {
            document.getElementById('district').innerHTML = '<option value="">-- Select --</option>';
            document.getElementById('upazila').innerHTML = '<option value="">-- Select --</option>';
            if (!id) return;
            fill('district', await fetchAPI('/districts/' + id));
        }
        async function loadUpazilas(id) {
            document.getElementById('upazila').innerHTML = '<option value="">-- Select --</option>';
            if (!id) return;
            fill('upazila', await fetchAPI('/upazilas/' + id));
        }
        async function loadUnions(id) {
            if (!id) return;
            const d = await fetchAPI('/unions/' + id);
            document.getElementById('output').textContent = JSON.stringify(d, null, 2);
        }
        loadDivisions();
    </script>
</body>
</html>
Save this code directly in a .html file and open it in the browser. No server or dependencies needed.

Use Node.js built-in fetch (v18+) to get data from the API. Includes an Express proxy example.

Basic fetch Examples

javascript
// Node.js 18+ (built-in fetch)
const API = "https://unifiedapi.pages.dev/api/geo/v1.0";

async function getDivisions() {
  const res = await fetch(API + '/divisions');
  const data = await res.json();
  if (data.success) {
    data.data.forEach(d => console.log(d.name, '(' + d.bn_name + ')'));
  }
  return data;
}

async function getDistricts(divisionId) {
  const res = await fetch(API + '/districts/' + divisionId);
  return res.json();
}

async function getUpazilas(districtId) {
  const res = await fetch(API + '/upazilas/' + districtId);
  return res.json();
}

async function search(query, type) {
  const url = type ? API + '/search/' + query + '?type=' + type : API + '/search/' + query;
  return (await fetch(url)).json();
}

getDivisions();
// Dhaka (ঢাকা)  Chattagram (চট্টগ্রাম)  ...

Express.js Proxy with In-Memory Cache

javascript
// Express.js proxy with in-memory cache
const express = require('express');
const app = express();
const BD_API = "https://unifiedapi.pages.dev/api/geo/v1.0";
const cache = new Map();
const TTL = 3600000; // 1 hour

app.get('/api/bd-geo/:path(*)', async (req, res) => {
  const key = req.params.path;
  const hit = cache.get(key);
  if (hit && Date.now() - hit.t < TTL) return res.json(hit.d);
  try {
    const r = await fetch(BD_API + '/' + key);
    const d = await r.json();
    cache.set(key, { d, t: Date.now() });
    res.json(d);
  } catch (e) {
    res.status(500).json({ success: false, message: 'Fetch failed' });
  }
});

app.listen(3000, () => console.log('Proxy on :3000'));
Use Node.js 18+ for built-in fetch. For older versions, install the node-fetch package.

Use the Python requests library to fetch data from the API. Includes basic requests, search, and pagination examples.

Basic Usage

python
import requests

BASE_URL = "https://unifiedapi.pages.dev/api/geo/v1.0"

# Get all divisions
response = requests.get(f"{BASE_URL}/divisions")
data = response.json()

for div in data["data"]:
    print(f'{div["id"]}: {div["name"]} ({div["bn_name"]})')

Search Example

python
# Search by name (English or Bengali)
response = requests.get(f"{BASE_URL}/search/ঢাকা")
results = response.json()

for item in results["data"]:
    print(f'{item["type"]}: {item["name"]}')

Pagination Example

python
# Pagination example
params = {"page": 1, "limit": 10}
response = requests.get(f"{BASE_URL}/districts", params=params)
result = response.json()

print(f'Page {result["pagination"]["page"]} of {result["pagination"]["total_pages"]}')
for dist in result["data"]:
    print(f'  - {dist["name"]}')
Install requests: pip install requests. For async, use httpx instead.

Create a BdGeoService class in Laravel using the Http facade and Cache. Includes controller, route definitions, and Blade template examples.

BdGeoService (app/Services/BdGeoService.php)

php
<?php

namespace App\Services;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;

class BdGeoService
{
    protected string $baseUrl = 'https://unifiedapi.pages.dev/api/geo/v1.0';
    protected int $cacheTtl = 3600;

    protected function fetch(string $endpoint): array
    {
        return Cache::remember('bd_geo_' . $endpoint, $this->cacheTtl, function () use ($endpoint) {
            $response = Http::get($this->baseUrl . $endpoint);
            return $response->successful() ? $response->json() : ['success' => false, 'data' => []];
        });
    }

    public function divisions(): array     { return $this->fetch('/divisions'); }
    public function districts(int $id): array  { return $this->fetch("/districts/{$id}"); }
    public function upazilas(int $id): array   { return $this->fetch("/upazilas/{$id}"); }
    public function unions(int $id): array      { return $this->fetch("/unions/{$id}"); }
    public function search(string $q, ?string $type = null): array
    {
        $ep = "/search/{$q}" . ($type ? "?type={$type}" : '');
        return $this->fetch($ep);
    }
}

GeoController & Routes

php
<?php

namespace App\Http\Controllers;
use App\Services\BdGeoService;
use Illuminate\Http\Request;

class GeoController extends Controller
{
    public function __construct(private BdGeoService $geo) {}

    public function divisions()
    {
        return view('geo.divisions', ['divisions' => $this->geo->divisions()]);
    }

    public function districts(Request $req)
    {
        $req->validate(['division_id' => 'required|integer']);
        return response()->json($this->geo->districts($req->division_id));
    }

    public function upazilas(Request $req)
    {
        $req->validate(['district_id' => 'required|integer']);
        return response()->json($this->geo->upazilas($req->district_id));
    }
}

// routes/web.php
// Route::get('/geo/divisions', [GeoController::class, 'divisions']);
// Route::get('/api/districts', [GeoController::class, 'districts']);
// Route::get('/api/upazilas', [GeoController::class, 'upazilas']);

Blade Cascading Dropdowns

blade
{-- Blade cascading dropdowns --}

<div class="form-group">
    <label>Division</label>
    <select id="division" class="form-control" onchange="loadDistricts(this.value)">
        <option value="">-- Select --</option>
        @foreach($divisions['data'] ?? [] as $div)
            <option value="{{ $div['id'] }}">{{ $div['name'] }} ({{ $div['bn_name'] }})</option>
        @endforeach
    </select>
</div>
<div class="form-group">
    <label>District</label>
    <select id="district" class="form-control" onchange="loadUpazilas(this.value)">
        <option value="">-- Select --</option>
    </select>
</div>

<script>
async function loadDistricts(id) {
    if (!id) return;
    const r = await fetch('/api/districts?division_id=' + id);
    const d = await r.json();
    const el = document.getElementById('district');
    el.innerHTML = '<option value="">-- Select --</option>';
    if (d.success) d.data.forEach(i => {
        el.innerHTML += '<option value="'+i.id+'">'+i.name+' ('+i.bn_name+')</option>';
    });
}
async function loadUpazilas(id) {
    if (!id) return;
    const r = await fetch('/api/upazilas?district_id=' + id);
    const d = await r.json();
    const el = document.getElementById('upazila');
    el.innerHTML = '<option value="">-- Select --</option>';
    if (d.success) d.data.forEach(i => {
        el.innerHTML += '<option value="'+i.id+'">'+i.name+' ('+i.bn_name+')</option>';
    });
}
</script>
Use Cache::tags(['bd_geo'])->flush() for bulk cache invalidation. This clears all bd_geo cached data at once.

Add UnifiedAPI to WHMCS modules or client area templates. Includes PHP helper function and cascading dropdown JS.

PHP Helper Function

php
<?php
// Add to your WHMCS module or includes/functions.php
function get_bd_geo_data($endpoint) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL            => "https://unifiedapi.pages.dev/api/geo/v1.0" . $endpoint,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 10,
        CURLOPT_SSL_VERIFYPEER => true,
    ]);
    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode === 200) return json_decode($response, true);
    return ['success' => false, 'data' => []];
}

// Populate custom fields
$divisions = get_bd_geo_data('/divisions');
if ($divisions['success']) {
    foreach ($divisions['data'] as $div) {
        $options[$div['id']] = $div['name'] . ' (' . $div['bn_name'] . ')';
    }
}

Client Area Cascading Dropdowns

javascript
// WHMCS Client Area Template — cascading dropdowns
// Add to your .tpl file:
// <select id="customDivision" class="form-control" onchange="loadDistricts(this.value)">
//     <option value="">-- Select Division --</option>
// </select>
// <select id="customDistrict" class="form-control" onchange="loadUpazilas(this.value)">
//     <option value="">-- Select District --</option>
// </select>

<script>
const BD_API = "https://unifiedapi.pages.dev/api/geo/v1.0";

async function bdFetch(ep) { return (await fetch(BD_API + ep)).json(); }

function bdFill(selId, data) {
    const el = document.getElementById(selId);
    el.innerHTML = '<option value="">-- Select --</option>';
    if (data.success) data.data.forEach(i => {
        el.innerHTML += '<option value="'+i.id+'">'+i.name+' ('+i.bn_name+')</option>';
    });
}

// Load divisions
bdFill('customDivision', await bdFetch('/divisions'));

// Load districts on division change
document.getElementById('customDivision').addEventListener('change', async function() {
    document.getElementById('customDistrict').innerHTML = '<option value="">-- Select --</option>';
    if (!this.value) return;
    bdFill('customDistrict', await bdFetch('/districts/' + this.value));
});
</script>
Use WHMCS hooks for auto-loading. Pre-load division data in the ClientAreaPage hook for better UX.

Use UnifiedAPI as a WordPress plugin. Display division cards with [bd_divisions] shortcode and cascading dropdowns with [bd_geo_form] shortcode.

Plugin Header & [bd_divisions] Shortcode

php
<?php
/**
 * Plugin Name: UnifiedAPI Integration
 * Description: Bangladesh geographic data for WordPress
 * Version: 1.0.0
 */

// Shortcode: Division cards
add_shortcode('bd_divisions', function() {
    $response = wp_remote_get('https://unifiedapi.pages.dev/api/geo/v1.0/divisions');
    $data = json_decode(wp_remote_retrieve_body($response), true);
    if (!$data || !$data['success']) return '<p>Failed to load.</p>';

    $html = '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;">';
    foreach ($data['data'] as $d) {
        $html .= sprintf(
            '<div style="padding:16px;border:1px solid #e2e8f0;border-radius:8px;">'
            . '<strong>%s</strong><br><small style="color:#64748b">%s</small></div>',
            esc_html($d['name']), esc_html($d['bn_name'])
        );
    }
    return $html . '</div>';
});

[bd_geo_form] Shortcode — Cascading Dropdowns

php
<?php
// Shortcode: Cascading dropdown form
add_shortcode('bd_geo_form', function() {
    ob_start(); ?>
    <div id="bd-geo-form">
        <select id="bd-div" style="width:100%;padding:10px;margin:8px 0;border:1px solid #ccc;border-radius:6px;">
            <option value="">-- Select Division --</option>
        </select>
        <select id="bd-dist" style="width:100%;padding:10px;margin:8px 0;border:1px solid #ccc;border-radius:6px;">
            <option value="">-- Select District --</option>
        </select>
        <select id="bd-upz" style="width:100%;padding:10px;margin:8px 0;border:1px solid #ccc;border-radius:6px;">
            <option value="">-- Select Upazila --</option>
        </select>
    </div>
    <script>
    (async function(){
        const A="https://unifiedapi.pages.dev/api/geo/v1.0";
        const f=async e=>(await fetch(A+e)).json();
        const fill=(s,d)=>{const e=document.getElementById(s);e.innerHTML='<option value="">-- Select --</option>';if(d.success)d.data.forEach(i=>{e.innerHTML+='<option value="'+i.id+'">'+i.name+' ('+i.bn_name+')</option>';})};
        fill('bd-div',await f('/divisions'));
        document.getElementById('bd-div').onchange=async function(){document.getElementById('bd-dist').innerHTML='<option value="">-- Select --</option>';document.getElementById('bd-upz').innerHTML='<option value="">-- Select --</option>';if(!this.value)return;fill('bd-dist',await f('/districts/'+this.value))};
        document.getElementById('bd-dist').onchange=async function(){document.getElementById('bd-upz').innerHTML='<option value="">-- Select --</option>';if(!this.value)return;fill('bd-upz',await f('/upazilas/'+this.value))};
    })();
    </script>
    <?php
    return ob_get_clean();
});

// Usage: [bd_divisions]  or  [bd_geo_form]
Write [bd_divisions] in any page or post to display division cards. Use [bd_geo_form] for the cascading dropdown form.

Ready to Test?

Try the API Playground to test endpoints interactively.

Open Playground