Edurra API · v1.0

Edurra API

Education intelligence for Nigeria — school discovery, catchment analysis, bus route planning, and community demographics built on Maiaddy Loccodes.

Version

v1.0

Base URL

https://api.maiaddy.com/edurra/api/v1

Protocol

REST / JSON

Auth

Bearer token (API key)

Built on

Maiaddy Loccode location intelligence

Overview

Edurra is an education geolocation API that enables applications to discover nearby schools, assess catchment area demand, plan school transport routes, and evaluate the demographic profile of a community — all using Maiaddy's loccode as the primary location identifier.

Every request is built around a Loccode — a unique identifier from the Maiaddy platform that pinpoints a specific geographic area at postcode-level precision. Send a loccode (or, for routing, a set of loccodes), and the API returns data for that exact location: nearby schools, catchment demand, optimised pickup routes, or community demographics.

The four endpoints

EndpointMethodPathWhat it returns
Plan Bus RoutePOST/edurra/api/v1/bus-routeAn optimised pickup route for a school bus, covering a school location and pickup locations, with per-leg distance and duration.
Get SchoolsGET/edurra/api/v1/schoolsSchools near a location, with type, capacity, and access score, filterable by radius, state, LGA, and school type.
Get CatchmentGET/edurra/api/v1/catchmentCatchment area analysis — number of schools, estimated capacity, and local school-age population within a radius.
Get DemographicsGET/edurra/api/v1/demographicsPopulation, literacy, urbanisation, and income bracket data for the area surrounding a location.

NOTE

Only the bus-route endpoint uses HTTP POST with a JSON request body. The schools, catchment, and demographics endpoints use HTTP GET with query parameters. Do not send a JSON body to GET endpoints.

The Loccode

Every request requires at least one loccode (the bus-route endpoint requires several). Understanding how to use it correctly will save you from the most common errors.

What is a loccode?

A loccode is a structured alphanumeric code that maps to a specific postcode-level area in Nigeria. It is generated and validated by the Maiaddy location intelligence platform, which links GPS-confirmed coordinates to a unique code for that location.

Think of it like a postcode, except it maps to a real, GPS-confirmed area rather than a general postal district. Each loccode resolves to a specific state, city, and set of coordinates.

Loccodes used in the examples throughout this document:

LoccodeLocationState
LA15A 2AEMakoko, Lagos MainlandLagos
LA13A 1MLOregun, IkejaLagos
LA11A 2TQAlausa, IkejaLagos
LA20A 1XSIsolo, Oshodi/IsoloLagos
LA16 0AAOshodi/IsoloLagos
LA15A 3IBAkoka, Lagos MainlandLagos
LA15A 2CUSomolu, ShomoluLagos
OY6A 1EZIbadan NorthOyo
LA11A 4YOOgba, IkejaLagos

The Loccode must be exact

A loccode must be submitted exactly as it was issued, with correct characters and correct spacing. The API does not correct or guess. Any mistake will cause the request to fail.

  • 400 Bad Request: The loccode field is missing entirely from the request.
  • 404 Not Found: A loccode was submitted, but it is either formatted incorrectly or does not exist in the database.

IMPORTANT

If you are unsure of the exact format for a Loccode, retrieve it from the Maiaddy app. Do not guess or construct one manually.

The Loccode echoed back in a response may look slightly different from what you sent; for example LA15A 2AE may return as LA15A-2AE. This is only a display difference in the response output.

Loccode as the primary filter

The loccode is the primary and required location identifier for all endpoints. The state and lga query parameters on the catchment and demographics endpoints are optional supplementary filters; they do not replace the loccode. Requests sent with only state or only lga, without a loccode, will not return results.

Authentication & Requests

API key

An API key is required for every request. Include it in the authorisation header:

Authorization: Bearer YOUR_API_KEY

Create an API Key here.

WARNING

Never put your API key in client-side code or any publicly visible location (including GitHub). Always make Edurra API calls from your server. Store your key in an environment variable; never hardcode it.

Request format

Every request to the Edurra API must include the following headers.

HeaderRequiredValue
AuthorizationYesBearer YOUR_API_KEY
Content-TypeYes (POST only)application/json

For GET endpoints (schools, catchment, demographics), parameters are passed as URL query parameters, not in a request body. Content-Type is only required for the POST bus-route endpoint.

Response format

All responses — success and error — are wrapped in a top-level envelope:

