Roomly API specification: student housing data model

Dev GuidesSeptember 5, 202612 min read

Status: Proposed

This document defines a proposed API for exposing Roomly's student housing data and services to external applications. The API described here is a portfolio specification and does not represent a currently deployed public API.

Roomly is a student housing platform that connects students with verified accommodation and provides features including property discovery, bookings, escrow-protected payments, receipt verification, reviews, and roommate matching.

This API is designed around a longer-term vision for Roomly as a student housing data and infrastructure layer. External applications could use the API to discover properties, query availability, retrieve location information, and build housing experiences on top of Roomly's underlying data.


⚠ Proposed SpecificationOpenAPI 3.0 Aligned

This document defines a proposed API specification aligned with OpenAPI 3.0 standards. It is a portfolio specification and does not represent a currently deployed public API. All endpoints, parameters, and response schemas are designed to be programmatically validatable against future implementations.


What are the API goals?

The API should allow developers to:

  • Discover student accommodation
  • Filter properties by location, school, price, type, availability, and verification status
  • Retrieve detailed property information
  • Explore supported schools and locations
  • Check property availability
  • Retrieve aggregated housing market data
  • Build student housing applications and services using Roomly data

The API is designed to be read-oriented in its initial version. Actions involving payments, bookings, withdrawals, and account management remain controlled by Roomly's own application until corresponding public API capabilities are explicitly introduced.


What is the base URL?

The proposed production base URL is:

https://api.roomly.com.ng/v1

The "/v1" path identifies the first version of the API.

Note: This URL is proposed and is not currently presented as a live public API endpoint.


How does authentication work?

Authenticated requests use an API key supplied as a Bearer token.

Authorization: Bearer YOUR_API_KEY

Example:

curl "https://api.roomly.com.ng/v1/properties" \
  -H "Authorization: Bearer YOUR_API_KEY"

API keys should be kept private and must not be exposed in client-side applications or committed to source control.


What is the response format?

Successful responses use JSON.

Collection endpoints return their results inside a "data" property:

{
  "data": [
    {
      "id": "prop_123",
      "name": "Example Lodge",
      "propertyType": "self_contain",
      "area": "Bosso",
      "school": "FUTMINNA",
      "rent": 250000,
      "available": true,
      "verified": true
    }
  ]
}

Single-resource endpoints return the requested resource directly inside "data":

{
  "data": {
    "id": "prop_123",
    "name": "Example Lodge",
    "propertyType": "self_contain",
    "area": "Bosso",
    "school": "FUTMINNA",
    "rent": 250000,
    "available": true,
    "verified": true
  }
}

What resources does the API expose?

The initial API is organized around five primary resources:

ResourcePurpose
propertiesStudent accommodation listings
schoolsSchools and institutions served by Roomly
areasGeographic areas where properties are listed
availabilityCurrent availability information for properties
market-dataAggregated housing and pricing information

How do you work with properties?

Properties are the primary resource in the Roomly API.

How do you list properties?

GET /v1/properties

Returns a paginated list of properties.

What query parameters are supported?

ParameterTypeRequiredDescription
schoolstringNoFilter by school identifier
areastringNoFilter by area identifier
minPriceintegerNoMinimum rent
maxPriceintegerNoMaximum rent
propertyTypestringNoFilter by property type
genderstringNoFilter by gender preference
verifiedbooleanNoReturn only verified properties
availablebooleanNoReturn only currently available properties
pageintegerNoPage number. Defaults to 1.
limitintegerNoNumber of results per page. Defaults to 20.

What property types are supported?

The public Roomly product currently presents property types including:

  • Self Contain
  • One Bedroom
  • Room & Parlor
  • Two Bedroom

The API uses machine-readable identifiers for these values:

Display nameAPI value
Self Containself_contain
One Bedroomone_bedroom
Room & Parlorroom_parlor
Two Bedroomtwo_bedroom

What's an example request?

curl "https://api.roomly.com.ng/v1/properties?area=bosso&propertyType=self_contain&available=true" \
  -H "Authorization: Bearer YOUR_API_KEY"

What's an example response?

