v2.0.0 Public Access

Sri Lankan Bus Fare API

A comprehensive REST API for calculating bus fares across Sri Lanka. Supports multilingual stop name search (Sinhala, English, Tamil) and returns all available routes between two stops with their respective fares.

Annual Bus Fare Revision July 2025

Effective from 04th of July 2025 (from 00.01 hrs.).

Source: ntc.gov.lk


Getting Started

This API is hosted and managed by us. You do not need to install or deploy anything. To start using the API, you only need your API key.

Get Your API Key

Please contact us to obtain your unique sk_live_... API key. You will need this key to authenticate all your requests.


API Reference

Base URL

https://v2.srilankabusfare.com/api
POST/fare

Calculate Fare

Calculate bus fare between two stops. Returns all available routes with their fares.

Headers

x-api-key
Required
Your unique API key
Content-Type
Required
application/json

Body Parameters

start
string
Starting stop name (Sinhala, English, or Tamil)
end
string
Ending stop name (Sinhala, English, or Tamil)

Example Request

English
bash
curl -X POST https://v2.srilankabusfare.com/api/fare \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_API_KEY" \
  -d '{"start": "Monaragala", "end": "Ampara Bus Stand"}'

Success Response

json
{
  "results": [
    {
      "routeId": "909",
      "routeName": "මොණරාගල - අම්පාර බස් නැවතුම්පොල",
      "routeNameEnglish": "Monaragala - Ampara Bus Stand",
      "routeNameTamil": "மொனராகலை - அம்பாறை பேருந்து நிலையம்",
      "category": "Normal",
      "startStop": {
        "name": "මොණරාගල",
        "englishName": "Monaragala",
        "tamilName": "மொனராகலை",
        "instance": 0
      },
      "endStop": {
        "name": "අම්පාර බස් නැවතුම්පොල",
        "englishName": "Ampara Bus Stand",
        "tamilName": "அம்பாரா பேருந்து நிලையम்",
        "instance": 48
      },
      "distanceStages": 48,
      "fare": 337,
      "semiLuxuryFare": 404,
      "luxuryFare": 471,
      "superLuxuryFare": 538,
      "currency": "LKR"
    },
    {
      "routeId": "909A",
      "routeName": "මොණරාගල - අම්පාර බස් නැවතුම්පොල",
      "routeNameEnglish": "Monaragala - Ampara Bus Stand",
      "routeNameTamil": "மொனராகலை - அம்பாறை பேருந்து நிலையம்",
      "category": "Semi-Luxury",
      "startStop": {
        "name": "මොණරාගල",
        "englishName": "Monaragala",
        "tamilName": "மொனராகலை",
        "instance": 0
      },
      "endStop": {
        "name": "අම්පාර බස් නැවතුම්පොල",
        "englishName": "Ampara Bus Stand",
        "tamilName": "அம்பாரா பேருந்து நிலையம்",
        "instance": 48
      },
      "distanceStages": 48,
      "fare": 337,
      "semiLuxuryFare": 404,
      "luxuryFare": 471,
      "superLuxuryFare": 538,
      "currency": "LKR"
    }
  ],
  "query": {
    "start": "Monaragala",
    "end": "Ampara Bus Stand"
  },
  "totalRoutes": 2
}
GET/stops

Search Stops

Search for bus stops by name to implement autocomplete. Returns a list of matching stops. Supports partial matching for Sinhala, English, and Tamil names.

Query Parameters

q
string
Search query (e.g., "Nit")

Example Request

bash
curl -X GET "https://v2.srilankabusfare.com/api/stops?q=Nit" \
  -H "x-api-key: YOUR_API_KEY"

Success Response

json
{
  "results": [
    {
      "stopId": "507f1f77bcf86cd799439011",
      "stopKey": "nittambuwa",
      "name": "නිට්ටඹුව",
      "englishName": "Nittambuwa",
      "tamilName": "நிட்டம்புவ"
    }
  ],
  "query": {
    "q": "Nit"
  },
  "count": 1
}

Client Integration Guide

1. Get an API Key

You must obtain a valid API key (sk_live_...) to access the API.

2. Configure Your Project

Store the API key securely in your project's environment variables.

env
BUSFAIR_API_KEY="sk_live_..."

3. Make API Requests

You must include the x-api-key header in every request.

Node.js (Fetch)

javascript
const API_KEY = process.env.BUSFAIR_API_KEY;

async function getFare(start, end) {
  const response = await fetch('https://v2.srilankabusfare.com/api/fare', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': API_KEY
    },
    body: JSON.stringify({ start, end })
  });

  const data = await response.json();
  console.log(data);
}