{
  "success": true,
  "message": "Human-readable result summary",
  "timestamp": 1781617176930,
  "data": { ... }
}

If something goes wrong, the API returns a non-200 status code with success: false and an error body. See Error reference for details.

Endpoints

Plan Bus Route

Returns an optimised pickup route for a school bus. Send a school loccode, a school ID, and a list of pickup locations each with a loccode and an ID, and the API returns the optimal visiting order, current weather at the school, per-leg distance and duration, total distance, total estimated duration, and operational recommendations.

POST
https://api.maiaddy.com/edurra/api/v1/bus-route

Request

Headers

HeaderRequiredValue
AuthorizationYesBearer YOUR_API_KEY
Content-TypeYesapplication/json

Body — Request parameters

FieldTypeRequiredDescription
school_loccodestringYesThe Loccode for the school's location, used as the route's start and end point. Must be exactly as issued. Example: LA15A 2AE
school_idstring or integerYesAn identifier for the school, echoed back in the optimised route. Example: 1
pickup_locationsarrayYesArray of pickup location objects (1–50). Each object must include both loccode and id.
pickup_locations[].loccodestringYesThe Loccode for this pickup point. Example: LA13A 1ML
pickup_locations[].idstring or integerYesAn identifier for this pickup point, echoed back in the optimised route.

IMPORTANT

The request body must be valid JSON. Both school_loccode and school_id are required. The pickup_locations array cannot exceed 50 entries. Every pickup location must include both loccode and id.

Example request body

{
  "school_loccode": "LA15A 2AE",
  "school_id": "1",
  "pickup_locations": [
    {"loccode": "LA13A 1ML", "id": "C"},
    {"loccode": "LA11A 2TQ", "id": "B"},
    {"loccode": "LA20A 1XS", "id": "E"},
    {"loccode": "LA16 0AA",  "id": "D"}
  ]
}

Full curl command

curl -X POST \
  "https://api.maiaddy.com/edurra/api/v1/bus-route" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "school_loccode": "LA15A 2AE",
    "school_id": "1",
    "pickup_locations": [
      {"loccode": "LA13A 1ML", "id": "C"},
      {"loccode": "LA11A 2TQ", "id": "B"},
      {"loccode": "LA20A 1XS", "id": "E"},
      {"loccode": "LA16 0AA",  "id": "D"}
    ]
  }'

Response — 200 OK

{
  "success": true,
  "message": "Bus route curated successfully",
  "timestamp": 1781780928760,
  "data": {
    "school_location": {
      "id": "1",
      "lat": 6.506227937499999,
      "lon": 3.3757273,
      "loccode": "LA15A 2AE",
      "formatted_address": "Commercial Avenue, Makoko, Lagos Mainland, Lagos State, 102215, Nigeria",
      "osm_address": null
    },
    "pickup_locations": [
      {
        "id": "C",
        "lat": 6.5887577,
        "lon": 3.3488258799999997,
        "loccode": "LA13A 1ML",
        "formatted_address": "Police College Ikeja, Oba Akinjobi Street, Oregun, Onigbongbo, Ikeja, Lagos State, 100271, Nigeria",
        "osm_address": null
      }
    ],
    "current_weather": {
      "condition": "clear",
      "temperature_c": 29.1,
      "precipitation_expected": false
    },
    "optimized_route": {
      "route_ids": ["1", "E", "C", "B", "D", "1"],
      "total_distance_km": 52.89,
      "estimated_duration_minutes": 54,
      "number_of_pickup_stops": 4,
      "route_legs": [
        {"from_id": "1", "to_id": "E", "distance_km": 12.0, "duration_minutes": 12.8}
      ]
    },
    "recommendations": [
      "Leave a little early in case of traffic.",
      "Check the weather before you go."
    ],
    "data_updated_at": "2026-06-18T11:08:48Z"
  }
}

Response fields

FieldTypeDescription
successbooleantrue when the request succeeds.
messagestringHuman-readable result summary.
timestampnumberUnix timestamp in milliseconds.
data.school_locationobjectResolved details for the school's loccode (id, lat, lon, loccode, formatted_address).
data.pickup_locationsarrayResolved details for each pickup location submitted.
data.current_weatherobjectCurrent weather at the school (condition, temperature_c, precipitation_expected).
data.optimized_routeobjectComputed route with route, route_ids, total_distance_km, estimated_duration_minutes, route_legs.
data.recommendationsarray of stringsOperational suggestions based on current conditions.
data.data_updated_atstringISO 8601 timestamp of when the data was generated.

