Bwendi Context API

Resolve any coordinate to places, markets, admin regions & economic context.

Pricing

$5
per 1,000 credits
$0.005
per credit

Try it

Authentication

Send your key in a header:

apikey: YOUR_API_KEY

Credits

EndpointBase costModifiers
POST /interpret/:cc/:lat/:lng16Context (1) + AI (15)
GET /context/:lat/:lng2Auto-resolve CC
GET /context/:cc/:lat/:lng1
  + ?lang=xx+1
  + ?expand=true+1
GET /markets/:tier/:cc1
GET /country1
GET /search/:cc1
GET /countries1
GET /languages1
GET /health0Public

Country & Markets

GET /markets/:tier/:cc

GET /markets/:tier[/:cc] Auth 1 cr

List all markets at or above the requested economic tier for a country. The special tier hubs uses an 80/20 rule on Huff-catchment intensity to auto-detect the primary market hubs.

ParamTypeNote
tierstringdominant · prime · high · integrated · moderate · peripheral · marginal · isolated · hubs
ccstringOptional — omit to detect from headers
QueryEffect
?lang=XXTranslate labels (+1 cr)
GET /markets/prime/CM
{
  "tier": "prime",
  "country_code": "CM",
  "count": 8,
  "markets": [
    {
      "name": "Douala",
      "type": "city",
      "lat": 4.0483,
      "lng": 9.7043,
      "population": 2768400,
      "economic_tier": "dominant",
      "market_score": 11.5
    }
  ]
}

Hierarchy: dominantprimehighintegratedmoderateperipheralmarginalisolated

GET /country

GET /country[/:cc] /country/:lat/:lng Auth 1 cr

Edge-only — no backend round-trip. Three variants:

PathResolves from
/countryCloudflare geolocation header
/country/CMCountry code
/country/3.87/11.52Coordinates (0.25° grid)
{
  "name": "Cameroon",
  "localName": "Cameroun",
  "code": "CM",
  "callingCode": "+237",
  "flag": "🇨🇲",
  "lang": "fr",
  "currency": {
    "symbol": "FCFA",
    "code": "XAF",
    "name": "Central African CFA Franc",
    "localName": "Franc CFA"
  }
}

Location Context

GET /context/:lat/:lng

GET /context/:lat/:lng Auth 2 cr

Auto-resolves the country code from coordinates using a 0.25° edge grid, then returns the full context. Response header x-resolved-cc shows the detected country.

ParamTypeRange
latnumber-90 … 90
lngnumber-180 … 180
QueryEffect
?lang=frTranslate labels (+1 cr)
?expand=trueResolve anchors to named places (+1 cr)
GET /context/3.8667/11.5167

Response is identical to /context/:cc/:lat/:lng below.

GET /context/:cc/:lat/:lng

GET /context/:cc/:lat/:lng Auth 1 cr

Full geographic context for a coordinate inside a known country.

ParamTypeNote
ccstringISO 3166-1 alpha-2
latnumber-90 … 90
lngnumber-180 … 180
QueryEffect
?lang=frTranslate labels (+1 cr)
?expand=trueResolve anchors to named places (+1 cr)
GET /context/CM/3.8667/11.5167
{
  "name": "Yaoundé",
  "ascii_name": "Yaounde",
  "lat": 3.8667,
  "lng": 11.5167,
  "type": "city",
  "within": {
    "name": "Centre",
    "label": "Région",
    "type": "region",
    "level": 4
  },
  "label": "Ville",
  "population": 2765568,
  "language": "fr",
  "economic_tier": "dominant",
  "distance": 0,
  "direction": "N",
  "context": "In Yaoundé, Centre region",
  "anchors": {
    "immediate": ["city"],
    "local": ["city"],
    "reachable": ["city"]
  },
  "markets": [
    {
      "name": "Douala",
      "type": "city",
      "distance": 194,
      "direction": "SW",
      "population": 2768400,
      "economic_tier": "dominant",
      "priority": 1,
      "text": "194km SW to Douala"
    }
  ],
  "nearby": [
    {
      "name": "Mballa II",
      "type": "suburb",
      "distance": 2.1,
      "direction": "NE"
    }
  ],
  "country": {
    "name": "Cameroon",
    "localName": "Cameroun",
    "code": "CM",
    "callingCode": "+237",
    "flag": "🇨🇲",
    "lang": "fr",
    "currency": {
      "symbol": "FCFA",
      "code": "XAF",
      "name": "Central African CFA Franc"
    }
  }
}