{
  "data": [
    {
      "id": "prop_123",
      "name": "Example Lodge",
      "propertyType": "self_contain",
      "area": {
        "id": "area_bosso",
        "name": "Bosso"
      },
      "school": {
        "id": "school_futminna",
        "name": "FUTMINNA"
      },
      "rent": 250000,
      "gender": "any",
      "available": true,
      "verified": true
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 1,
    "totalPages": 1
  }
}

How do you retrieve a single property?

GET /v1/properties/{propertyId}

Example:

curl "https://api.roomly.com.ng/v1/properties/prop_123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Example response:

{
  "data": {
    "id": "prop_123",
    "name": "Example Lodge",
    "description": "Student accommodation near FUTMINNA.",
    "propertyType": "self_contain",
    "rent": 250000,
    "gender": "any",
    "verified": true,
    "available": true,
    "area": {
      "id": "area_bosso",
      "name": "Bosso"
    },
    "school": {
      "id": "school_futminna",
      "name": "FUTMINNA"
    },
    "amenities": ["water", "electricity", "security"]
  }
}

How do you work with schools?

Schools represent educational institutions associated with Roomly properties.

How do you list schools?

GET /v1/schools

Returns schools available for property discovery.

Example response:

{
  "data": [
    {
      "id": "school_futminna",
      "name": "Federal University of Technology, Minna",
      "shortName": "FUTMINNA"
    }
  ]
}

How do you retrieve a single school?

GET /v1/schools/{schoolId}

Returns information about a specific school.

How do you get properties near a school?

GET /v1/schools/{schoolId}/properties

This endpoint provides a convenient way for applications to retrieve accommodation associated with a particular institution.

Example:

curl "https://api.roomly.com.ng/v1/schools/school_futminna/properties" \
  -H "Authorization: Bearer YOUR_API_KEY"

How do you work with areas?

Areas represent geographic locations used for property discovery.

How do you list areas?

GET /v1/areas

The API may return areas such as Bosso, Gidan Kwano, Gidan Mangoro, Gidan Painti, Dama, and Albishiri, which are currently presented as popular Roomly locations.

How do you retrieve a single area?

GET /v1/areas/{areaId}

How do you get properties in an area?

GET /v1/areas/{areaId}/properties

Example:

curl "https://api.roomly.com.ng/v1/areas/area_bosso/properties" \
  -H "Authorization: Bearer YOUR_API_KEY"

How do you check availability?

Availability allows applications to determine whether a property currently has accommodation available.

How do you check property availability?

GET /v1/properties/{propertyId}/availability

Example response:

{
  "data": {
    "propertyId": "prop_123",
    "available": true,
    "availableUnits": 3,
    "lastUpdated": "2026-09-05T12:30:00Z"
  }
}

Availability data should be treated as time-sensitive. Applications should not assume that a property remains available after retrieving this response.


How do you work with market data?

The market-data resource provides aggregated information rather than individual property records.

This allows developers to build applications that answer questions such as:

  • What is the average rent in an area?
  • How many verified properties are available?
  • Which property types are most common?
  • How does pricing vary between areas?

How do you retrieve market data?

GET /v1/market-data

What query parameters are supported?

ParameterTypeRequiredDescription
areastringNoRestrict statistics to an area
schoolstringNoRestrict statistics to a school
propertyTypestringNoRestrict statistics to a property type

Example response:

{
  "data": {
    "area": "Bosso",
    "propertyType": "self_contain",
    "averageRent": 250000,
    "medianRent": 230000,
    "availableProperties": 143,
    "verifiedProperties": 98
  }
}

How do you get area statistics?

GET /v1/areas/{areaId}/statistics

Returns aggregated housing statistics for an area.


How does pagination work?

Collection endpoints use page-based pagination.

GET /v1/properties?page=2&limit=20

A paginated response contains:

{
  "pagination": {
    "page": 2,
    "limit": 20,
    "total": 143,
    "totalPages": 8
  }
}

The maximum permitted "limit" should be enforced by the API to prevent unnecessarily large responses.


How does filtering work?

Filters can be combined in a single request.

Example:

GET /v1/properties?school=school_futminna&area=area_bosso&minPrice=150000&maxPrice=300000&verified=true&available=true

Applications should treat unspecified filters as unrestricted.

If no properties match the supplied filters, the API returns an empty "data" array rather than an error:

{
  "data": [],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 0,
    "totalPages": 0
  }
}