Errors

HTTP statusError codeWhat it meansWhat to do
400VALIDATION_ERRORschool_loccode is missing, empty, or null.Add a valid school_loccode. See The Loccode.
400VALIDATION_ERRORA pickup location is missing its id field.Ensure every object in pickup_locations includes both loccode and id.
400VALIDATION_ERRORpickup_locations exceeds the maximum of 50 entries.Reduce the number of pickup locations to 50 or fewer per request.
404LOCCODE_NOT_FOUNDA school or pickup loccode is malformed or unregistered.Check the Loccode. Retrieve the exact format from the Maiaddy app.
500INTERNAL_SERVER_ERRORAn unexpected server error occurred.Retry the request. Contact Edurra support with the timestamp if it continues.
503SERVICE_UNAVAILABLEThe routing or weather data source is temporarily unavailable.Wait and retry. Use exponential backoff if retrying programmatically.

Get Schools

Returns schools near a location. Pass a loccode as a query parameter with optional filters for radius, state, LGA, school type, and result limit.

GET
https://api.maiaddy.com/edurra/api/v1/schools?loccode=OY6A%201EZ&radius_km=1

Headers

HeaderRequiredValue
AuthorizationYesBearer YOUR_API_KEY

Query — Request parameters

FieldTypeRequiredDescription
loccodestringYesThe Loccode for the target location. Must be exactly as issued. Example: OY6A 1EZ
radius_kmnumberNoThe search radius in kilometres around the loccode. Example: 1
statestringNoFilter results to a specific Nigerian state.
lgastringNoFilter results to a specific Local Government Area.
school_typestringNoFilter by school type: nursery, primary, secondary, tertiary, library.
limitnumberNoMaximum number of schools to return.

Example query params

loccode=OY6A 1EZ&radius_km=1

Full curl command

curl -X GET "https://api.maiaddy.com/edurra/api/v1/schools?loccode=OY6A%201EZ&radius_km=1" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response — 200 OK

{
  "success": true,
  "message": "Schools retrieved successfully",
  "timestamp": 1781777662985,
  "data": {
    "search_location": {
      "latitude": 7.419050761206895,
      "longitude": 3.897207932758622,
      "state": "Oyo",
      "lga": "Ibadan North"
    },
    "schools": [
      {
        "school_id": "78bf7da98bbe19c9",
        "loccode": "OY5A 4FR",
        "state": "Oyo State",
        "name": "Educational Advancement Centre",
        "school_type": "primary",
        "latitude": "7.4181966",
        "longitude": "3.9009386",
        "distance_km": 0.42
      }
    ],
    "data_updated_at": "2026-06-18T10:14:22Z"
  }
}

Response fields

FieldTypeDescription
successbooleantrue when the request succeeds.
messagestringHuman-readable result summary.
timestampnumberUnix timestamp in milliseconds.
data.search_locationobjectResolved coordinates and administrative labels for the queried loccode.
data.schoolsarraySchool objects with school_id, loccode, name, school_type, distance_km, capacity_estimate, access_score.
data.data_updated_atstringISO 8601 timestamp of when the data was generated.

Errors

HTTP statusError codeWhat it meansWhat to do
400LOCCODE_REQUIREDThe loccode query parameter is missing.Add loccode to the query string.
404LOCCODE_NOT_FOUNDThe Loccode is formatted incorrectly or does not match any registered location.Check the loccode. Retrieve the exact format from the Maiaddy app.
400INVALID_SCHOOL_TYPEThe school_type value is not recognised.Use a supported value: nursery, primary, secondary, tertiary, or library.
500INTERNAL_SERVER_ERRORAn unexpected server error occurred.Retry the request. Contact Edurra support if it continues.
503SERVICE_UNAVAILABLEThe data source is temporarily unavailable.Wait and retry. Use exponential backoff if retrying programmatically.

Get Catchment

Returns a catchment area analysis for a location. Pass a loccode as a query parameter and the API returns schools within the catchment radius, estimated total school capacity, estimated local school-age population, and current weather conditions.

GET
https://api.maiaddy.com/edurra/api/v1/catchment?loccode=OY6A%201EZ

Headers

HeaderRequiredValue
AuthorizationYesBearer YOUR_API_KEY

Query — Request parameters