Autocomplete

GET /search/:cc?q=… Auth 1 cr

Fuzzy place name search within a country. Returns matching settlements ranked by population.

ParamTypeNote
ccstringISO 3166-1 alpha-2
QueryTypeNote
qstringRequired, min 2 chars
limitint1–50 (default 10)
typesstringComma-separated: city,town,village
langstringTranslate labels (+1 cr)
GET /search/CM?q=Douala
{
  "country_code": "CM",
  "query": "Douala",
  "count": 3,
  "results": [
    {
      "name": "Douala",
      "type": "city",
      "lat": 4.0483,
      "lng": 9.7043,
      "population": 2768400,
      "economic_tier": "dominant",
      "within": "Littoral"
    }
  ]
}

Intelligence

POST /interpret/:cc/:lat/:lng

POST /interpret/:cc/:lat/:lng Auth 16 cr

Resolves full location context, then feeds it along with a user prompt to Gemini for AI-powered geospatial analysis. Returns the complete context response plus the AI interpretation.

ParamTypeNote
ccstringISO 3166-1 alpha-2
latnumber-90 … 90
lngnumber-180 … 180
BodyTypeNote
promptstringRequired, max 500 chars
QueryEffect
?lang=frTranslate labels (+1 cr)
?expand=trueResolve anchors (+1 cr)
POST /interpret/CM/3.8667/11.5167
Content-Type: application/json

{ "prompt": "What is the commercial potential?" }

Returns the full context response (same as /context) plus:

"ai": {
  "prompt": "What is the commercial potential?",
  "response": "This location is Cameroon's political capital with a population of 2.8M. The dominant economic tier and high gravity score indicate strong commercial integration. Douala, the economic hub, is 194km SW — the dual-hub corridor between these cities is the most commercially active zone in the country..."
}
Cost breakdown: 1 cr for context lookup + 15 cr for AI interpretation = 16 cr total. Add +1 for ?lang, +1 for ?expand.

Status / Info

GET /health

GET /health Public 0 cr

Server health check — no authentication required.

{
  "status": "ok",
  "uptime": 84210,
  "countries_loaded": 47,
  "memory_mb": 128,
  "timestamp": "2026-02-14T12:00:00.000Z"
}

GET /countries

GET /countries /countries/:cc Auth 1 cr

List all available countries, or get detailed info for a specific country.

// GET /countries
{
  "built": ["AD","AE","CM","NG",...],
  "built_count": 47,
  "source": [...],
  "source_count": 200
}

// GET /countries/CM
{
  "country_code": "CM",
  "has_data": true,
  "has_db": true,
  "db_size_mb": 12.4,
  "db_modified": "2026-02-14T10:00:00Z",
  "config": {...}
}

GET /languages

GET /languages Auth 1 cr

All supported translation languages and their count.

{
  "languages": {
    "fr": "Français",
    "es": "Español",
    "de": "Deutsch",
    ...
  },
  "country_count": 47,
  "unique_languages": ["fr","es","de",...],
  "unique_count": 24
}

Response Headers

HeaderValue
x-credit-costCredits charged for this request (0–18)
x-balance-remainingCredits left on your key (-1 = unlimited)
x-resolved-ccAuto-resolved country code (when CC omitted)

Errors

StatusMeaning
400Invalid parameters
401Missing API key
402Insufficient credits
403Invalid or inactive key
404Country not found / no nearby populated area
429Rate limit exceeded (default 60 req/min)
500Internal server error