Search API
Search API Documentation
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 parameters429 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 |