How does sorting work?

Collection endpoints may support sorting using the "sort" and "order" parameters.

GET /v1/properties?sort=rent&order=asc

Supported sorting fields should be limited to fields for which predictable ordering is available:

  • "rent"
  • "createdAt"
  • "updatedAt"

What are the error codes?

The API uses standard HTTP status codes.

StatusMeaning
200Request succeeded
400Invalid request
401Authentication required or invalid
403Request not permitted
404Resource not found
429Rate limit exceeded
500Internal server error

Errors use a consistent response structure:

{
  "error": {
    "code": "PROPERTY_NOT_FOUND",
    "message": "The requested property does not exist."
  }
}

Example: invalid request

{
  "error": {
    "code": "INVALID_PARAMETER",
    "message": "maxPrice must be greater than or equal to minPrice."
  }
}

Applications should use the HTTP status code for broad error handling and the error code for application-specific handling.


What are the rate limits?

The proposed API should enforce rate limits to protect the service from excessive requests.

Authenticated applications may initially receive:

1,000 requests per hour

When a client exceeds its limit, the API returns:

429 Too Many Requests

Rate limits may vary by API plan and can be changed as the service scales.

Note: These limits are part of the proposed API design and are not current Roomly production limits.


How does versioning work?

The API uses URL-based versioning.

https://api.roomly.com.ng/v1/

Breaking changes should result in a new API version rather than silently changing the behaviour of an existing version.

Example:

/v1/properties
/v2/properties

Existing API versions should remain available for a defined deprecation period before removal.


How are resources related?

Roomly resources are related through stable identifiers.

A property belongs to an area and may be associated with a school.

Property
├── Area
├── School
├── Property Type
├── Amenities
└── Availability

Applications should use resource IDs when making API requests rather than relying on display names.

Example:

  • area_bosso is preferred over Bosso when requesting a specific area.

What operations are available?

The initial proposed API focuses on read operations.

Available in the initial API design

GET /v1/properties
GET /v1/properties/{propertyId}
GET /v1/properties/{propertyId}/availability

GET /v1/schools
GET /v1/schools/{schoolId}
GET /v1/schools/{schoolId}/properties

GET /v1/areas
GET /v1/areas/{areaId}
GET /v1/areas/{areaId}/properties
GET /v1/areas/{areaId}/statistics

GET /v1/market-data

Future capabilities

Write operations could eventually expose selected Roomly functionality, including:

  • Creating or updating listings
  • Managing availability
  • Creating reservations
  • Retrieving booking information
  • Managing reviews
  • Receipt verification
  • Partner integrations

These operations require additional authentication, authorization, validation, and security considerations and are outside the scope of this initial specification.


What are the API design principles?

The proposed API follows these principles:

  1. Resource-oriented URLs — URLs represent resources rather than actions.
  2. Predictable responses — related endpoints use consistent response structures.
  3. Explicit filtering — clients can narrow results without requiring separate endpoints for every use case.
  4. Stable identifiers — resources are referenced by IDs rather than display names.
  5. Versioned contracts — breaking changes are isolated behind API versions.
  6. Progressive capability — the initial API exposes useful read operations before introducing higher-risk write operations.
  7. Developer usability — endpoints, parameters, responses, and errors should be predictable enough for developers to integrate without needing access to Roomly's internal implementation.

What's the proposed API surface summary?

Properties
GET /v1/properties
GET /v1/properties/{propertyId}
GET /v1/properties/{propertyId}/availability

Schools
GET /v1/schools
GET /v1/schools/{schoolId}
GET /v1/schools/{schoolId}/properties

Areas
GET /v1/areas
GET /v1/areas/{areaId}
GET /v1/areas/{areaId}/properties
GET /v1/areas/{areaId}/statistics

Market Data
GET /v1/market-data

This specification serves as the proposed contract from which the Roomly Developer Guides can be written.

The guides will explain how to accomplish specific tasks with this API, while this specification defines what the API exposes and how its contract behaves.