RAID API
  1. Public
  • DiveRAID frontend public API
    • Search divers
      POST
    • Search instructors
      POST
    • Search dive centers
      POST
    • Search dive centers by country
      GET
  • DiveRAID rest API V1
    • Auth
      • Register a new user
      • Login and get a Sanctum token
      • Send password reset email
      • Reset password using token
      • Logout and revoke the current token
      • Resend email verification
    • Profile
      • Get authenticated user profile
      • Update profile
      • Delete account
      • Update password
      • Update dive center association
    • Diver
      • Courses
        • List active courses
        • List expired courses
        • Get course detail
        • Submit module quiz
        • Get quiz result
        • Submit course exam
        • Get exam result
        • Get skills progress
        • Sign skills (diver)
      • Free Learnings
        • List enrolled free learnings
        • List available free learning courses
        • Enroll in a free learning course
        • Get free learning detail
        • Submit free learning module quiz
        • Get free learning quiz result
      • Certifications
        • Get certification history
        • Get certification quiz result
        • Get certification exam result
        • Get certification skills
        • List diver certifications
      • Dive Logs
        • List dive logs (paginated)
        • Create dive log
        • Get dive log
        • Update dive log
      • Awards
        • List award cards
      • Documents
        • List diver documents
      • Forms
        • List diver forms
      • Medical
        • Get medical questionnaire structure
        • Submit medical questionnaire
      • Store
        • List courses available for purchase
        • Get order status
    • Professional
      • Students
        • List students
        • Get student progress
        • Get student quiz result
        • Get student exam result
        • Get student skills progress
        • Sign student skills
      • Certifications
        • List all professional certifications
        • List diver-level certifications
        • List specialty certifications
        • List professional certifications
        • List trainer certifications
        • List examiner certifications
        • Get certification history
        • Get certification quiz result
        • Get certification exam result
        • Get certification skills
      • Classroom
        • List classrooms
        • Get classroom progress (all students)
        • Get classroom student progress
        • Get classroom student quiz result
        • Get classroom student exam result
        • Get classroom student skills
        • Sign classroom student skills
      • Renewals
        • List renewal courses
        • Get renewal progress
        • Submit renewal module quiz
        • Get renewal quiz result
        • Submit renewal exam
        • Get renewal exam result
        • Get renewal skills progress
        • Sign renewal skills
      • Recognitions
        • List recognition courses
      • Dive Logs
        • List student dive logs for a course
        • Get student dive log
        • Sign student dive log
      • Store
    • Sync
      • Get sync status
      • Download full course data for offline use
      • Upload offline operations
    • Dive Center
    • Public
      • List all countries
        GET
      • Get country data
        GET
      • Get country divisions (states/provinces)
        GET
      • List time zone identifiers, optionally narrowed to one country
        GET
      • List, search, and radius-search publicly visible dive centres
        GET
      • Every publicly visible, geolocated dive centre as a map marker
        GET
      • Countries with at least one publicly visible dive centre
        GET
      • Full detail of one publicly visible dive centre
        GET
  • Schemas
    • Frontend API Schema
      • DiverSearch
    • SuccessResponse
    • ValidationErrorResponse
    • TokenResponse
    • ErrorResponse
    • UserProfile
    • CourseLog
    • CourseLogDetail
    • QuizResult
    • ExamResult
    • SkillProgress
    • DiveLog
    • Certification
    • PaginatedDiveLogs
    • StoreItem
    • PaymentIntentResponse
    • OrderConfirmResponse
    • OrderStatusResponse
    • InstructorSearch
    • DiveCenterSearch
  1. Public

List, search, and radius-search publicly visible dive centres

GET
https://test.diveraid.com/api/v1/public/dive-centers
Public
Maintainer:Not configured

Overview#

Paginated, searchable list of publicly visible dive centres. Switches to radius mode when lat/lng are both given, ordering by distance instead of name and carrying distance_km on every row. Replaces GET /api/v1/utility/dive-centers, which returned every active centre unpaginated and leaked email in a searchable list - both fixed here (D-C3, S9 in docs/api/_alignment/contract-baseline.md).
Controller: App\Http\Controllers\Api\V1\Public\DiveCenterController::index()
Route name: api.v1.public.dive-centers.index

Authentication#

Type: None (public endpoint)
Additional middleware: throttle:public. See docs/api/README.md §14.

Request#

Method: GET
Path: /api/v1/public/dive-centers

Query parameters#

ParameterTypeRequiredDefaultDescription
searchstringNononeMatches name, city, raid_id only - never email
countrystring(2)NononeISO 3166-1 alpha-2, validated against the platform country list
per_pageintegerNo20Maximum 100
pageintegerNo1
latnumberRequired together with lngnone-90..90. Presence of lat, lng, or radius_km requires the other two coordinate fields
lngnumberRequired together with latnone-180..180
radius_kmintegerNo (only meaningful with lat/lng)501..500

Example request#

Plain list:
Radius search around Rome:

Response 200 OK#

