Skip to main content

Search API

Search API Documentation

Author: Josh S. Sakweli, Backend Lead Team
Last Updated: 2025-12-23
Version: v1.0

Base URL: https://api.nextgate.com/api/v1

Short Description: Public search endpoints for discovering users and shops on the Nexgate platform. These endpoints power the @mention and $shop autocomplete features across the application.

Hints:

  • Use @ prefix for user search (automatically stripped)
  • Use $ prefix for shop search (automatically stripped)
  • Results are ordered by relevance: exact match → starts with → contains
  • All endpoints are public and do not require authentication
  • Rate limiting applies to prevent abuse

Standard Response Format

All API responses follow a consistent structure using our Globe Response Builder pattern:

Success Response Structure

{
  "success": true,
  "httpStatus": "OK",
  "message": "Operation completed successfully",
  "action_time": "2025-12-23T10:30:45",
  "data": {
    // Actual response data goes here
  }
}

Error Response Structure

{
  "success": false,
  "httpStatus": "BAD_REQUEST",
  "message": "Error description",
  "action_time": "2025-12-23T10:30:45",
  "data": "Error description"
}

Endpoints

1. Search Users

Purpose: Search for users by username, first name, or last name for @mentions and user discovery.

Endpoint: GET {base_url}/users/search

Access Level: 🌐 Public (Rate limited)

Authentication: None

Query Parameters:

Parameter Type Required Description Validation Default
q string No Search query (username, first name, or last name). @ prefix is automatically removed Min: 1 character after trimming -
page integer No Page number (1-based) Min: 1 1
size integer No Number of results per page Min: 1, Max: 50 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Users retrieved successfully",
  "action_time": "2025-12-23T11:14:05.293524449",
  "data": {
    "content": [
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "userName": "john_doe",
        "displayName": "John Doe",
        "avatarUrl": "https://cdn.nextgate.com/avatars/john_doe.jpg",
        "isVerified": true
      },
      {
        "id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
        "userName": "johnny_b",
        "displayName": "Johnny Brown",
        "avatarUrl": null,
        "isVerified": false
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 10,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": false,
    "totalPages": 3,
    "totalElements": 25,
    "first": true,
    "size": 10,
    "number": 0,
    "numberOfElements": 10,
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "empty": false
  }
}

Success Response Fields:

Field Description
content Array of user objects matching the search query
content[].id Unique identifier of the user
content[].userName Username of the user
content[].displayName Full display name (firstName + lastName, or userName if not available)
content[].avatarUrl URL to user's profile picture (null if not set)
content[].isVerified Whether the user account is verified
totalElements Total number of users matching the query
totalPages Total number of pages available
first Whether this is the first page
last Whether this is the last page

Empty Result Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Users retrieved successfully",
  "action_time": "2025-12-23T11:14:05.293524449",
  "data": {
    "content": [],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 10,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": true,
    "totalPages": 0,
    "totalElements": 0,
    "first": true,
    "size": 10,
    "number": 0,
    "numberOfElements": 0,
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "empty": true
  }
}

Example Requests:

Use Case Request
Basic search /users/search?q=john
Search with @ prefix /users/search?q=@john
Paginated search /users/search?q=john&page=2&size=20

2. Search Shops

Purpose: Search for shops by name, slug, or tagline for $mentions and shop discovery.

Endpoint: GET {base_url}/shops/search

Access Level: 🌐 Public (Rate limited)

Authentication: None

Query Parameters:

Parameter Type Required Description Validation Default
q string No Search query (shop name, slug, or tagline). $ prefix is automatically removed Min: 1 character after trimming -
page integer No Page number (1-based) Min: 1 1
size integer No Number of results per page Min: 1, Max: 50 10

Success Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Shops retrieved successfully",
  "action_time": "2025-12-23T11:20:30.123456789",
  "data": {
    "content": [
      {
        "shopId": "c3d4e5f6-a7b8-9012-cdef-123456789012",
        "shopName": "Mama's Kitchen",
        "shopSlug": "mamas-kitchen",
        "tagline": "Best local food in town",
        "logoUrl": "https://cdn.nextgate.com/shops/mamas-kitchen/logo.jpg",
        "isVerified": true,
        "verificationBadge": "GOLD",
        "city": "Dar es Salaam"
      },
      {
        "shopId": "d4e5f6a7-b8c9-0123-def0-234567890123",
        "shopName": "Mama Lishe",
        "shopSlug": "mama-lishe",
        "tagline": "Authentic Tanzanian cuisine",
        "logoUrl": null,
        "isVerified": false,
        "verificationBadge": null,
        "city": "Arusha"
      }
    ],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 10,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": false,
    "totalPages": 2,
    "totalElements": 15,
    "first": true,
    "size": 10,
    "number": 0,
    "numberOfElements": 10,
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "empty": false
  }
}

Success Response Fields:

Field Description
content Array of shop objects matching the search query
content[].shopId Unique identifier of the shop
content[].shopName Display name of the shop
content[].shopSlug URL-friendly unique identifier
content[].tagline Short promotional text for the shop
content[].logoUrl URL to shop's logo image (null if not set)
content[].isVerified Whether the shop is verified
content[].verificationBadge Verification badge level (GOLD, SILVER, BRONZE, or null)
content[].city City where the shop is located
totalElements Total number of shops matching the query
totalPages Total number of pages available
first Whether this is the first page
last Whether this is the last page

Empty Result Response JSON Sample:

{
  "success": true,
  "httpStatus": "OK",
  "message": "Shops retrieved successfully",
  "action_time": "2025-12-23T11:20:30.123456789",
  "data": {
    "content": [],
    "pageable": {
      "pageNumber": 0,
      "pageSize": 10,
      "sort": {
        "empty": true,
        "sorted": false,
        "unsorted": true
      },
      "offset": 0,
      "paged": true,
      "unpaged": false
    },
    "last": true,
    "totalPages": 0,
    "totalElements": 0,
    "first": true,
    "size": 10,
    "number": 0,
    "numberOfElements": 0,
    "sort": {
      "empty": true,
      "sorted": false,
      "unsorted": true
    },
    "empty": true
  }
}

Example Requests:

Use Case Request
Basic search /shops/search?q=mama
Search with $ prefix /shops/search?q=$mama
Paginated search /shops/search?q=kitchen&page=2&size=20

Search Ordering Logic

Both search endpoints use smart ordering to return the most relevant results first:

Priority Match Type Example (query: "john")
1 Exact match john
2 Starts with johnny, john_doe
3 Contains big_john, _john_

Results with the same priority are sorted alphabetically.


Error Responses

Standard Error Types:

Application-Level Exceptions (400-499)

  • 400 BAD_REQUEST: Invalid request parameters
  • 429 TOO_MANY_REQUESTS: Rate limit exceeded

Error Response Examples:

Rate Limit Exceeded (429):

{
  "success": false,
  "httpStatus": "TOO_MANY_REQUESTS",
  "message": "Rate limit exceeded. Please try again later.",
  "action_time": "2025-12-23T11:30:45",
  "data": "Rate limit exceeded. Please try again later."
}

Quick Reference

Feature User Search Shop Search
Endpoint /users/search /shops/search
Prefix @ (optional) $ (optional)
Searches userName, firstName, lastName shopName, shopSlug, tagline
Filters Non-locked users only Active, non-deleted shops only
Auth None None