Postings API

Endpoints for managing tutoring postings -- the mechanism through which parents describe their needs and tutors apply for matches.

GET /api/postings All authenticated roles

List postings. Behavior varies by role: Admin sees all postings with full details and application counts. Tutor sees open postings available for application. Parent sees own postings with application status.

ParameterTypeDescription
statusstringOpen | Filled | Closed
subjectstringFilter by subject
pagenumberPage number (default: 1)
Response
{
  "ok": true,
  "data": {
    "postings": [
      {
        "id": 15,
        "parent_user_id": 42,
        "child_id": 8,
        "subject": "Mathematics",
        "level": "Primary 4",
        "schedule_preference": "Weekday afternoons",
        "location_preference": "Home (Tampines)",
        "special_needs": "ADHD - needs patient, structured approach",
        "status": "Open",
        "application_count": 3,
        "created_at": "2026-03-15T08:00:00Z"
      }
    ]
  }
}
POST /api/postings Parent, Admin

Create a new posting.

ParameterTypeDescription
child_idnumberChild to create posting for
subjectstringSubject needed
levelstringEducation level
schedule_preferencestringPreferred schedule
location_preferencestringWhere sessions should take place
special_needsstringAny special requirements
gender_preferencestringTutor gender preference
language_preferencestringPreferred teaching language(s)
additional_notesstringExtra context for tutors
Response
{
  "ok": true,
  "data": { "id": 16, ... }
}
GET /api/postings/:id Parent owner, Admin

Fetch a single posting. Parent receives the blind educator review view for their own posting. Admin should use the dedicated admin detail route for full application data. Tutors should use /api/postings/browse instead of this endpoint.

Response
{
  "ok": true,
  "data": { "id": 15, "status": "Open", "timing_preferences": [ ... ] }
}
Role-safe detail access

/api/postings/:id is not a generic cross-role detail endpoint. It is restricted to the owning parent or admin access patterns so tutors cannot query admin-style application payloads.

POST /api/postings/:id/apply tutor

Apply to an open posting.

ParameterTypeDescription
notestringApplication note from the tutor
Response
{
  "ok": true,
  "data": { "application_id": 27, "status": "Pending" }
}
POST /api/postings/:id/push admin

Push a tutor application to the parent for review.

ParameterTypeDescription
application_idnumberApplication to push
coordinator_notestringNote for the parent
Response
{
  "ok": true,
  "data": { "status": "Pushed" }
}
POST /api/postings/:id/accept parent

Parent accepts a pushed tutor. Creates the match and auto-schedules sessions.

ParameterTypeDescription
application_idnumberApplication to accept
Response
{
  "ok": true,
  "data": { "match_id": 15, "sessions_created": 4 }
}

On acceptance:

  • Match status is set to Parent_Accepted
  • Sessions are auto-created for the next 4 weeks
  • All other applications to this posting are silently rejected
  • Applicable discounts are attached to relevant sessions

Match Scoring

Each application is scored across 5 dimensions (total 0-100):

Score Breakdown
{
  "subject_score": 22,        // 0-25
  "language_score": 15,       // 0-20
  "gender_score": 15,         // 0-15
  "timing_score": 16,         // 0-20
  "special_needs_score": 20,  // 0-20
  "total_score": 88
}

Posting Statuses

StatusDescription
OpenAccepting applications from tutors
FilledParent accepted a tutor, match created
ClosedPosting withdrawn by parent or coordinator

Application Statuses

StatusDescription
PendingTutor has submitted application, awaiting coordinator review
PushedCoordinator has pushed this application to the parent
ShortlistedParent has shortlisted this tutor for consideration
RejectedApplication rejected (silently when another tutor is accepted, or explicitly)
WithdrawnTutor withdrew their own application