FieldTypeRequiredDescription
loccodestringYesThe Loccode for the target location. Must be exactly as issued. Example: OY6A 1EZ
statestringNoSupplementary state filter. Only functions when a valid loccode is also present.
lgastringNoSupplementary LGA filter. Only functions when a valid loccode is also present.
radius_kmnumberNoThe catchment radius in kilometres. Defaults to 8.0 if not provided.

Example query params

loccode=OY6A 1EZ

Full curl command

curl -X GET "https://api.maiaddy.com/edurra/api/v1/catchment?loccode=OY6A%201EZ" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response — 200 OK

{
  "success": true,
  "message": "Catchment analysis retrieved successfully",
  "timestamp": 1781710882137,
  "data": {
    "product": "Edurra-Catchment Premium",
    "search_parameters": {
      "loccode": "OY6A 1EZ",
      "state": "Oyo",
      "radius_km": 8.0
    },
    "target_location": {
      "latitude": 7.419050761206895,
      "longitude": 3.897207932758622,
      "state": "Oyo",
      "lga": "Ibadan North"
    },
    "current_weather": {
      "condition": "stormy",
      "temperature_c": 25.3,
      "precipitation_expected": true
    },
    "catchment_analysis": {
      "schools_in_catchment": 30,
      "total_school_capacity_estimate": 100800,
      "local_population_estimate": 25000,
      "school_age_population_estimate": 5000,
      "schools": [
        {
          "school_id": "b56f86a6c7284cdda3df2616c29e29ef",
          "loccode": "OY6A 1OR",
          "name": "Educational Advancement Centre",
          "school_type": "primary",
          "distance_km": 0.42
        }
      ]
    },
    "data_updated_at": "2026-06-17T15:41:22Z"
  }
}

Response fields

FieldTypeDescription
successbooleantrue when the request succeeds.
messagestringHuman-readable result summary.
data.productstringProduct name (Edurra-Catchment Premium).
data.search_parametersobjectEchoes back query parameters with defaults applied.
data.target_locationobjectResolved details for the queried loccode.
data.current_weatherobjectWeather at the target location.
data.catchment_analysisobjectschools_in_catchment, total_school_capacity_estimate, local_population_estimate, school_age_population_estimate, schools array.
data.data_sourcesarray of stringsData sources used to generate the catchment analysis.
data.data_updated_atstringISO 8601 timestamp of when the data was generated.

Errors

HTTP statusError codeWhat it meansWhat to do
400LOCCODE_REQUIREDThe loccode query parameter is missing.Add loccode to the query string.
404LOCCODE_NOT_FOUNDThe Loccode is formatted incorrectly or does not match any registered location.Check the loccode. Retrieve the exact format from the Maiaddy app.
500INTERNAL_SERVER_ERRORAn unexpected server error occurred.Retry the request. Contact Edurra support if it continues.
503SERVICE_UNAVAILABLEThe data source is temporarily unavailable.Wait and retry. Use exponential backoff if retrying programmatically.

Get Demographics

Returns demographic data for the area surrounding a location. Pass a loccode as a query parameter and the API returns the resolved address, current weather, and a demographic summary covering population, school-age population, literacy rate, urbanisation, and income brackets.

GET
https://api.maiaddy.com/edurra/api/v1/demographics?loccode=OY6A%201EZ

Headers

HeaderRequiredValue
AuthorizationYesBearer YOUR_API_KEY

Query — Request parameters

FieldTypeRequiredDescription
loccodestringYesThe Loccode for the target location. Must be exactly as issued. Example: OY6A 1EZ
addressstringNoAn optional address string to supplement the loccode. Example: Ogba
statestringNoSupplementary state filter. Only functions when a valid loccode is also present.
lgastringNoSupplementary LGA filter. Only functions when a valid loccode is also present.

Example query params

loccode=OY6A 1EZ

Full curl command

curl -X GET "https://api.maiaddy.com/edurra/api/v1/demographics?loccode=OY6A%201EZ" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response — 200 OK