Shaped exactly like GET /api/v1/diver/dive-logs: the collection sits at data.data, the pagination at data.meta, no links key. distance_km is present only in radius mode. Captured live, plain list (per_page=3, 449 centres total at capture time):
{
  "success": true,
  "status": "success",
  "message": "OK",
  "data": {
    "data": [
      {
        "id": 1132,
        "raid_id": "DCMX24-609-707",
        "name": "Cozumel Top Dive Experience",
        "country": { "value": "MX", "label": "Mexico" },
        "city": "Cozumel",
        "logo": "https://example.com/dive_centers/logo.webp",
        "location": null
      },
      {
        "id": 856,
        "raid_id": "DCCN22-880-975",
        "name": "18M Diving",
        "country": { "value": "CN", "label": "China" },
        "city": "Macao SAR",
        "logo": "https://example.com/dive_centers/logo.webp",
        "location": { "lat": 22.20004, "lng": 113.54933 }
      }
    ],
    "meta": { "current_page": 1, "last_page": 150, "per_page": 3, "total": 449 }
  }
}
Captured live, radius search (lat=41.9028&lng=12.4964&radius_km=50, one centre within range at capture time):
{
  "success": true,
  "status": "success",
  "message": "OK",
  "data": {
    "data": [
      {
        "id": 287,
        "raid_id": "DCIT15-960-660",
        "name": "ROMA SUB",
        "country": { "value": "IT", "label": "Italy" },
        "city": "roma",
        "logo": "https://example.com/dive_centers/logo.webp",
        "location": { "lat": 41.890293, "lng": 12.3827714 },
        "distance_km": 9.5
      }
    ],
    "meta": { "current_page": 1, "last_page": 1, "per_page": 20, "total": 1 }
  }
}

Response fields#

FieldTypeNullableAlways presentDescription
data.data[].idintegerNoYesNumeric primary key. This is what RegisterRequest::dive_center and UpdateDiveCenterRequest::dive_center_id take - not raid_id
data.data[].raid_idstringNoYesThe path identifier for GET .../dive-centers/{raid_id}
data.data[].namestringNoYes
data.data[].countryobjectNoYes{value, label}, same shape as GET /api/v1/public/countries
data.data[].citystringYesYes
data.data[].logostringYesYesnull when the centre has no logo uploaded
data.data[].locationobjectYesYes{lat, lng} as floats, or null when the centre's coordinates fail validation (see §14's coordinate-coverage caveat)
data.data[].distance_kmnumberNoOnly in radius modeRounded to 1 decimal, ascending order
data.meta.current_pageintegerNoYes
data.meta.last_pageintegerNoYes
data.meta.per_pageintegerNoYes
data.meta.totalintegerNoYesHonours every active filter, including the radius

Errors#

422 Unprocessable Entity — validation#

Standard FormRequest envelope. Causes: per_page above 100, unrecognised country, lat given without lng (or vice versa), radius_km above 500 or below 1.
{
  "success": false,
  "status": "error",
  "message": "Validation failed",
  "errors": {
    "per_page": ["The per page field must not be greater than 100."]
  }
}

429 Too Many Requests#

Behind the dedicated public limiter (300 requests per minute, keyed by IP). No errors key.
{
  "success": false,
  "status": "error",
  "message": "Too many requests"
}

Notes#

Side effect of D2 (coordinate validity): a centre with unusable lat/lng still appears in this list with location: null. It is excluded from GET .../dive-centers/map and from every radius search, even when its garbled coordinates would numerically fall inside the requested radius.
Radius mode filters through whereRaw, not having: data.meta.total correctly reflects only the centres inside the radius, because the pagination count query keeps WHERE clauses but drops SELECT-level aggregates.
Logo and social-link URLs in the examples above are replaced with placeholders; every other field is a real captured value. Personal and contact values (manager name, email, phone) never appear on this endpoint at all - they are detail-only, see GET .../dive-centers/{raid_id}.
Replaces GET /api/v1/utility/dive-centers (removed; see docs/api/_archive/utility/GET_dive_centers.md), which was unpaginated, had no search or radius, and exposed email on every row.

Request

Query Params

Responses

🟢200
application/json
Success
Bodyapplication/json

🟠422
🟠429
Request Request Example
Shell
JavaScript
Java
Swift
curl --location 'https://test.diveraid.com/api/v1/public/dive-centers?search=&country=&per_page=&page=&lat=&lng=&radius_km='
Response Response Example
200 - Example 1
{
    "status": "success",
    "message": "string",
    "data": {
        "data": [
            {
                "id": 0,
                "raid_id": "string",
                "name": "string",
                "country": {
                    "value": "IT",
                    "label": "Italy"
                },
                "city": "string",
                "logo": "string",
                "location": {
                    "lat": 0,
                    "lng": 0
                },
                "distance_km": 0
            }
        ],
        "meta": {
            "current_page": 0,
            "last_page": 0,
            "per_page": 0,
            "total": 0
        }
    }
}
Modified at 2026-09-25 16:28:03
Previous
List time zone identifiers, optionally narrowed to one country
Next
Every publicly visible, geolocated dive centre as a map marker
Built with