Python (Requests)

python
import os
import requests

api_key = os.getenv('BUSFAIR_API_KEY')

response = requests.post(
    'https://v2.srilankabusfare.com/api/fare',
    headers={
        'Content-Type': 'application/json',
        'x-api-key': api_key
    },
    json={'start': 'Monaragala', 'end': 'Ampara'}
)

print(response.json())

Data Model

Routes Object

javascript
{
  "routeId": "909",
  "routeName": "මොණරාගල - අම්පාර",           // Sinhala
  "routeNameEnglish": "Monaragala - Ampara", // English
  "routeNameTamil": "மொனராகலை - அம்பாறை",     // Tamil
  "category": "Normal",
  "startStop": {
      "name": "මොණරාගල",           // Sinhala
      "englishName": "Monaragala", // English
      "tamilName": "மொනராகலை",      // Tamil
      "instance": 0                // Position on route
  },
  "endStop": {
      "name": "අම්පාර බස් නැවතුම්පොල",
      "englishName": "Ampara Bus Stand",
      "tamilName": "அம්பාරா பேருந்து நிலையම்",
      "instance": 48
  },
  "distanceStages": 48,
  "fare": 337,
  "semiLuxuryFare": 404,
  "luxuryFare": 471,
  "superLuxuryFare": 538,
  "currency": "LKR"
}

Field Descriptions

name / routeName

Primary name in Sinhala script

englishName / routeNameEnglish

English transliteration (optional)

tamilName / routeNameTamil

Tamil translation (optional)

instance

Position of the stop on the route (sequence number)

distanceStages

Number of stages between start and end stops

fare

Base fare for Normal/Regular buses

semiLuxuryFare / luxuryFare / superLuxuryFare

Optional premium fares for different bus categories


React Integration Best Practices

Common React Error

Error: "Objects are not valid as a React child"

This occurs when trying to render multilingual string fields directly without accessing the specific language property.

✅ Correct Usage

All name fields are returned as separate string properties. Access them directly:

tsx
// ✅ CORRECT: Access language-specific properties
function FareCard({ route }) {
  return (
    <div>
      <h3>{route.routeNameEnglish}</h3>
      <p>From: {route.startStop.englishName}</p>
      <p>To: {route.endStop.englishName}</p>
      <p>Fare: {route.fare} {route.currency}</p>
    </div>
  );
}

// ✅ CORRECT: Display multiple languages
function MultilingualStopName({ stop }) {
  return (
    <div>
      <p className="font-sinhala">{stop.name}</p>
      <p className="text-sm text-gray-600">{stop.englishName}</p>
      <p className="font-tamil text-sm">{stop.tamilName}</p>
    </div>
  );
}

// ✅ CORRECT: Conditional rendering for optional fields
function RouteName({ route }) {
  return (
    <h2>
      {route.routeNameEnglish || route.routeName || 'Unknown Route'}
    </h2>
  );
}

❌ Incorrect Usage

These patterns will cause React errors:

tsx
// ❌ WRONG: Trying to render the entire stop object
function BrokenComponent({ route }) {
  return (
    <div>
      {/* This will cause: "Objects are not valid as a React child" */}
      <p>{route.startStop}</p>
    </div>
  );
}

// ❌ WRONG: Incorrect property access
function AnotherBrokenComponent({ route }) {
  return (
    <div>
      {/* These properties don't exist in the API response */}
      <p>{route.startStop.si}</p>
      <p>{route.startStop.en}</p>
      <p>{route.startStop.ta}</p>
    </div>
  );
}

Language Preference Helper

Use a helper function to select the appropriate language:

typescript
// Helper function to get name in preferred language
function getLocalizedName(
  item: { name?: string; englishName?: string; tamilName?: string },
  preferredLang: 'si' | 'en' | 'ta' = 'en'
): string {
  const nameMap = {
    si: item.name,
    en: item.englishName,
    ta: item.tamilName,
  };
  
  // Return preferred language or fallback to available names
  return nameMap[preferredLang] || 
         item.englishName || 
         item.name || 
         item.tamilName || 
         'Unknown';
}

// Usage in component
function SmartFareCard({ route, language = 'en' }) {
  return (
    <div>
      <h3>{getLocalizedName({
        name: route.routeName,
        englishName: route.routeNameEnglish,
        tamilName: route.routeNameTamil
      }, language)}</h3>
      
      <p>From: {getLocalizedName(route.startStop, language)}</p>
      <p>To: {getLocalizedName(route.endStop, language)}</p>
    </div>
  );
}