{
  "success": true,
  "message": "Demographics retrieved successfully",
  "timestamp": 1781711424010,
  "data": {
    "search_parameters": {
      "loccode": "OY6A 1EZ",
      "address": "Obafemi Awolowo Avenue, Ibadan North, Oyo State, 200285, Nigeria",
      "state": "Oyo",
      "lga": "Ibadan North"
    },
    "location": {
      "latitude": 7.419050761206895,
      "longitude": 3.897207932758622,
      "state": "Oyo",
      "lga": "Ibadan North",
      "formatted_address": "Obafemi Awolowo Avenue, Ibadan North, Oyo State, 200285, Nigeria"
    },
    "current_weather": {
      "condition": "stormy",
      "temperature_c": 25.1,
      "precipitation_expected": true
    },
    "demographic_summary": {
      "state_population": { "value": 6823000, "source": "NPC Nigeria 2022 Projection" },
      "local_area_population": { "value": 1090000, "source": "NPC Nigeria 2022 Projection", "is_estimate": false },
      "school_age_population": { "value": 259420, "source": "UNICEF MICS Nigeria 2021" },
      "literacy_rate": { "value": 0.79, "source": "UNESCO UIS 2022" },
      "urban_percentage": { "value": 0.61, "source": "UN-Habitat World Cities Report 2023" },
      "rural_percentage": { "value": 0.39, "source": "UN-Habitat World Cities Report 2023" }
    },
    "data_updated_at": "2026-06-17T15:50:23Z"
  }
}

Response fields

FieldTypeDescription
successbooleantrue when the request succeeds.
messagestringHuman-readable result summary.
data.search_parametersobjectEchoes back query parameters and resolved address.
data.locationobjectResolved location details for the queried loccode.
data.current_weatherobjectWeather at the target location.
data.demographic_summaryobjectstate_population, local_area_population, school_age_population, literacy_rate, urban/rural percentages, income_brackets.
data.data_sourcesarray of stringsData sources used to generate the demographic summary.
data.notestringMethodology note on demographic estimates.

Errors

HTTP statusError codeWhat it meansWhat to do
400LOCCODE_REQUIREDThe loccode query parameter is missing.Add loccode to the query string.
404LOCCODE_NOT_FOUNDThe Loccode is formatted incorrectly or does not match any registered location.Check the loccode. Retrieve the exact format from the Maiaddy app.
500INTERNAL_SERVER_ERRORAn unexpected server error occurred.Retry the request. Contact Edurra support if it continues.
503SERVICE_UNAVAILABLEThe data source is temporarily unavailable.Wait and retry. Use exponential backoff if retrying programmatically.

Error reference

HTTP error codes the Edurra API can return across any endpoint.

HTTP status codes — all endpoints

HTTP statusError codeWhat it meansWhat to do
400Bad RequestThe request is malformed; a required field is missing, a Loccode is incorrectly formatted, or a field value is not recognised.Check the request. Make sure all required fields are present and the Loccode is exactly as issued. See The Loccode.
404Not FoundThe endpoint URL is wrong, or a Loccode does not match any registered location in the database.Verify the URL is correct and the Loccode exists in the Maiaddy platform.
429Too Many RequestsThe request rate limit has been exceeded. Default: 60 requests per minute per API key.Reduce request frequency. Use exponential backoff when retrying programmatically.
500Internal Server ErrorAn unexpected error occurred on the server.Retry after a short delay. Contact Edurra support if it persists — include the request details and timestamp.
503Service UnavailableThe API or a data source it depends on is temporarily offline.Wait and retry. Contact support if the issue continues.

Error response body

When an error occurs, the API returns a JSON body alongside the error status code:

{
  "success": false,
  "errorCode": "ERROR_CODE_STRING",
  "message": "A plain-language description of what went wrong.",
  "errors": { "fieldName": "specific field error message" },
  "timestamp": 1781538439435
}

Quick reference

Endpoints at a glance

EndpointMethodPathRequired parameters
Get Bus RoutePOST/bus-routeschool_loccode, school_id, pickup_locations (each with loccode and id)
Get SchoolsGET/schoolsloccode
Get CatchmentGET/catchmentloccode
Get DemographicsGET/demographicsloccode

NOTE

All GET requests require Authorization: Bearer YOUR_API_KEY. The POST bus-route endpoint additionally requires Content-Type: application/json.

Supported school types

The following school types are accepted by the schools and catchment endpoints as filter values. Values are not case-sensitive.

nursery       primary       secondary       tertiary       library

Further Resources

Everything you need to go further with the Edurra API.

SDK documentation

SDKs for Python and Java are available and cover all four endpoints. See the Edurra SDK guide for installation, authentication, and working code examples for every endpoint.

The Loccode

Loccodes are generated and validated by the Maiaddy location intelligence platform. Retrieve them from the Maiaddy app — do not guess or construct one manually. The API returns 404 for any Loccode that is malformed or unregistered.

Getting help

For bug reports, feature requests, or integration questions, contact the Maiaddy team directly.