Skip to main content

Endpoint reference

All paths are relative to https://<your-api-host>/api/v2, and every request needs an Authorization header — see Authentication.

MethodPathPurpose
GET/v2/public/coursesEvery public course, with its next class
GET/v2/public/popularThe three most-registered courses
GET/v2/public/classesPaginated, filterable class search
GET/v2/public/course/{id}/classesThe same search, scoped to one course
GET/v2/public/course/{id}A single course
GET/v2/public/class/{id}A single class, in full

List public courses​

GET /v2/public/courses

Every public course, alphabetically by name, each with a summary of its next upcoming public class. Designed to render a course catalogue page in one request.

Query parameters​

NameTypeDescription
typestring or arrayRestrict to one or more course types. Repeat the key for several: ?type[]=Online&type[]=Blended. Must be Online, Brick and Mortar, or Blended.

This endpoint is not paginated — it returns the full catalogue. limit and page are ignored if sent.

Response 200​

{
"data": [
{
"id": 12,
"name": "Basic Safety Training",
"upcoming_class": {
"start": "2026-10-06",
"end": "2026-10-10",
"type": "Brick and Mortar",
"city": "Norfolk",
"state": "VA",
"cost": 129500,
"available_seats": 4
}
},
{
"id": 19,
"name": "Radar Observer Recertification",
"upcoming_class": null
}
]
}

upcoming_class is null when a course has no upcoming public class — render the course without a "next date" rather than hiding it.

Example​

curl -H "Authorization: Bearer $TOKEN" \
"$API_BASE/v2/public/courses?type[]=Online&type[]=Blended"

GET /v2/public/popular

The three courses with the most registrations of all time, each with its next upcoming public class. Intended for a homepage "most popular" strip.

Takes no parameters.

Response shape

This response is a bare JSON array, not an object with a data key.

Response 200​

[
{
"id": 12,
"name": "Basic Safety Training",
"upcoming_class": {
"id": 340,
"cost": 129500,
"start": "2026-10-06",
"end": "2026-10-10",
"available_seats": 4
}
}
]

The upcoming_class shape here differs from /v2/public/courses: it carries the class id (so you can link straight to it) but no location or type.


Search classes​

GET /v2/public/classes

Paginated search across every upcoming public class. This is the endpoint behind a "find a class" page.

Results are ordered by start date ascending. Classes in the past are excluded, except for online courses, which have no fixed sitting and are always included.

Query parameters​

NameTypeDefaultDescription
searchstring—Case-insensitive partial match on the course name.
startMM-DD-YYYY—Only classes starting on or after this date.
endMM-DD-YYYY—Only classes starting on or before this date.
dateMM-DD-YYYY—Only classes running on this date (start ≤ date ≤ end).
limitinteger ≤ 5025Results per page.
pageinteger1Page number.

Date filters use MM-DD-YYYY, unlike the YYYY-MM-DD dates in responses.

Validate dates before sending them

The literal string invalid date is accepted and ignored for start, end, and date, which lets a front-end pass a half-filled date picker straight through. Any other unparseable value raises a 500.

Response 200​

{
"data": [
{
"id": "340",
"course_id": "12",
"course": "Basic Safety Training",
"start": "2026-10-06",
"end": "2026-10-10",
"type": "Brick and Mortar",
"city": "Norfolk",
"state": "VA",
"schedule": null,
"cost": 129500,
"full": false,
"available_seats": 4
}
],
"total": 87,
"last_page": 4
}
FieldNotes
id, course_idReturned as strings here, and as integers elsewhere. Compare loosely or cast.
city, statenull for online classes and for classes with no room assigned yet.
scheduleNot populated in search results. Use Get a class for the schedule text.
fulltrue only when a capped class has no seats left. An uncapped class is never full.
available_seatsnull when uncapped. See Seat counts.
total, last_pagePagination metadata, alongside data rather than nested.

Example​

curl -H "Authorization: Bearer $TOKEN" \
"$API_BASE/v2/public/classes?search=safety&start=10-01-2026&end=12-31-2026&limit=10&page=1"

Search a course's classes​

GET /v2/public/course/{id}/classes

Identical to Search classes — same parameters, same response shape — but restricted to one course. Use it for a course detail page's list of sittings.

curl -H "Authorization: Bearer $TOKEN" \
"$API_BASE/v2/public/course/12/classes?limit=50"

A course that is not public returns an empty result set rather than a 404.


Get a course​

GET /v2/public/course/{id}

Response 200​

{
"id": 12,
"name": "Basic Safety Training",
"type": "Brick and Mortar",
"description": "<p>A five-day STCW course covering...</p>"
}

description may contain HTML authored in the AnchorPoint admin. Sanitise it before rendering it into your page.

Returns 404 if the course does not exist or is not public.


Get a class​

GET /v2/public/class/{id}

Full detail for a single class — the endpoint behind a "class details" page or a registration call-to-action.

Response 200​

{
"course_id": 12,
"course_name": "Basic Safety Training",
"course_type": "Brick and Mortar",
"start": "2026-10-06",
"end": "2026-10-10",
"schedule": "Mon-Fri, 08:00-16:30",
"cost": 129500,
"can_register": true,
"location": {
"name": "Norfolk Training Center",
"room": "Classroom B",
"city": "Norfolk",
"state": "VA",
"zip": "23510",
"country": "US"
},
"down_payment": "25000",
"registration_id": null,
"prev_reg_test_date": null,
"open_seats": 4
}
FieldNotes
scheduleFree-text schedule description entered by staff. May be null.
can_registerWhether registration is open: seats remain and the class has not started. Always true for online courses.
locationAn object for in-person classes. For online courses it is the literal string "online" — check the type before reading properties. Fields are null when no room has been assigned yet.
down_paymentCents, but returned as a string ("25000") because of the underlying column type. null if the class requires payment in full. Cast before doing arithmetic.
open_seatsnull when uncapped.
Reading this endpoint with an API token

registration_id and prev_reg_test_date are personalisation fields resolved from the signed-in user. With an API token there is no user, so they are always null. can_register likewise reflects only class-level availability, not whether a particular person is eligible. If you need per-student state, the caller must authenticate with a JWT instead.

Returns 404 if the class does not exist, is not public, or belongs to a non-public course.