openapi: 3.0.3
info:
title: 'Student Matching Platform APi API Documentation'
description: ''
version: 1.0.0
servers:
-
url: 'https://vps117355.serveur-vps.net'
tags:
-
name: 'Academic Information Management'
description: "\nEndpoints for managing academic informations of students"
-
name: 'Admin Notification Management'
description: "\nEndpoints to handle admin-scoped notifications (listing, viewing and marking as read).\n\nThese endpoints return enriched information via the `AdminNotificationResource` and support\nfiltering by read/unread and pagination. They are scoped to the authenticated admin (results limited\nto notifications intended for the authenticated admin).\n\nExample: GET /api/admin/admin_notifications?status=unread&paginated=true"
-
name: 'Authentication Endpoints'
description: "\nEndpoints to handle authentication."
-
name: 'Bundles Management'
description: ''
-
name: 'Contact Management'
description: "\nEndpoints for managing contacts"
-
name: 'Countries Management'
description: "\nManage countries and their associations with study destinations (regions).\nCountries are categorized by region tier: emerging (Africa, Asia) and global (USA, UK, Europe, UAE)."
-
name: 'Credit Management'
description: ''
-
name: 'Credit Purchases & Bundle Payments'
description: ''
-
name: Currency
description: "\nManage currencies"
-
name: 'Current Status Management'
description: "\nManage the current status in the system"
-
name: 'Document Locker'
description: "\nEndpoints to manage the document locker"
-
name: Endpoints
description: ''
-
name: 'HighSchool Management'
description: "\nEndpoints for managing highschools"
-
name: 'Majors Management'
description: ''
-
name: 'Matching Suggestions'
description: "\nAPIs for managing matching suggestions"
-
name: Miscellaneous
description: ''
-
name: 'Payment Management'
description: ''
-
name: 'Personal Information'
description: "\nManage personal informations of a student"
-
name: 'Preferences and goals'
description: "\nManage student preferences."
-
name: 'Special Needs Management'
description: "\nEndpoints to manage special needs"
-
name: 'Staff Management'
description: "\nManage staff members and their student assignments"
-
name: 'Student Conversations'
description: "\nMessage box between students and uni staff. Students can start conversations with university staff.\nAssigned managers/advisers for the student and admins can participate and reply."
-
name: 'Student Language'
description: "\nManage the languages spoken by the student."
-
name: 'Student Management'
description: "\nEndpoint to manage the students"
-
name: 'Study destination'
description: "\nManage study destination"
-
name: Universities
description: "\nManage universities information, including descriptions, tuition, and gallery images."
-
name: 'University Applications Management'
description: ''
-
name: 'User Management'
description: "\nEndpoints to manage users (admin only for most operations)."
-
name: 'User Notification Management'
description: "\nEndpoints to handle the authenticated user's notifications.\n\nFlexible endpoint that supports filtering by status, limiting results, and pagination."
-
name: 'Users roles'
description: "\nManage users and student roles."
components:
securitySchemes:
default:
type: http
scheme: bearer
description: 'You can retrieve a user token by calling the login endpoint or register endpoint for new users.'
security:
-
default: []
paths:
/api/v1/ai:
get:
summary: "Get the current authenticated user's academic information."
operationId: getTheCurrentAuthenticatedUsersAcademicInformation
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 1
current_status:
id: 2
name: Undergraduate
high_schools_attended: []
properties:
id:
type: integer
example: 1
current_status:
type: object
properties:
id:
type: integer
example: 2
name:
type: string
example: Undergraduate
high_schools_attended:
type: array
example: []
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Academic information not found'
academic_information: null
properties:
message:
type: string
example: 'Academic information not found'
academic_information:
type: string
example: null
tags:
- 'Academic Information Management'
post:
summary: 'Create a new academic information entry.'
operationId: createANewAcademicInformationEntry
description: ''
parameters: []
responses: { }
tags:
- 'Academic Information Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
current_status:
type: string
description: 'the id of the current status of the student.'
example: consequatur
nullable: false
user_id:
type: string
description: 'the id of the student this value is used to check and avoid creating redudant entries.'
example: consequatur
nullable: false
required:
- current_status
- user_id
'/api/v1/ai/{id}':
put:
summary: 'Update an academic information entry.'
operationId: updateAnAcademicInformationEntry
description: ''
parameters: []
responses: { }
tags:
- 'Academic Information Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
current_status:
type: string
description: 'the id of the current status of the student.'
example: consequatur
nullable: false
user_id:
type: string
description: 'the id of the student this value is used to check and avoid creating redudant entries.'
example: null
nullable: false
required:
- current_status
parameters:
-
in: path
name: id
description: 'The ID of the ai.'
example: 1
required: true
schema:
type: integer
/api/v1/admin/admin_notifications:
get:
summary: 'Display a listing of the resource.'
operationId: displayAListingOfTheResource
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.345036Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.345036Z'
tags:
- 'Admin Notification Management'
'/api/v1/admin/admin_notifications/{id}':
get:
summary: 'Display the specified resource.'
operationId: displayTheSpecifiedResource
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.348998Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.348998Z'
tags:
- 'Admin Notification Management'
parameters:
-
in: path
name: id
description: 'The ID of the admin notification.'
example: 1
required: true
schema:
type: integer
/api/v1/admin/admin_notifications/read-all:
post:
summary: ''
operationId: postApiV1AdminAdmin_notificationsReadAll
description: ''
parameters: []
responses: { }
tags:
- 'Admin Notification Management'
/api/v1/forgot_password:
post:
summary: 'Forgot Password (API Flow)'
operationId: forgotPasswordAPIFlow
description: 'Generates a 6-digit code and sends it via email.'
parameters: []
responses: { }
tags:
- 'Authentication Endpoints'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: "The user's email."
example: user@example.com
nullable: false
required:
- email
security: []
/api/v1/validate_reset_code:
post:
summary: 'Validate Reset Code'
operationId: validateResetCode
description: "Verifies if the 6-digit code is valid for the given email.\nUse this to allow the frontend to proceed to the \"New Password\" screen.\n* @bodyParam email string required. Example: user@example.com"
parameters: []
responses: { }
tags:
- 'Authentication Endpoints'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: 'Must be a valid email address. The email of an existing record in the users table.'
example: qkunze@example.com
nullable: false
code:
type: string
description: required.
example: '123456'
nullable: false
required:
- email
security: []
/api/v1/reset_password:
post:
summary: 'Reset Password'
operationId: resetPassword
description: "The final step: Update the password using the validated code.\n* @bodyParam email string required."
parameters: []
responses: { }
tags:
- 'Authentication Endpoints'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: 'Must be a valid email address. The email of an existing record in the users table.'
example: qkunze@example.com
nullable: false
code:
type: string
description: required.
example: consequatur
nullable: false
password:
type: string
description: required.
example: 'O[2UZ5ij-e/dl4m{o,'
nullable: false
password_confirmation:
type: string
description: required.
example: consequatur
nullable: false
required:
- email
security: []
/api/v1/register:
post:
summary: 'Register a new user'
operationId: registerANewUser
description: "This endpoint handles user registration. It accepts a name, email, and password,\ncreates a new user, and returns an authentication token."
parameters: []
responses: { }
tags:
- 'Authentication Endpoints'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'The name of the user. Must not be greater than 255 characters.'
example: 'John Doe'
nullable: false
email:
type: string
description: 'The email of the user. Must be a valid email address. Must not be greater than 255 characters.'
example: john@ollav.com
nullable: false
password:
type: string
description: 'The password for the user. Must be at least 8 characters.'
example: 'O[2UZ5ij-e/dl4m{o,'
nullable: false
required:
- name
- email
- password
security: []
/api/v1/login:
post:
summary: 'Login a new user'
operationId: loginANewUser
description: "This endpoint handles user signin process. It accepts an email and password,\nCheck the user, and returns an authentication token."
parameters: []
responses: { }
tags:
- 'Authentication Endpoints'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: 'The email of the user. Must be a valid email address.'
example: john@ollav.com
nullable: false
password:
type: string
description: 'The password for the user.'
example: consequatur
nullable: false
required:
- email
- password
security: []
/api/v1/logout:
post:
summary: 'Logout the authenticated user'
operationId: logoutTheAuthenticatedUser
description: 'This endpoint handles user signing out.'
parameters: []
responses: { }
tags:
- 'Authentication Endpoints'
/api/v1/admin/staff:
post:
summary: 'Create a new staff member'
operationId: createANewStaffMember
description: "This endpoint handles staff account creation. It accepts a name, email, password, and role_id,\ncreates a new staff user, and sends a welcome email notification."
parameters: []
responses: { }
tags:
- 'Authentication Endpoints'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'The name of the staff member. Must not be greater than 255 characters.'
example: 'Jane Smith'
nullable: false
email:
type: string
description: 'The email of the staff member. Must be a valid email address. Must not be greater than 255 characters.'
example: jane@ollav.com
nullable: false
password:
type: string
description: 'The password for the staff member account. Must be at least 8 characters.'
example: 'O[2UZ5ij-e/dl4m{o,'
nullable: false
role_id:
type: integer
description: 'The role ID for the staff member. The id of an existing record in the roles table.'
example: 2
nullable: false
required:
- name
- email
- password
- role_id
security: []
get:
summary: 'Show the list of all staff members in the system'
operationId: showTheListOfAllStaffMembersInTheSystem
description: "Get all staff members (non-student users) available in the system.\nResults are paginated with 10 staff members per page."
parameters: []
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": [...], "links": {...}, "meta": {"total": 5, "per_page": 10, "current_page": 1}}'
tags:
- 'Staff Management'
/api/v1/bundles:
get:
summary: 'List available bundles'
operationId: listAvailableBundles
description: ''
parameters: []
responses:
200:
description: 'List of active bundles with emerging and global prices'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Bundles Management'
'/api/v1/bundles/{bundleId}':
get:
summary: 'Get bundle details'
operationId: getBundleDetails
description: ''
parameters: []
responses:
200:
description: 'Detailed bundle information'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Bundles Management'
parameters:
-
in: path
name: bundleId
description: ''
example: consequatur
required: true
schema:
type: string
/api/v1/admin/bundles:
post:
summary: 'Create new bundle (admin only)'
operationId: createNewBundleadminOnly
description: ''
parameters: []
responses: { }
tags:
- 'Bundles Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Bundle name'
example: 'Premium Pack'
nullable: false
application_number:
type: integer
description: 'Number of applications included'
example: 10
nullable: false
emerging_price:
type: number
description: 'Price for emerging markets'
example: 50.0
nullable: false
global_price:
type: number
description: 'Price for global markets'
example: 100.0
nullable: false
currency_id:
type: integer
description: 'Currency ID'
example: 1
nullable: false
whats_included:
type: array
description: 'Array of features included'
example:
- '5 job applications'
- 'Priority support'
items:
type: string
ideal_for:
type: string
description: 'Who this bundle is ideal for'
example: 'Active job seekers'
nullable: false
is_active:
type: boolean
description: 'Active status'
example: true
nullable: false
required:
- name
- application_number
- emerging_price
- global_price
- currency_id
'/api/v1/admin/bundles/{bundleId}':
get:
summary: 'Get bundle details'
operationId: getBundleDetails
description: ''
parameters: []
responses:
200:
description: 'Detailed bundle information'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Bundles Management'
patch:
summary: 'Update bundle (admin only)'
operationId: updateBundleadminOnly
description: ''
parameters: []
responses: { }
tags:
- 'Bundles Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must not be greater than 255 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: false
application_number:
type: integer
description: 'Must be at least 1.'
example: 2
nullable: false
emerging_price:
type: number
description: 'Price for emerging markets'
example: 45.0
nullable: false
global_price:
type: number
description: 'Price for global markets'
example: 95.0
nullable: false
currency_id:
type: integer
description: 'Currency ID'
example: 2
nullable: false
whats_included:
type: array
description: 'Array of features included'
example:
- consequatur
items:
type: string
ideal_for:
type: string
description: 'Must not be greater than 255 characters.'
example: mqeopfuudtdsufvyvddqa
nullable: true
is_active:
type: boolean
description: ''
example: true
nullable: false
delete:
summary: 'Delete bundle (admin only)'
operationId: deleteBundleadminOnly
description: ''
parameters: []
responses: { }
tags:
- 'Bundles Management'
parameters:
-
in: path
name: bundleId
description: ''
example: consequatur
required: true
schema:
type: string
/api/v1/contacts:
post:
summary: 'Store a newly created contact.'
operationId: storeANewlyCreatedContact
description: ''
parameters: []
responses: { }
tags:
- 'Contact Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: 'the email of the contact. Must be a valid email address.'
example: qkunze@example.com
nullable: false
phone:
type: string
description: 'the phone number of the contact.'
example: consequatur
nullable: false
address:
type: string
description: 'the address of the contact. Must be at least 6 characters.'
example: mqeopfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjury
nullable: false
personal_information_id:
type: integer
description: 'the id of the personal information associated with the contact.'
example: 17
nullable: false
required:
- phone
- personal_information_id
'/api/v1/contacts/{id}':
put:
summary: 'Update the specified contact.'
operationId: updateTheSpecifiedContact
description: ''
parameters: []
responses: { }
tags:
- 'Contact Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
email:
type: string
description: 'the email of the contact. Must be a valid email address.'
example: qkunze@example.com
nullable: false
phone:
type: string
description: 'the phone number of the contact.'
example: null
nullable: false
address:
type: string
description: 'the address of the contact. Must be at least 6 characters.'
example: opfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjuryvoj
nullable: false
delete:
summary: 'Delete the specified contact.'
operationId: deleteTheSpecifiedContact
description: 'this must be done by the owning user or an admin.'
parameters: []
responses: { }
tags:
- 'Contact Management'
parameters:
-
in: path
name: id
description: 'The ID of the contact.'
example: 1
required: true
schema:
type: integer
/api/v1/countries:
get:
summary: 'List countries with filters'
operationId: listCountriesWithFilters
description: "Returns paginated list of countries with their associated region information.\nSupports filtering by region name, market tier, and search queries."
parameters:
-
in: query
name: region
description: 'Filter by region name. One of: Africa, Asia, Europe, USA, UK, UAE.'
example: Africa
required: false
schema:
type: string
description: 'Filter by region name. One of: Africa, Asia, Europe, USA, UK, UAE.'
example: Africa
nullable: false
-
in: query
name: tier
description: 'Filter by market tier. One of: emerging, global.'
example: emerging
required: false
schema:
type: string
description: 'Filter by market tier. One of: emerging, global.'
example: emerging
nullable: false
-
in: query
name: search
description: 'Search by country code or name (English/French).'
example: Burundi
required: false
schema:
type: string
description: 'Search by country code or name (English/French).'
example: Burundi
nullable: false
-
in: query
name: sort_by
description: 'Field to sort by. One of: code, name, created_at. Default: created_at.'
example: code
required: false
schema:
type: string
description: 'Field to sort by. One of: code, name, created_at. Default: created_at.'
example: code
nullable: false
-
in: query
name: sort_order
description: 'Sort direction. One of: asc, desc. Default: desc.'
example: asc
required: false
schema:
type: string
description: 'Sort direction. One of: asc, desc. Default: desc.'
example: asc
nullable: false
-
in: query
name: per_page
description: 'Items per page (1-100). Default: 15.'
example: 20
required: false
schema:
type: integer
description: 'Items per page (1-100). Default: 15.'
example: 20
nullable: false
responses:
200:
description: 'Paginated list of countries'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Countries Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
region:
type: string
description: ''
example: UK
nullable: true
enum:
- Africa
- Asia
- Europe
- USA
- UK
- UAE
tier:
type: string
description: ''
example: global
nullable: true
enum:
- emerging
- global
search:
type: string
description: 'Must be at least 2 characters. Must not be greater than 50 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: true
sort_by:
type: string
description: ''
example: code
nullable: true
enum:
- code
- name
- created_at
sort_order:
type: string
description: ''
example: desc
nullable: true
enum:
- asc
- desc
per_page:
type: integer
description: 'Must be at least 1. Must not be greater than 100.'
example: 1
nullable: true
'/api/v1/countries/{id}':
get:
summary: 'Get country details'
operationId: getCountryDetails
description: ''
parameters: []
responses:
200:
description: 'Country details with region'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Countries Management'
parameters:
-
in: path
name: id
description: 'The ID of the country.'
example: 002e58d3-68bd-4d41-80b0-eb9e97919daf
required: true
schema:
type: string
-
in: path
name: country
description: 'Optional parameter. uuid required The UUID of the country.'
required: true
schema:
type: integer
examples:
omitted:
summary: 'When the value is omitted'
value: ''
present:
summary: 'When the value is present'
value: 9
/api/v1/admin/countries:
post:
summary: 'Create new country'
operationId: createNewCountry
description: 'Creates a new country with localized names and associates it with a study destination region.'
parameters: []
responses:
201:
description: 'Country created successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Countries Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
code:
type: string
description: 'ISO country code (2 characters).'
example: BI
nullable: false
flag:
type: string
description: 'Flag emoji or image URL.'
example: 🇧🇮
nullable: false
dial_code:
type: string
description: 'International dialing code.'
example: '+257'
nullable: false
name:
type: object
description: 'Localized country names.'
example: []
nullable: false
properties:
en:
type: string
description: 'English name.'
example: Burundi
nullable: false
fr:
type: string
description: 'French name.'
example: Burundi
nullable: false
required:
- en
- fr
region_id:
type: uuid
description: 'The study destination region ID.'
example: 9b1e967a-706d-4912-9c31
nullable: false
required:
- code
- flag
- dial_code
- name
- region_id
'/api/v1/admin/countries/{id}':
put:
summary: 'Update country'
operationId: updateCountry
description: ''
parameters: []
responses:
200:
description: 'Country updated successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Countries Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
code:
type: string
description: 'optional ISO country code.'
example: BI
nullable: false
flag:
type: string
description: 'optional Flag emoji or URL.'
example: 🇧🇮
nullable: false
dial_code:
type: string
description: 'optional Dialing code.'
example: '+257'
nullable: false
name:
type: object
description: 'optional Localized names.'
example: []
nullable: false
properties:
en:
type: string
description: 'optional English name.'
example: Burundi
nullable: false
fr:
type: string
description: 'optional French name.'
example: Burundi
nullable: false
region_id:
type: uuid
description: 'optional Study destination region ID.'
example: 9b1e967a-706d-4912-9c31
nullable: false
delete:
summary: 'Delete country'
operationId: deleteCountry
description: ''
parameters: []
responses:
204:
description: 'Country deleted successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Countries Management'
parameters:
-
in: path
name: id
description: 'The ID of the country.'
example: 002e58d3-68bd-4d41-80b0-eb9e97919daf
required: true
schema:
type: string
-
in: path
name: country
description: 'Optional parameter. uuid required The UUID of the country.'
required: true
schema:
type: integer
examples:
omitted:
summary: 'When the value is omitted'
value: ''
present:
summary: 'When the value is present'
value: 9
'/api/v1/users/{user_id}/credits/deduct':
post:
summary: 'Deduct credits for application'
operationId: deductCreditsForApplication
description: ''
parameters: []
responses:
200:
description: 'Credits deducted successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Insufficient credits'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
quantity:
type: integer
description: 'Number of applications to deduct'
example: 1
nullable: false
preferred_bundle_id:
type: string
description: 'Specific bundle to use'
example: consequatur
nullable: false
price_type:
type: string
description: 'Prefer emerging or global price credits'
example: emerging
nullable: false
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
'/api/v1/users/{user_id}/credits/balance':
get:
summary: 'Get user credit balance'
operationId: getUserCreditBalance
description: ''
parameters: []
responses:
200:
description: 'Current credit balance with breakdown'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
'/api/v1/users/{user_id}/credits/history':
get:
summary: 'Get user credit history'
operationId: getUserCreditHistory
description: ''
parameters: []
responses:
200:
description: 'Credit transaction history'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
'/api/v1/users/{user_id}/transactions':
post:
summary: 'Record a transaction'
operationId: recordATransaction
description: 'Typically used when a user purchases credits or pays an application fee.'
parameters: []
responses:
200:
description: 'Transaction recorded successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
transaction_type:
type: string
description: 'Type of transaction'
example: credit_purchase
nullable: false
amount:
type: integer
description: 'Amount in credits or currency units'
example: 100
nullable: false
required:
- transaction_type
- amount
get:
summary: 'List user transaction history'
operationId: listUserTransactionHistory
description: 'Returns paginated list of all recorded transactions.'
parameters:
-
in: query
name: per_page
description: 'Number of items per page'
example: 20
required: false
schema:
type: integer
description: 'Number of items per page'
example: 20
nullable: false
responses:
200:
description: 'Paginated list of transactions'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
'/api/v1/users/{user_id}/transactions/{transactionId}':
get:
summary: 'Show a transaction'
operationId: showATransaction
description: ''
parameters: []
responses:
200:
description: 'Transaction details'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Transaction not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
-
in: path
name: transactionId
description: ''
example: consequatur
required: true
schema:
type: string
'/api/v1/admin/universities/{university_id}/credits/add':
post:
summary: 'Add credits to university'
operationId: addCreditsToUniversity
description: ''
parameters: []
responses:
200:
description: 'Credits added successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
amount:
type: integer
description: 'Amount of credits to add (minimum 1)'
example: 100
nullable: false
description:
type: string
description: 'Optional description'
example: 'Bulk purchase'
nullable: false
required:
- amount
parameters:
-
in: path
name: university_id
description: 'The ID of the university.'
example: 00ce85a9-6d2d-4be1-a0cd-274d7c063eac
required: true
schema:
type: string
'/api/v1/admin/universities/{university_id}/credits/deduct':
post:
summary: 'Deduct credits from university'
operationId: deductCreditsFromUniversity
description: ''
parameters: []
responses:
200:
description: 'Credits deducted successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Insufficient credits'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'No credit record found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
amount:
type: integer
description: 'Amount of credits to deduct'
example: 10
nullable: false
description:
type: string
description: 'Optional description'
example: 'Application processed'
nullable: false
required:
- amount
parameters:
-
in: path
name: university_id
description: 'The ID of the university.'
example: 00ce85a9-6d2d-4be1-a0cd-274d7c063eac
required: true
schema:
type: string
'/api/v1/admin/universities/{university_id}/credits/balance':
get:
summary: 'Get university credit balance'
operationId: getUniversityCreditBalance
description: ''
parameters: []
responses:
200:
description: 'Current credit balance'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
parameters:
-
in: path
name: university_id
description: 'The ID of the university.'
example: 00ce85a9-6d2d-4be1-a0cd-274d7c063eac
required: true
schema:
type: string
'/api/v1/admin/majors/{major_id}/credits/add':
post:
summary: 'Add credits to major'
operationId: addCreditsToMajor
description: ''
parameters: []
responses:
200:
description: 'Credits added successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
amount:
type: integer
description: 'Amount of credits to add (minimum 1)'
example: 100
nullable: false
description:
type: string
description: 'Optional description'
example: 'Bulk purchase'
nullable: false
required:
- amount
parameters:
-
in: path
name: major_id
description: 'The ID of the major.'
example: 6
required: true
schema:
type: integer
'/api/v1/admin/majors/{major_id}/credits/deduct':
post:
summary: 'Deduct credits from major'
operationId: deductCreditsFromMajor
description: ''
parameters: []
responses:
200:
description: 'Credits deducted successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Insufficient credits'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'No credit record found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
amount:
type: integer
description: 'Amount of credits to deduct'
example: 10
nullable: false
description:
type: string
description: 'Optional description'
example: 'Application processed'
nullable: false
required:
- amount
parameters:
-
in: path
name: major_id
description: 'The ID of the major.'
example: 6
required: true
schema:
type: integer
'/api/v1/admin/majors/{major_id}/credits/balance':
get:
summary: 'Get major credit balance'
operationId: getMajorCreditBalance
description: ''
parameters: []
responses:
200:
description: 'Current credit balance'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Management'
parameters:
-
in: path
name: major_id
description: 'The ID of the major.'
example: 6
required: true
schema:
type: integer
/api/v1/credit_purchases:
post:
summary: 'Submit bundle purchase with payment proof'
operationId: submitBundlePurchaseWithPaymentProof
description: "Allows a user to buy a credit bundle via offline/manual payment (e.g., mobile money, bank transfer).\nUser selects a bundle and uploads a screenshot/receipt as proof.\nThe request becomes pending until an admin approves or rejects it."
parameters: []
responses:
201:
description: 'Proof submitted successfully. Awaiting admin approval.'
content:
application/json:
schema:
type: object
nullable: true
422:
description: 'Validation errors (invalid bundle, wrong file type, etc.)'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Purchases & Bundle Payments'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
bundle_id:
type: string
description: 'UUID of the selected bundle'
example: 019b1de6-8c48-7396-9209-11c69db9e53b
nullable: false
amount:
type: number
description: 'Must be at least 0.01.'
example: 56
nullable: false
proof_image:
type: string
format: binary
description: 'Image proof of payment (screenshot/receipt). Allowed: jpeg, png, jpg. Max 5MB.'
nullable: false
required:
- bundle_id
- amount
- proof_image
/api/v1/credit_purchases/pending:
get:
summary: 'List pending credit purchases (admin only)'
operationId: listPendingCreditPurchasesadminOnly
description: 'Returns paginated list of purchases awaiting approval, with user and bundle details.'
parameters: []
responses:
200:
description: 'Paginated list of pending purchases'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Purchases & Bundle Payments'
'/api/v1/credit_purchases/{purchaseId}/approve':
post:
summary: 'Approve credit purchase (admin only)'
operationId: approveCreditPurchaseadminOnly
description: "On approval:\n- Credits from the bundle are added to the user's balance\n- A transaction record is created (type: credit_purchase)\n- Purchase status changes to approved"
parameters: []
responses:
200:
description: 'Purchase approved and credits added successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Purchase already processed'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Purchase not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Purchases & Bundle Payments'
parameters:
-
in: path
name: purchaseId
description: ''
example: consequatur
required: true
schema:
type: string
'/api/v1/credit_purchases/{purchaseId}/reject':
post:
summary: 'Reject credit purchase (admin only)'
operationId: rejectCreditPurchaseadminOnly
description: 'Rejects the purchase and records an admin note (reason).'
parameters: []
responses:
200:
description: 'Purchase rejected successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Purchase already processed'
content:
application/json:
schema:
type: object
nullable: true
422:
description: 'Missing or invalid admin_note'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Purchases & Bundle Payments'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
admin_note:
type: string
description: 'Reason for rejection (visible to user)'
example: 'Payment not received or proof unclear'
nullable: false
required:
- admin_note
parameters:
-
in: path
name: purchaseId
description: ''
example: consequatur
required: true
schema:
type: string
/api/v1/admin/credit-purchases/pending:
get:
summary: 'List pending credit purchases (admin only)'
operationId: listPendingCreditPurchasesadminOnly
description: 'Returns paginated list of purchases awaiting approval, with user and bundle details.'
parameters: []
responses:
200:
description: 'Paginated list of pending purchases'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Purchases & Bundle Payments'
'/api/v1/admin/credit-purchases/{purchaseId}/approve':
post:
summary: 'Approve credit purchase (admin only)'
operationId: approveCreditPurchaseadminOnly
description: "On approval:\n- Credits from the bundle are added to the user's balance\n- A transaction record is created (type: credit_purchase)\n- Purchase status changes to approved"
parameters: []
responses:
200:
description: 'Purchase approved and credits added successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Purchase already processed'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Purchase not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Purchases & Bundle Payments'
parameters:
-
in: path
name: purchaseId
description: ''
example: consequatur
required: true
schema:
type: string
'/api/v1/admin/credit-purchases/{purchaseId}/reject':
post:
summary: 'Reject credit purchase (admin only)'
operationId: rejectCreditPurchaseadminOnly
description: 'Rejects the purchase and records an admin note (reason).'
parameters: []
responses:
200:
description: 'Purchase rejected successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Purchase already processed'
content:
application/json:
schema:
type: object
nullable: true
422:
description: 'Missing or invalid admin_note'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Credit Purchases & Bundle Payments'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
admin_note:
type: string
description: 'Reason for rejection (visible to user)'
example: 'Payment not received or proof unclear'
nullable: false
required:
- admin_note
parameters:
-
in: path
name: purchaseId
description: ''
example: consequatur
required: true
schema:
type: string
/api/v1/currencies:
get:
summary: 'Display a listing of all the currencies.'
operationId: displayAListingOfAllTheCurrencies
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
success: true
data:
-
id: 0a2264e3-b4f0-4ebd-8d07-fcfb99ed1e42
code: GBP
symbol: £
-
id: 110ac3b9-d073-4e71-ac19-1c20a21ead1a
code: EUR
symbol: €
-
id: 134c1321-cfcb-4186-8732-0ed04440b595
code: AUD
symbol: A$
-
id: 6edd3a74-de48-4273-b307-3354cf7774b4
code: CAD
symbol: CA$
-
id: 861f0e7e-40fe-4b3f-9771-d3d4676ae8a6
code: USD
symbol: $
timestamp: '2026-04-18T17:44:13.812495Z'
properties:
success:
type: boolean
example: true
data:
type: array
example:
-
id: 0a2264e3-b4f0-4ebd-8d07-fcfb99ed1e42
code: GBP
symbol: £
-
id: 110ac3b9-d073-4e71-ac19-1c20a21ead1a
code: EUR
symbol: €
-
id: 134c1321-cfcb-4186-8732-0ed04440b595
code: AUD
symbol: A$
-
id: 6edd3a74-de48-4273-b307-3354cf7774b4
code: CAD
symbol: CA$
-
id: 861f0e7e-40fe-4b3f-9771-d3d4676ae8a6
code: USD
symbol: $
items:
type: object
properties:
id:
type: string
example: 0a2264e3-b4f0-4ebd-8d07-fcfb99ed1e42
code:
type: string
example: GBP
symbol:
type: string
example: £
timestamp:
type: string
example: '2026-04-18T17:44:13.812495Z'
tags:
- Currency
post:
summary: 'Store a newly created currency.'
operationId: storeANewlyCreatedCurrency
description: ''
parameters: []
responses: { }
tags:
- Currency
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
code:
type: string
description: 'Must not be greater than 10 characters.'
example: vmqeopfuu
nullable: false
symbol:
type: string
description: 'Must not be greater than 10 characters.'
example: dtdsufvyv
nullable: true
required:
- code
'/api/v1/currencies/{id}':
get:
summary: 'Display the specified currency.'
operationId: displayTheSpecifiedCurrency
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
success: true
data:
id: 0a2264e3-b4f0-4ebd-8d07-fcfb99ed1e42
code: GBP
symbol: £
created_at: '2026-01-30T15:31:20.000000Z'
updated_at: null
timestamp: '2026-04-18T17:44:13.819596Z'
properties:
success:
type: boolean
example: true
data:
type: object
properties:
id:
type: string
example: 0a2264e3-b4f0-4ebd-8d07-fcfb99ed1e42
code:
type: string
example: GBP
symbol:
type: string
example: £
created_at:
type: string
example: '2026-01-30T15:31:20.000000Z'
updated_at:
type: string
example: null
timestamp:
type: string
example: '2026-04-18T17:44:13.819596Z'
tags:
- Currency
put:
summary: 'Update the specified currency.'
operationId: updateTheSpecifiedCurrency
description: ''
parameters: []
responses: { }
tags:
- Currency
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
code:
type: string
description: ''
example: null
nullable: false
symbol:
type: string
description: 'Must not be greater than 10 characters.'
example: vmqeopfuu
nullable: false
delete:
summary: 'Remove the specified resource from storage.'
operationId: removeTheSpecifiedResourceFromStorage
description: ''
parameters: []
responses: { }
tags:
- Currency
parameters:
-
in: path
name: id
description: 'The ID of the currency.'
example: 0a2264e3-b4f0-4ebd-8d07-fcfb99ed1e42
required: true
schema:
type: string
/api/v1/admin/current_status:
get:
summary: 'List of all the current status a student can have.'
operationId: listOfAllTheCurrentStatusAStudentCanHave
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.325009Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.325009Z'
tags:
- 'Current Status Management'
post:
summary: 'Store a newly created current status.'
operationId: storeANewlyCreatedCurrentStatus
description: ''
parameters: []
responses: { }
tags:
- 'Current Status Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'the name of the current status.'
example: consequatur
nullable: false
required:
- name
'/api/v1/admin/current_status/{id}':
get:
summary: 'Show one current status.'
operationId: showOneCurrentStatus
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.330470Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.330470Z'
tags:
- 'Current Status Management'
put:
summary: 'Update the specified resource in storage.'
operationId: updateTheSpecifiedResourceInStorage
description: ''
parameters: []
responses: { }
tags:
- 'Current Status Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: ''
example: consequatur
nullable: false
delete:
summary: 'Remove the specified resource from storage.'
operationId: removeTheSpecifiedResourceFromStorage
description: ''
parameters: []
responses: { }
tags:
- 'Current Status Management'
parameters:
-
in: path
name: id
description: 'The ID of the current status.'
example: 1
required: true
schema:
type: integer
/api/v1/document_locker:
get:
summary: 'Show the content of the document locker'
operationId: showTheContentOfTheDocumentLocker
description: 'The document locker that is associated with authenticated user also the user has to be as student.'
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.972366Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.972366Z'
tags:
- 'Document Locker'
'/api/v1/document_locker/{id}':
get:
summary: 'Show one specific document locker by user id'
operationId: showOneSpecificDocumentLockerByUserId
description: 'can be used by the user owner of the token or an admin to fetch the document locker of a specific user'
parameters:
-
in: query
name: id
description: 'The id of the user whose document locker you want to fetch.'
example: '1'
required: true
schema:
type: string
description: 'The id of the user whose document locker you want to fetch.'
example: '1'
nullable: false
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.976135Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.976135Z'
tags:
- 'Document Locker'
parameters:
-
in: path
name: id
description: 'The ID of the document locker.'
example: consequatur
required: true
schema:
type: string
/api/v1/exam_results:
get:
summary: "List all exam results for the authenticated user's locker."
operationId: listAllExamResultsForTheAuthenticatedUsersLocker
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.980129Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.980129Z'
tags:
- 'Document Locker'
'/api/v1/exam_results/{id}':
get:
summary: "Show a specific exam result in the authenticated user's locker."
operationId: showASpecificExamResultInTheAuthenticatedUsersLocker
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.984827Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.984827Z'
tags:
- 'Document Locker'
delete:
summary: "Delete a specific exam result from the authenticated user's locker."
operationId: deleteASpecificExamResultFromTheAuthenticatedUsersLocker
description: ''
parameters: []
responses: { }
tags:
- 'Document Locker'
parameters:
-
in: path
name: id
description: 'The ID of the exam result.'
example: consequatur
required: true
schema:
type: string
/api/v1/other_documents:
get:
summary: "List all other documents for the authenticated user's locker."
operationId: listAllOtherDocumentsForTheAuthenticatedUsersLocker
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.991169Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.991169Z'
tags:
- 'Document Locker'
'/api/v1/other_documents/{id}':
get:
summary: "Show a specific other document in the authenticated user's locker."
operationId: showASpecificOtherDocumentInTheAuthenticatedUsersLocker
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.995208Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.995208Z'
tags:
- 'Document Locker'
delete:
summary: "Delete a specific other document from the authenticated user's locker."
operationId: deleteASpecificOtherDocumentFromTheAuthenticatedUsersLocker
description: ''
parameters: []
responses: { }
tags:
- 'Document Locker'
parameters:
-
in: path
name: id
description: 'The ID of the other document.'
example: consequatur
required: true
schema:
type: string
/api/v1/document_locker/setup:
post:
summary: 'Setup or init a new document locker for the authenticated student'
operationId: setupOrInitANewDocumentLockerForTheAuthenticatedStudent
description: ''
parameters: []
responses: { }
tags:
- 'Document Locker'
/api/v1/document_locker/upload:
post:
summary: "Endpoint to upload documents to the authenticated student's locker."
operationId: endpointToUploadDocumentsToTheAuthenticatedStudentsLocker
description: "Supported upload types (send as `upload_type`):\n- transcript: requires `description` (string) and `transcript_file` (file: pdf, txt, docx)\n- exam_results: requires `exam_name` (string) and either `exam_result_file` (file) OR `exam_result_text` (string). Optional `score` and `description`.\n- recommendation_letter: requires `description` and `recommendation_letter_file` (file)\n- personal_statement: requires `description` and either `personal_statement_file` (file) or `personal_statement_text` (string)\n- resume: requires `resume_file` (file)\n- passport: requires `passport_file` (file)\n- id_document: requires `id_document_file` (file: pdf, jpg, png), `document_type` (string: passport, national_id, drivers_license, etc.), and `date_of_birth` (date: Y-m-d format)\n- others: requires `document_name`, optional `description`, and `other_document_file` (file: pdf, jpg, png)\n\nFiles are validated with extensions and size limits (see controller validation rules)."
parameters: []
responses: { }
tags:
- 'Document Locker'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
upload_type:
type: string
description: 'The type of upload.'
example: transcript
nullable: false
required:
- upload_type
/api/v1/document_locker/replace:
post:
summary: 'Endpoint to replace a document already stored in the locker.'
operationId: endpointToReplaceADocumentAlreadyStoredInTheLocker
description: "Use `upload_type` and `doc_id` to select which document to replace, then send the same file param that\nwould be used for an upload of that type. Supported `upload_type` values and file params are the same as\nfor the upload endpoint (transcript, exam_results, recommendation_letter, personal_statement, resume, passport, others)."
parameters: []
responses: { }
tags:
- 'Document Locker'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
upload_type:
type: string
description: 'The type of upload.'
example: transcript
nullable: false
doc_id:
type: integer
description: 'The id of the document to replace.'
example: 17
nullable: false
required:
- upload_type
- doc_id
/api/v1/profile/grade:
post:
summary: "Submit or update the student's overall academic grade."
operationId: submitOrUpdateTheStudentsOverallAcademicGrade
description: "This endpoint allows a student to manually enter their academic average (e.g., moyenne générale from Diplôme d'État\nfor Burundian users, GPA for international users, etc.). The submitted grade is stored in the Document Locker\nsection and requires admin verification before it can be used in university/major recommendation matching."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Grade submitted successfully'
grade:
id: 45
user_id: 123
grading_system: percentage_100
grade_value: 76.5
description: "Moyenne générale - Diplôme d'État 2024"
status_id: 2
verified_at: null
created_at: '2025-12-15T10:30:00.000000Z'
updated_at: '2025-12-15T10:30:00.000000Z'
properties:
message:
type: string
example: 'Grade submitted successfully'
grade:
type: object
properties:
id:
type: integer
example: 45
user_id:
type: integer
example: 123
grading_system:
type: string
example: percentage_100
grade_value:
type: number
example: 76.5
description:
type: string
example: "Moyenne générale - Diplôme d'État 2024"
status_id:
type: integer
example: 2
verified_at:
type: string
example: null
created_at:
type: string
example: '2025-12-15T10:30:00.000000Z'
updated_at:
type: string
example: '2025-12-15T10:30:00.000000Z'
403:
description: ''
content:
application/json:
schema:
type: object
example:
error: 'Not a student'
properties:
error:
type: string
example: 'Not a student'
422:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'The given data was invalid.'
errors:
grading_system:
- 'The selected grading system is invalid.'
grade_value:
- 'The grade value must be a number.'
properties:
message:
type: string
example: 'The given data was invalid.'
errors:
type: object
properties:
grading_system:
type: array
example:
- 'The selected grading system is invalid.'
items:
type: string
grade_value:
type: array
example:
- 'The grade value must be a number.'
items:
type: string
tags:
- 'Document Locker'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
grading_system:
type: string
description: "The grading system used. Must be one of:\n - \"percentage_100\" (default for Burundi users, e.g., 76.5)\n - \"gpa_4_0\" (US/international GPA, e.g., 3.2)\n - \"out_of_20\" (French-system score, e.g., 15.4)\n - \"other\" (for any non-standard format)"
example: percentage_100
nullable: false
grade_value:
type: number
description: "The numeric value of the grade (without symbols or units).\n Examples:\n - 76.5 for percentage_100\n - 3.2 for gpa_4_0\n - 15.4 for out_of_20"
example: 11613.31890586
nullable: false
description:
type: string
description: "nullable\n Optional description of the grade."
example: '"Moyenne générale - Diplôme d''État 2024"'
nullable: true
required:
- grading_system
- grade_value
/api/v1/admin/upload_validation:
post:
summary: 'Admin verification of a specific uploaded document'
operationId: adminVerificationOfASpecificUploadedDocument
description: ''
parameters: []
responses: { }
tags:
- 'Document Locker'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
document_locker_id:
type: integer
description: ''
example: 17
nullable: false
document_type:
type: string
description: 'One of: transcript, recommendation_letter, personal_statement, resume, passport, exam_results, id_document, others'
example: consequatur
nullable: false
document_id:
type: integer
description: ''
example: 17
nullable: false
verdict:
type: string
description: 'Must be: approved or rejected'
example: consequatur
nullable: false
feedback:
type: string
description: 'nullable Required if verdict is rejected'
example: consequatur
nullable: true
required:
- document_locker_id
- document_type
- document_id
- verdict
/api/v1/fetch-file:
get:
summary: 'File Proxy Route'
operationId: fileProxyRoute
description: '* @query url string The full public URL of the file (e.g., https://.../storage/uploads/file.docx)'
parameters: []
responses:
400:
description: ''
content:
application/json:
schema:
type: object
example:
error: 'No URL provided'
properties:
error:
type: string
example: 'No URL provided'
tags:
- Endpoints
/api/v1/onboarding_data:
get:
summary: 'Retrieve onboarding data grouped by major category'
operationId: retrieveOnboardingDataGroupedByMajorCategory
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
success: true
data:
message: 'Onboarding data retrieved successfully'
categories:
-
id: 1
name: 'Agriculture, Food & Natural Resources'
slug: agriculture-food-natural-resources
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 2
name: 'Architecture & Construction'
slug: architecture-construction
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 3
name: 'Arts, Design & Media'
slug: arts-design-media
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 4
name: 'Business, Management & Finance'
slug: business-management-finance
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 5
name: 'Computer Science & Information Technology'
slug: computer-science-information-technology
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 6
name: 'Education & Training'
slug: education-training
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 7
name: 'Engineering & Manufacturing'
slug: engineering-manufacturing
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 8
name: 'Health Sciences & Medicine'
slug: health-sciences-medicine
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 9
name: 'Humanities & Culture'
slug: humanities-culture
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 10
name: 'Law, Public Safety & Security'
slug: law-public-safety-security
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 11
name: 'Social Sciences & Psychology'
slug: social-sciences-psychology
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 12
name: 'Natural Sciences & Mathematics'
slug: natural-sciences-mathematics
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 13
name: 'Tourism, Hospitality & Culinary Arts'
slug: tourism-hospitality-culinary-arts
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 14
name: 'Communication & Journalism'
slug: communication-journalism
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
timestamp: '2026-04-18T17:44:13.836548Z'
properties:
success:
type: boolean
example: true
data:
type: object
properties:
message:
type: string
example: 'Onboarding data retrieved successfully'
categories:
type: array
example:
-
id: 1
name: 'Agriculture, Food & Natural Resources'
slug: agriculture-food-natural-resources
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 2
name: 'Architecture & Construction'
slug: architecture-construction
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 3
name: 'Arts, Design & Media'
slug: arts-design-media
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 4
name: 'Business, Management & Finance'
slug: business-management-finance
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 5
name: 'Computer Science & Information Technology'
slug: computer-science-information-technology
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 6
name: 'Education & Training'
slug: education-training
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 7
name: 'Engineering & Manufacturing'
slug: engineering-manufacturing
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 8
name: 'Health Sciences & Medicine'
slug: health-sciences-medicine
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 9
name: 'Humanities & Culture'
slug: humanities-culture
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 10
name: 'Law, Public Safety & Security'
slug: law-public-safety-security
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 11
name: 'Social Sciences & Psychology'
slug: social-sciences-psychology
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 12
name: 'Natural Sciences & Mathematics'
slug: natural-sciences-mathematics
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 13
name: 'Tourism, Hospitality & Culinary Arts'
slug: tourism-hospitality-culinary-arts
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
-
id: 14
name: 'Communication & Journalism'
slug: communication-journalism
icon: null
created_at: '2026-04-14T07:44:08.000000Z'
updated_at: '2026-04-14T07:44:08.000000Z'
items:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: 'Agriculture, Food & Natural Resources'
slug:
type: string
example: agriculture-food-natural-resources
icon:
type: string
example: null
created_at:
type: string
example: '2026-04-14T07:44:08.000000Z'
updated_at:
type: string
example: '2026-04-14T07:44:08.000000Z'
timestamp:
type: string
example: '2026-04-18T17:44:13.836548Z'
tags:
- Endpoints
/api/v1/onboarding:
post:
summary: 'Complete the student onboarding process.'
operationId: completeTheStudentOnboardingProcess
description: ''
parameters: []
responses: { }
tags:
- Endpoints
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
date_of_birth:
type: string
description: 'Must be a valid date. Must be a valid date in the format Y-m-d. Must be a date before today.'
example: '2020-08-14'
nullable: false
gender:
type: string
description: ''
example: Male
nullable: false
enum:
- Male
- Female
- Other
nationality:
type: string
description: 'Must not be greater than 100 characters.'
example: mqeopfuudtdsufvyvddqa
nullable: false
profile_photo:
type: string
format: binary
description: 'Must be a file. Must not be greater than 5120 kilobytes.'
nullable: true
email:
type: string
description: 'Must be a valid email address. Must not be greater than 255 characters.'
example: eloisa.harber@example.com
nullable: false
phone:
type: string
description: 'Must not be greater than 20 characters.'
example: fqcoynlazghdtqtqx
nullable: false
address:
type: string
description: 'Must not be greater than 500 characters.'
example: bajwbpilpmufinllwloau
nullable: false
languages:
type: array
description: 'Must be at least 2 characters. Must not be greater than 50 characters.'
example:
- ydlsmsjuryvojcybzvrby
items:
type: string
id_document_file:
type: string
format: binary
description: 'Must be a file. Must not be greater than 5120 kilobytes.'
nullable: false
id_document_type:
type: string
description: 'Must be at least 3 characters. Must not be greater than 100 characters.'
example: ickznkygloigmkwxphlva
nullable: false
study_destination_ids:
type: array
description: 'The id of an existing record in the study_destinations table.'
example:
- 17
items:
type: integer
intended_field_of_study:
type: string
description: 'Must not be greater than 255 characters.'
example: mqeopfuudtdsufvyvddqa
nullable: false
min_budget:
type: number
description: 'Must be at least 0.'
example: 45
nullable: false
max_budget:
type: number
description: 'Must be at least 0.'
example: 46
nullable: false
currency:
type: string
description: ''
example: CHF
nullable: false
enum:
- USD
- EUR
- GBP
- CAD
- AUD
- CHF
- CNY
- INR
- JPY
- KES
- UGX
- RWF
- BIF
scholarship_interest:
type: boolean
description: ''
example: true
nullable: false
special_needs:
type: array
description: 'Must not be greater than 255 characters.'
example:
- iihfqcoynlazghdtqtqxb
items:
type: string
category_ids:
type: array
description: 'The id of an existing record in the major_categories table.'
example:
- consequatur
items:
type: string
required:
- date_of_birth
- gender
- nationality
- email
- phone
- address
- id_document_file
- id_document_type
- intended_field_of_study
- min_budget
- max_budget
- currency
- scholarship_interest
- category_ids
/api/v1/document-packages:
post:
summary: 'Request a new document package (queued generation)'
operationId: requestANewDocumentPackagequeuedGeneration
description: ''
parameters: []
responses: { }
tags:
- Endpoints
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
user_id:
type: integer
description: 'The id of an existing record in the users table.'
example: 17
nullable: false
required:
- user_id
get:
summary: 'List all document packages'
operationId: listAllDocumentPackages
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.240239Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.240239Z'
tags:
- Endpoints
'/api/v1/document-packages/{package_id}':
get:
summary: 'Get single package details'
operationId: getSinglePackageDetails
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.244495Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.244495Z'
tags:
- Endpoints
delete:
summary: 'Delete a package'
operationId: deleteAPackage
description: ''
parameters: []
responses: { }
tags:
- Endpoints
parameters:
-
in: path
name: package_id
description: 'The ID of the package.'
example: consequatur
required: true
schema:
type: string
'/api/v1/document-packages/{package_id}/download':
get:
summary: 'Download a completed package - serves file through API with auth check'
operationId: downloadACompletedPackageServesFileThroughAPIWithAuthCheck
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.248434Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.248434Z'
tags:
- Endpoints
parameters:
-
in: path
name: package_id
description: 'The ID of the package.'
example: consequatur
required: true
schema:
type: string
'/api/v1/document-packages/{package_id}/retry':
post:
summary: 'Retry a failed package'
operationId: retryAFailedPackage
description: ''
parameters: []
responses: { }
tags:
- Endpoints
parameters:
-
in: path
name: package_id
description: 'The ID of the package.'
example: consequatur
required: true
schema:
type: string
/api/v1/admin/totals:
get:
summary: 'basic metrics about totals'
operationId: basicMetricsAboutTotals
description: "Total applications\nTotal students\nTotal universities\nTotal majors"
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.295340Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.295340Z'
tags:
- Endpoints
/api/v1/admin/metrics:
get:
summary: 'Return precomputed dashboard metrics or a timeseries over a date range.'
operationId: returnPrecomputedDashboardMetricsOrATimeseriesOverADateRange
description: "Query params:\n- start YYYY-MM-DD (optional)\n- end YYYY-MM-DD (optional)"
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.395589Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.395589Z'
tags:
- Endpoints
/api/v1/admin/metrics/recompute:
post:
summary: ''
operationId: postApiV1AdminMetricsRecompute
description: ''
parameters: []
responses: { }
tags:
- Endpoints
/api/v1/admin/metrics/universities:
get:
summary: 'Return aggregated per-university metrics over a date range (or single day if start=end)'
operationId: returnAggregatedPerUniversityMetricsOverADateRangeorSingleDayIfStartend
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.399954Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.399954Z'
tags:
- Endpoints
/api/v1/admin/metrics/events:
get:
summary: 'List metric events with optional filters'
operationId: listMetricEventsWithOptionalFilters
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.403243Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.403243Z'
tags:
- Endpoints
/api/v1/admin/metrics/backfill:
post:
summary: 'Backfill metrics for a date range (admin-triggered)'
operationId: backfillMetricsForADateRangeadminTriggered
description: ''
parameters: []
responses: { }
tags:
- Endpoints
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
start:
type: string
description: 'Must be a valid date.'
example: '2026-04-18T17:44:14'
nullable: false
end:
type: string
description: 'Must be a valid date. Must be a date after or equal to start.'
example: '2107-05-18'
nullable: false
required:
- start
- end
/api/v1/haha:
get:
summary: ''
operationId: getApiV1Haha
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
status: success
updated_count: 0
remaining_orphans: []
message: 'Migration parfaite : 100% des données sont catégorisées.'
properties:
status:
type: string
example: success
updated_count:
type: integer
example: 0
remaining_orphans:
type: array
example: []
message:
type: string
example: 'Migration parfaite : 100% des données sont catégorisées.'
tags:
- Endpoints
/api/v1/highschools:
post:
summary: 'Store a newly created highSchool.'
operationId: storeANewlyCreatedHighSchool
description: ''
parameters: []
responses: { }
tags:
- 'HighSchool Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must not be greater than 255 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: false
country:
type: string
description: 'Must not be greater than 100 characters.'
example: amniihfqcoynlazghdtqt
nullable: false
years:
type: integer
description: 'the amount of years spent there. Must be at least 1. Must not be greater than 30.'
example: 16
nullable: false
since:
type: string
description: 'the year he/she began studying at the highSchool,.'
example: null
nullable: false
until:
type: string
description: 'the last year.'
example: null
nullable: false
academic_information_id:
type: string
description: 'The id of an existing record in the academic_information table.'
example: consequatur
nullable: false
required:
- name
- country
- years
- academic_information_id
'/api/v1/highschools/{id}':
put:
summary: 'Update the specified highSchool.'
operationId: updateTheSpecifiedHighSchool
description: ''
parameters: []
responses: { }
tags:
- 'HighSchool Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must not be greater than 255 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: false
country:
type: string
description: 'Must not be greater than 100 characters.'
example: amniihfqcoynlazghdtqt
nullable: false
years:
type: integer
description: 'Must be at least 1. Must not be greater than 30.'
example: 16
nullable: false
since:
type: string
description: ''
example: null
nullable: false
until:
type: string
description: ''
example: null
nullable: false
academic_information_id:
type: string
description: 'The id of an existing record in the academic_information table.'
example: null
nullable: false
delete:
summary: 'Remove the specified highSchool.'
operationId: removeTheSpecifiedHighSchool
description: ''
parameters: []
responses: { }
tags:
- 'HighSchool Management'
parameters:
-
in: path
name: id
description: 'The ID of the highschool.'
example: 1
required: true
schema:
type: integer
/api/v1/majors:
get:
summary: 'Get all majors'
operationId: getAllMajors
description: "Returns a paginated list of majors.
\nYou can optionally filter by degree, university or category."
parameters:
-
in: query
name: degree
description: 'Filter by degree level (Bachelor, Master, PHD).'
example: Bachelor
required: false
schema:
type: string
description: 'Filter by degree level (Bachelor, Master, PHD).'
example: Bachelor
nullable: false
-
in: query
name: university_id
description: 'Filter by university id.'
example: 42
required: false
schema:
type: integer
description: 'Filter by university id.'
example: 42
nullable: false
-
in: query
name: major_category_id
description: 'Filter by major category id.'
example: 5
required: false
schema:
type: integer
description: 'Filter by major category id.'
example: 5
nullable: false
-
in: query
name: page
description: 'Page number for pagination.'
example: 1
required: false
schema:
type: integer
description: 'Page number for pagination.'
example: 1
nullable: false
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.208365Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.208365Z'
tags:
- 'Majors Management'
'/api/v1/majors/{id}':
get:
summary: 'Get a single major'
operationId: getASingleMajor
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 1
name: 'Computer Science'
description: 'Software engineering & algorithms'
degree: Bachelor
major_category_id: 5
is_applications_open: true
minimum_gpa_grades: '3.0 / 75%'
budget_range: $8k–12k/year
is_scholarship_available: true
university:
id: 42
name: 'Example University'
category:
id: 5
name: 'Computer Science & IT'
properties:
id:
type: integer
example: 1
name:
type: string
example: 'Computer Science'
description:
type: string
example: 'Software engineering & algorithms'
degree:
type: string
example: Bachelor
major_category_id:
type: integer
example: 5
is_applications_open:
type: boolean
example: true
minimum_gpa_grades:
type: string
example: '3.0 / 75%'
budget_range:
type: string
example: $8k–12k/year
is_scholarship_available:
type: boolean
example: true
university:
type: object
properties:
id:
type: integer
example: 42
name:
type: string
example: 'Example University'
category:
type: object
properties:
id:
type: integer
example: 5
name:
type: string
example: 'Computer Science & IT'
tags:
- 'Majors Management'
parameters:
-
in: path
name: id
description: 'The ID of the major.'
example: 6
required: true
schema:
type: integer
/api/v1/admin/majors:
post:
summary: 'Create a new major'
operationId: createANewMajor
description: ''
parameters: []
responses:
201:
description: ''
content:
application/json:
schema:
type: object
example:
id: 11
name: 'Data Science'
description: 'Machine learning & big-data analytics'
degree: Master
major_category_id: 5
is_applications_open: true
minimum_gpa_grades: '3.5 / 80%'
budget_range: $10k–15k/year
is_scholarship_available: false
university:
id: 5
name: 'Tech University'
properties:
id:
type: integer
example: 11
name:
type: string
example: 'Data Science'
description:
type: string
example: 'Machine learning & big-data analytics'
degree:
type: string
example: Master
major_category_id:
type: integer
example: 5
is_applications_open:
type: boolean
example: true
minimum_gpa_grades:
type: string
example: '3.5 / 80%'
budget_range:
type: string
example: $10k–15k/year
is_scholarship_available:
type: boolean
example: false
university:
type: object
properties:
id:
type: integer
example: 5
name:
type: string
example: 'Tech University'
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: Forbidden
properties:
message:
type: string
example: Forbidden
tags:
- 'Majors Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must not be greater than 255 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: false
description:
type: string
description: ''
example: 'Dolores dolorum amet iste laborum eius est dolor.'
nullable: true
degree:
type: string
description: ''
example: Master
nullable: false
enum:
- Bachelor
- Master
- PHD
major_category_id:
type: string
description: 'The id of an existing record in the major_categories table.'
example: consequatur
nullable: false
is_applications_open:
type: boolean
description: ''
example: false
nullable: true
minimum_gpa_grades:
type: string
description: 'Must not be greater than 50 characters.'
example: mqeopfuudtdsufvyvddqa
nullable: true
budget_range:
type: string
description: 'Must not be greater than 100 characters.'
example: mniihfqcoynlazghdtqtq
nullable: true
is_scholarship_available:
type: boolean
description: ''
example: true
nullable: true
university_id:
type: string
description: 'The id of an existing record in the universities table.'
example: consequatur
nullable: false
application_deadline:
type: string
description: 'Must be a valid date.'
example: '2026-04-18T17:44:14'
nullable: true
required:
- name
- degree
- major_category_id
- university_id
'/api/v1/admin/majors/{major_id}':
put:
summary: 'Update an existing major'
operationId: updateAnExistingMajor
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 7
name: 'Mechanical Engineering'
description: 'Updated description'
degree: Bachelor
major_category_id: 7
is_applications_open: false
minimum_gpa_grades: '3.2 / 78%'
budget_range: $9k–13k/year
is_scholarship_available: true
university:
id: 3
name: 'State University'
properties:
id:
type: integer
example: 7
name:
type: string
example: 'Mechanical Engineering'
description:
type: string
example: 'Updated description'
degree:
type: string
example: Bachelor
major_category_id:
type: integer
example: 7
is_applications_open:
type: boolean
example: false
minimum_gpa_grades:
type: string
example: '3.2 / 78%'
budget_range:
type: string
example: $9k–13k/year
is_scholarship_available:
type: boolean
example: true
university:
type: object
properties:
id:
type: integer
example: 3
name:
type: string
example: 'State University'
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: Forbidden
properties:
message:
type: string
example: Forbidden
tags:
- 'Majors Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must not be greater than 255 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: false
description:
type: string
description: ''
example: null
nullable: false
degree:
type: string
description: ''
example: Bachelor
nullable: false
enum:
- Bachelor
- Master
- PHD
major_category_id:
type: string
description: 'The id of an existing record in the major_categories table.'
example: null
nullable: false
is_applications_open:
type: boolean
description: ''
example: false
nullable: false
minimum_gpa_grades:
type: string
description: 'Must not be greater than 50 characters.'
example: amniihfqcoynlazghdtqt
nullable: false
budget_range:
type: string
description: 'Must not be greater than 100 characters.'
example: qxbajwbpilpmufinllwlo
nullable: false
is_scholarship_available:
type: boolean
description: ''
example: false
nullable: false
university_id:
type: string
description: 'The id of an existing record in the universities table.'
example: null
nullable: false
delete:
summary: 'Delete a major'
operationId: deleteAMajor
description: ''
parameters: []
responses:
204:
description: ''
content:
application/json:
schema:
type: object
example: { }
properties: { }
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: Forbidden
properties:
message:
type: string
example: Forbidden
tags:
- 'Majors Management'
parameters:
-
in: path
name: major_id
description: 'The ID of the major.'
example: 6
required: true
schema:
type: integer
/api/v1/admin/majorCategories:
post:
summary: 'Store a newly created major category'
operationId: storeANewlyCreatedMajorCategory
description: ''
parameters: []
responses: { }
tags:
- 'Majors Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must not be greater than 255 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: false
required:
- name
get:
summary: 'Get a list of all major categories'
operationId: getAListOfAllMajorCategories
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.517820Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.517820Z'
tags:
- 'Majors Management'
'/api/v1/admin/majorCategories/{majorCategory_id}':
put:
summary: 'Update the name and slug of a major category'
operationId: updateTheNameAndSlugOfAMajorCategory
description: ''
parameters: []
responses: { }
tags:
- 'Majors Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: ''
example: null
nullable: false
get:
summary: 'Get majors for a specific category'
operationId: getMajorsForASpecificCategory
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.521814Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.521814Z'
tags:
- 'Majors Management'
parameters:
-
in: path
name: majorCategory_id
description: 'The ID of the majorCategory.'
example: 1
required: true
schema:
type: integer
/api/v1/my_suggestions:
get:
summary: 'List of all matching suggestions for a user'
operationId: listOfAllMatchingSuggestionsForAUser
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.223703Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.223703Z'
tags:
- 'Matching Suggestions'
'/api/v1/my_suggestions/{id}':
get:
summary: 'Display one matching suggestion'
operationId: displayOneMatchingSuggestion
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.227000Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.227000Z'
tags:
- 'Matching Suggestions'
parameters:
-
in: path
name: id
description: 'The ID of the my suggestion.'
example: consequatur
required: true
schema:
type: string
/api/v1/admin/matchingSuggestions:
post:
summary: 'Store a new matching suggestion'
operationId: storeANewMatchingSuggestion
description: ''
parameters: []
responses: { }
tags:
- 'Matching Suggestions'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
suggested_user_id:
type: integer
description: 'The id of an existing record in the users table.'
example: 17
nullable: false
match_percentage:
type: number
description: 'Must be at least 0. Must not be greater than 100.'
example: 13
nullable: false
reason:
type: string
description: 'Must not be greater than 255 characters.'
example: qeopfuudtdsufvyvddqam
nullable: true
major_id:
type: integer
description: 'The id of an existing record in the majors table.'
example: 17
nullable: false
required:
- suggested_user_id
- match_percentage
- major_id
'/api/v1/admin/matchingSuggestions/{id}':
put:
summary: 'Update one matching suggestion.'
operationId: updateOneMatchingSuggestion
description: ''
parameters: []
responses: { }
tags:
- 'Matching Suggestions'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
suggested_user_id:
type: integer
description: 'The id of an existing record in the users table.'
example: 17
nullable: false
match_percentage:
type: number
description: 'Must be at least 0. Must not be greater than 100.'
example: 13
nullable: false
reason:
type: string
description: 'Must not be greater than 255 characters.'
example: qeopfuudtdsufvyvddqam
nullable: true
major_id:
type: integer
description: 'The id of an existing record in the majors table.'
example: 17
nullable: false
required:
- suggested_user_id
- match_percentage
- major_id
delete:
summary: 'Delete one matching suggestion.'
operationId: deleteOneMatchingSuggestion
description: ''
parameters: []
responses: { }
tags:
- 'Matching Suggestions'
parameters:
-
in: path
name: id
description: 'The ID of the matchingSuggestion.'
example: consequatur
required: true
schema:
type: string
/api/v1/user:
get:
summary: 'Get the user by the token'
operationId: getTheUserByTheToken
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.736075Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.736075Z'
tags:
- Miscellaneous
/api/v1/health:
get:
summary: 'Check if the api is online'
operationId: checkIfTheApiIsOnline
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
status: OK
properties:
status:
type: string
example: OK
tags:
- Miscellaneous
security: []
/api/v1/payment_proofs:
get:
summary: 'List payment proofs'
operationId: listPaymentProofs
description: ''
parameters:
-
in: query
name: status
description: 'Filter by status (pending, approved, rejected)'
example: pending
required: false
schema:
type: string
description: 'Filter by status (pending, approved, rejected)'
example: pending
nullable: false
-
in: query
name: per_page
description: 'Items per page'
example: 15
required: false
schema:
type: integer
description: 'Items per page'
example: 15
nullable: false
responses:
200:
description: 'List of payment proofs retrieved successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Payment Management'
post:
summary: 'Create payment proof'
operationId: createPaymentProof
description: ''
parameters: []
responses:
201:
description: 'Payment proof created successfully'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Unauthorized - can only create proof for own payments'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Payment not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Payment Management'
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
image:
type: string
format: binary
description: 'Payment proof image (jpg, png, pdf)'
nullable: false
receipt_number:
type: string
description: 'Receipt number'
example: REC-2024-001
nullable: false
payer_name:
type: string
description: 'Name of the payer'
example: 'John Doe'
nullable: false
amount:
type: numeric
description: 'Payment amount'
example: 150.0
nullable: false
payment_date:
type: date
description: 'Date of payment (Y-m-d)'
example: '2024-01-15'
nullable: false
payment_method:
type: string
description: 'Payment method used'
example: bank_transfer
nullable: false
payment_id:
type: string
description: "Payment ID (must be user's own payment)"
example: 550e8400-e29b-41d4-a716-446655440000
nullable: false
required:
- image
- receipt_number
- payer_name
- amount
- payment_date
- payment_method
- payment_id
'/api/v1/payment_proofs/{id}':
get:
summary: 'Get payment proof details'
operationId: getPaymentProofDetails
description: ''
parameters: []
responses:
200:
description: 'Payment proof retrieved successfully'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Unauthorized to view this payment proof'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Payment proof not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Payment Management'
put:
summary: 'Update payment proof'
operationId: updatePaymentProof
description: ''
parameters: []
responses:
200:
description: 'Payment proof updated successfully'
content:
application/json:
schema:
type: object
nullable: true
403:
description: Unauthorized
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Payment proof not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Payment Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: 'Status (pending, approved, rejected)'
example: approved
nullable: false
admin_comment:
type: string
description: 'Admin comment on the payment proof'
example: 'Payment verified successfully'
nullable: false
parameters:
-
in: path
name: id
description: 'The ID of the payment proof.'
example: consequatur
required: true
schema:
type: string
'/api/v1/payment_proofs/{paymentProofId}/verify':
post:
summary: 'Admin verify payment proof'
operationId: adminVerifyPaymentProof
description: "On approval: Verifies proof file, auto-detects price type from payment amount,\napproves proof, approves payment, approves credit purchase, adds credits, records transaction.\nOn rejection: Requires comment explaining why, rejects proof/payment/credit purchase, records rejection."
parameters: []
responses:
200:
description: 'Payment proof processed successfully'
content:
application/json:
schema:
type: object
nullable: true
400:
description: 'Invalid action or missing required fields'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Admin access required'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Payment proof not found'
content:
application/json:
schema:
type: object
nullable: true
422:
description: 'Payment proof file verification failed'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Payment Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
action:
type: string
description: 'Verification action: approve or reject'
example: approve
nullable: false
admin_comment:
type: string
description: 'Required rejection reason when rejecting, optional note when approving'
example: 'Payment proof unclear'
nullable: false
required:
- action
parameters:
-
in: path
name: paymentProofId
description: ''
example: consequatur
required: true
schema:
type: string
/api/v1/payments:
get:
summary: 'List payments'
operationId: listPayments
description: ''
parameters:
-
in: query
name: status
description: 'Filter by status (pending, paid, failed, cancelled, refunded)'
example: paid
required: false
schema:
type: string
description: 'Filter by status (pending, paid, failed, cancelled, refunded)'
example: paid
nullable: false
-
in: query
name: provider
description: 'Filter by payment provider'
example: stripe
required: false
schema:
type: string
description: 'Filter by payment provider'
example: stripe
nullable: false
-
in: query
name: page
description: 'Page number'
example: 1
required: false
schema:
type: integer
description: 'Page number'
example: 1
nullable: false
-
in: query
name: per_page
description: 'Items per page'
example: 15
required: false
schema:
type: integer
description: 'Items per page'
example: 15
nullable: false
responses:
200:
description: 'List of payments retrieved successfully'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Payment Management'
'/api/v1/payments/{paymentId}':
get:
summary: 'Get payment details'
operationId: getPaymentDetails
description: ''
parameters: []
responses:
200:
description: 'Payment retrieved successfully'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Unauthorized to view this payment'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'Payment not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'Payment Management'
parameters:
-
in: path
name: paymentId
description: ''
example: consequatur
required: true
schema:
type: string
/api/v1/pi:
get:
summary: "Get the current authenticated user's personal information."
operationId: getTheCurrentAuthenticatedUsersPersonalInformation
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 1
date_of_birth: '1995-06-01'
gender: Female
nationality: Kenya
user_id: 5
properties:
id:
type: integer
example: 1
date_of_birth:
type: string
example: '1995-06-01'
gender:
type: string
example: Female
nationality:
type: string
example: Kenya
user_id:
type: integer
example: 5
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Personal information not found'
personal_information: null
properties:
message:
type: string
example: 'Personal information not found'
personal_information:
type: string
example: null
tags:
- 'Personal Information'
'/api/v1/pi/{user}':
post:
summary: 'Store a newly created Personal info.'
operationId: storeANewlyCreatedPersonalInfo
description: ''
parameters: []
responses: { }
tags:
- 'Personal Information'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
date_of_birth:
type: string
description: 'Must be a valid date.'
example: '2026-04-18T17:44:13'
nullable: false
gender:
type: string
description: ''
example: consequatur
nullable: false
nationality:
type: string
description: 'Must be at least 4 characters.'
example: mqeopfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjury
nullable: false
user_id:
type: string
description: 'The id of an existing record in the users table.'
example: consequatur
nullable: false
required:
- date_of_birth
- gender
- nationality
- user_id
parameters:
-
in: path
name: user
description: ''
example: consequatur
required: true
schema:
type: string
'/api/v1/pi/{id}':
put:
summary: 'Update the specified personal information.'
operationId: updateTheSpecifiedPersonalInformation
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Personal Information updated successfully'
personal_information:
id: 1
date_of_birth: '1995-06-01'
gender: Female
nationality: Kenya
properties:
message:
type: string
example: 'Personal Information updated successfully'
personal_information:
type: object
properties:
id:
type: integer
example: 1
date_of_birth:
type: string
example: '1995-06-01'
gender:
type: string
example: Female
nationality:
type: string
example: Kenya
tags:
- 'Personal Information'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
date_of_birth:
type: string
description: 'Must be a valid date.'
example: '2026-04-18T17:44:13'
nullable: false
gender:
type: string
description: ''
example: consequatur
nullable: false
nationality:
type: string
description: 'Must be at least 4 characters.'
example: mqeopfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjury
nullable: false
parameters:
-
in: path
name: id
description: 'The ID of the pi.'
example: consequatur
required: true
schema:
type: string
/api/v1/preferences:
get:
summary: "Get the current authenticated user's preferences."
operationId: getTheCurrentAuthenticatedUsersPreferences
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 1
intended_field_of_study: 'Computer Science'
min_budget: 5000
max_budget: 20000
currency: USD
scholarship_interest: true
study_destinations: []
properties:
id:
type: integer
example: 1
intended_field_of_study:
type: string
example: 'Computer Science'
min_budget:
type: integer
example: 5000
max_budget:
type: integer
example: 20000
currency:
type: string
example: USD
scholarship_interest:
type: boolean
example: true
study_destinations:
type: array
example: []
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Preferences not found'
preferences: null
properties:
message:
type: string
example: 'Preferences not found'
preferences:
type: string
example: null
tags:
- 'Preferences and goals'
post:
summary: 'Store a newly created preference.'
operationId: storeANewlyCreatedPreference
description: ''
parameters: []
responses: { }
tags:
- 'Preferences and goals'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
intended_field_of_study:
type: string
description: ''
example: consequatur
nullable: false
min_budget:
type: number
description: 'the least/minimum amount of money he/she can afford.'
example: 11613.31890586
nullable: false
max_budget:
type: number
description: 'the maximum he/she can pay for school.'
example: 11613.31890586
nullable: false
currency:
type: string
description: 'Must be at least 3 characters.'
example: opfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjuryvoj
nullable: false
user_id:
type: string
description: ''
example: consequatur
nullable: false
scholarship_interest:
type: string
description: ''
example: null
nullable: false
study_destination_ids:
type: object
description: 'the school study destination are to be created by the admins, provide with an id or an array of ids.'
example: null
nullable: false
properties: { }
required:
- intended_field_of_study
- min_budget
- currency
- user_id
'/api/v1/preferences/{id}':
put:
summary: 'Update the specified preference.'
operationId: updateTheSpecifiedPreference
description: ''
parameters: []
responses: { }
tags:
- 'Preferences and goals'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
intended_field_of_study:
type: string
description: ''
example: null
nullable: false
min_budget:
type: number
description: ''
example: 11613.31890586
nullable: false
max_budget:
type: number
description: ''
example: 11613.31890586
nullable: false
currency:
type: string
description: 'Must be at least 3 characters.'
example: opfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjuryvoj
nullable: false
scholarship_interest:
type: string
description: ''
example: null
nullable: false
study_destination_ids:
type: object
description: ''
example: null
nullable: false
properties: { }
parameters:
-
in: path
name: id
description: 'The ID of the preference.'
example: consequatur
required: true
schema:
type: string
/api/v1/special_needs:
post:
summary: 'Store a newly created special need.'
operationId: storeANewlyCreatedSpecialNeed
description: ''
parameters: []
responses: { }
tags:
- 'Special Needs Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
needs:
type: object
description: 'the needs here is to be an array of needs. come up with a list of needs or let the user enter one Exemple: "needs": {"visa_support": "yes","disabilities": "eyes problems" }.'
example: []
nullable: false
properties: { }
required:
- needs
'/api/v1/special_needs/{id}':
put:
summary: 'Update the specified special needs of a student.'
operationId: updateTheSpecifiedSpecialNeedsOfAStudent
description: ''
parameters: []
responses: { }
tags:
- 'Special Needs Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
needs:
type: object
description: 'the same as the store endpoints, but here the array that you send will replace the old one, it''s doesn''t updating only one but the whole object of needs with the one you provide here Exemple: "needs": {"visa_support": "yes","disabilities": "eyes problems" }.'
example: null
nullable: false
properties: { }
delete:
summary: 'Remove the specified resource from storage.'
operationId: removeTheSpecifiedResourceFromStorage
description: ''
parameters: []
responses: { }
tags:
- 'Special Needs Management'
parameters:
-
in: path
name: id
description: 'The ID of the special need.'
example: 1
required: true
schema:
type: integer
/api/v1/my_staff:
get:
summary: 'Get the staff member assigned to a student'
operationId: getTheStaffMemberAssignedToAStudent
description: "Student can view their own staff member, admins can view any student's staff member.\nReturns paginated list of staff members assigned to a student."
parameters:
-
in: query
name: student_id
description: 'The ID of the student (if not provided, uses authenticated user)'
example: 17
required: false
schema:
type: integer
description: 'The ID of the student (if not provided, uses authenticated user)'
example: 17
nullable: false
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": [{"id": 5, "name": "Staff Member", "email": "staff@example.com", ...}], "links": {...}, "meta": {"total": 1, "per_page": 15}}'
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'You can only view your own assigned staff'
properties:
message:
type: string
example: 'You can only view your own assigned staff'
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Student not found'
properties:
message:
type: string
example: 'Student not found'
tags:
- 'Staff Management'
'/api/v1/admin/staff/{id}':
put:
summary: 'Update a staff member'
operationId: updateAStaffMember
description: 'Update user-related information for a staff member. Password and role cannot be updated through this endpoint.'
parameters: []
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": {...}, "message": "Staff member updated successfully"}'
tags:
- 'Staff Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must not be greater than 255 characters.'
example: vmqeopfuudtdsufvyvddq
nullable: true
email:
type: string
description: 'Must be a valid email address. Must not be greater than 255 characters.'
example: kunde.eloisa@example.com
nullable: true
profile_picture:
type: string
description: ''
example: consequatur
nullable: true
first_time_login:
type: boolean
description: ''
example: false
nullable: true
is_verified:
type: boolean
description: ''
example: false
nullable: true
parameters:
-
in: path
name: id
description: 'The ID of the staff.'
example: 1
required: true
schema:
type: integer
/api/v1/admin/staff/assign-student:
post:
summary: 'Assign a student to a staff member'
operationId: assignAStudentToAStaffMember
description: "Only admins can assign students to staff members.\nA staff member cannot be a student (role_id must not be 1)."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Student assigned to staff member successfully'
staff_id: 5
student_id: 3
properties:
message:
type: string
example: 'Student assigned to staff member successfully'
staff_id:
type: integer
example: 5
student_id:
type: integer
example: 3
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Only admins can assign students to staff'
properties:
message:
type: string
example: 'Only admins can assign students to staff'
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Staff or student not found'
properties:
message:
type: string
example: 'Staff or student not found'
422:
description: ''
content:
text/plain:
schema:
type: string
example: '{"message": "User is not a staff member" or "User is not a student" or "Student is already assigned to this staff"}'
tags:
- 'Staff Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
staff_id:
type: integer
description: 'The ID of the staff member user'
example: 17
nullable: false
student_id:
type: integer
description: 'The ID of the student user'
example: 17
nullable: false
required:
- staff_id
- student_id
/api/v1/admin/staff/remove-student:
post:
summary: 'Remove a student from a staff member'
operationId: removeAStudentFromAStaffMember
description: 'Only admins can remove student assignments from staff members.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Student removed from staff member successfully'
staff_id: 5
student_id: 3
properties:
message:
type: string
example: 'Student removed from staff member successfully'
staff_id:
type: integer
example: 5
student_id:
type: integer
example: 3
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Only admins can remove student assignments'
properties:
message:
type: string
example: 'Only admins can remove student assignments'
404:
description: ''
content:
text/plain:
schema:
type: string
example: '{"message": "Staff or student not found" or "Assignment not found"}'
tags:
- 'Staff Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
staff_id:
type: integer
description: 'The ID of the staff member user'
example: 17
nullable: false
student_id:
type: integer
description: 'The ID of the student user'
example: 17
nullable: false
required:
- staff_id
- student_id
/api/v1/admin/staff/list:
get:
summary: 'List all staff members'
operationId: listAllStaffMembers
description: "Get a paginated list of all staff members in the system.\nResults are paginated with 15 staff members per page."
parameters: []
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": [{"id": 5, "name": "Staff Member", "email": "staff@example.com", ...}], "links": {...}, "meta": {"total": 5, "per_page": 15}}'
tags:
- 'Staff Management'
/api/v1/admin/staff/with-counts:
get:
summary: 'Get all staff members with their assigned students count'
operationId: getAllStaffMembersWithTheirAssignedStudentsCount
description: 'Retrieve a paginated list of all staff members in the system with the count of students assigned to each.'
parameters: []
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": [{"user_id": 5, "name": "Staff Member", "email": "staff@example.com", "assigned_students_count": 3}, ...], "links": {...}, "meta": {"total": 5, "per_page": 10}}'
tags:
- 'Staff Management'
/api/v1/admin/staff/unassigned/count:
get:
summary: 'Get count of unassigned students'
operationId: getCountOfUnassignedStudents
description: 'Retrieve the total count of students who are not assigned to any staff member.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
unassigned_count: 5
properties:
data:
type: object
properties:
unassigned_count:
type: integer
example: 5
tags:
- 'Staff Management'
/api/v1/admin/staff/unassigned/students:
get:
summary: 'Get all unassigned students with count'
operationId: getAllUnassignedStudentsWithCount
description: 'Retrieve all students who are not assigned to any staff member, along with the total count.'
parameters: []
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": [...], "links": {...}, "meta": {...}}'
tags:
- 'Staff Management'
/api/v1/admin/staff/students:
get:
summary: 'Get all students assigned to a staff member'
operationId: getAllStudentsAssignedToAStaffMember
description: "Staff member can view their own students, admins can view any staff member's students.\nResults are paginated with 15 students per page."
parameters:
-
in: query
name: staff_id
description: 'The ID of the staff member (if not provided, uses authenticated staff user)'
example: 17
required: false
schema:
type: integer
description: 'The ID of the staff member (if not provided, uses authenticated staff user)'
example: 17
nullable: false
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": [{"id": 3, "name": "John Doe", "email": "john@example.com", ...}], "links": {...}, "meta": {"total": 1, "per_page": 15}}'
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'You can only view your own assigned students'
properties:
message:
type: string
example: 'You can only view your own assigned students'
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Staff member not found'
properties:
message:
type: string
example: 'Staff member not found'
tags:
- 'Staff Management'
'/api/v1/admin/staff/{staff_id}':
get:
summary: 'Get a staff member with the count of assigned students'
operationId: getAStaffMemberWithTheCountOfAssignedStudents
description: 'Retrieve a specific staff member and include the total number of students assigned to them.'
parameters: []
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": {..., "assigned_students_count": 3}}'
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Staff member not found'
properties:
message:
type: string
example: 'Staff member not found'
422:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'User is not a staff member'
properties:
message:
type: string
example: 'User is not a staff member'
tags:
- 'Staff Management'
parameters:
-
in: path
name: staff_id
description: 'The ID of the staff.'
example: 1
required: true
schema:
type: integer
/api/v1/admin/students/staff:
get:
summary: 'Get the staff member assigned to a student'
operationId: getTheStaffMemberAssignedToAStudent
description: "Student can view their own staff member, admins can view any student's staff member.\nReturns paginated list of staff members assigned to a student."
parameters:
-
in: query
name: student_id
description: 'The ID of the student (if not provided, uses authenticated user)'
example: 17
required: false
schema:
type: integer
description: 'The ID of the student (if not provided, uses authenticated user)'
example: 17
nullable: false
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{"data": [{"id": 5, "name": "Staff Member", "email": "staff@example.com", ...}], "links": {...}, "meta": {"total": 1, "per_page": 15}}'
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'You can only view your own assigned staff'
properties:
message:
type: string
example: 'You can only view your own assigned staff'
404:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Student not found'
properties:
message:
type: string
example: 'Student not found'
tags:
- 'Staff Management'
/api/v1/conversations:
get:
summary: 'List conversations.'
operationId: listConversations
description: "* Get a flat list of all conversations relevant to the user.\n- Admins: All conversations in the system.\n- Staff: Conversations they are part of OR involving their assigned students.\n- Students: Only conversations where they are a participant."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
success: true
data:
-
id: 1
subject: Inquiry
initiator:
id: 1
name: 'User Name'
profile_picture: null
role_id: 1
counter_part:
id: 2
name: 'Staff Name'
profile_picture: null
role_id: 2
last_message:
body: Hello!
sender_id: 1
read_at: null
created_at: '2026-03-27 12:00:00'
updated_at: '2026-03-27 12:00:00'
properties:
success:
type: boolean
example: true
data:
type: array
example:
-
id: 1
subject: Inquiry
initiator:
id: 1
name: 'User Name'
profile_picture: null
role_id: 1
counter_part:
id: 2
name: 'Staff Name'
profile_picture: null
role_id: 2
last_message:
body: Hello!
sender_id: 1
read_at: null
created_at: '2026-03-27 12:00:00'
updated_at: '2026-03-27 12:00:00'
items:
type: object
properties:
id:
type: integer
example: 1
subject:
type: string
example: Inquiry
initiator:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: 'User Name'
profile_picture:
type: string
example: null
role_id:
type: integer
example: 1
counter_part:
type: object
properties:
id:
type: integer
example: 2
name:
type: string
example: 'Staff Name'
profile_picture:
type: string
example: null
role_id:
type: integer
example: 2
last_message:
type: object
properties:
body:
type: string
example: Hello!
sender_id:
type: integer
example: 1
read_at:
type: string
example: null
created_at:
type: string
example: '2026-03-27 12:00:00'
updated_at:
type: string
example: '2026-03-27 12:00:00'
tags:
- 'Student Conversations'
post:
summary: 'Start/Get conversation.'
operationId: startGetConversation
description: "* Initiates a 1-on-1 thread. If a conversation already exists between the users, it appends the message to the existing thread.\n* @bodyParam counter_part_id int optional The ID of the user to talk to (Required for Admin/Staff). Example: 5"
parameters: []
responses:
201:
description: ''
content:
application/json:
schema:
type: object
example:
success: true
data:
message: 'Conversation created'
conversation:
id: 1
initiator_id: 1
counter_part_id: 5
subject: 'Academic Support'
properties:
success:
type: boolean
example: true
data:
type: object
properties:
message:
type: string
example: 'Conversation created'
conversation:
type: object
properties:
id:
type: integer
example: 1
initiator_id:
type: integer
example: 1
counter_part_id:
type: integer
example: 5
subject:
type: string
example: 'Academic Support'
403:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
message: 'You cannot start a conversation until a staff member is assigned to you'
properties:
success:
type: boolean
example: false
message:
type: string
example: 'You cannot start a conversation until a staff member is assigned to you'
tags:
- 'Student Conversations'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
subject:
type: string
description: 'optional The topic of conversation.'
example: 'Academic Support'
nullable: true
body:
type: string
description: 'The first message body.'
example: 'Hello, I need help with my application.'
nullable: false
required:
- body
'/api/v1/conversations/{id}':
get:
summary: 'View conversation.'
operationId: viewConversation
description: '* Retrieves a single conversation including the full flat list of messages.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
success: true
data:
conversation:
id: 1
initiator_id: 1
counter_part_id: 5
subject: 'Academic Support'
messages:
-
id: 10
body: Hello!
sender_id: 1
receiver_id: 5
created_at: ...
properties:
success:
type: boolean
example: true
data:
type: object
properties:
conversation:
type: object
properties:
id:
type: integer
example: 1
initiator_id:
type: integer
example: 1
counter_part_id:
type: integer
example: 5
subject:
type: string
example: 'Academic Support'
messages:
type: array
example:
-
id: 10
body: Hello!
sender_id: 1
receiver_id: 5
created_at: ...
items:
type: object
properties:
id:
type: integer
example: 10
body:
type: string
example: Hello!
sender_id:
type: integer
example: 1
receiver_id:
type: integer
example: 5
created_at:
type: string
example: ...
tags:
- 'Student Conversations'
parameters:
-
in: path
name: id
description: 'The ID of the conversation.'
example: 019d914e-f748-72b7-aa90-4d20ce91737a
required: true
schema:
type: string
-
in: path
name: conversation
description: 'The ID of the conversation.'
example: '1'
required: true
schema:
type: string
'/api/v1/conversations/{conversation_id}/messages':
post:
summary: 'Reply to conversation.'
operationId: replyToConversation
description: "* Adds a new message to an existing conversation and notifies the recipient.\n* @urlParam conversation required The ID of the conversation. Example: 1"
parameters: []
responses: { }
tags:
- 'Student Conversations'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
body:
type: string
description: 'The message body.'
example: "Noted, thank you.\n* @response 200 {\n\"success\": true,\n\"message\": \"Message posted\",\n\"data\": {\n\"id\": 11,\n\"body\": \"Noted, thank you.\",\n\"sender_id\": 5,\n\"receiver_id\": 1,\n\"sender\": {\"id\": 5, \"name\": \"Staff Name\"}\n}\n}"
nullable: false
required:
- body
parameters:
-
in: path
name: conversation_id
description: 'The ID of the conversation.'
example: 019d914e-f748-72b7-aa90-4d20ce91737a
required: true
schema:
type: string
/api/v1/languages:
post:
summary: 'Store a newly created language.'
operationId: storeANewlyCreatedLanguage
description: ''
parameters: []
responses: { }
tags:
- 'Student Language'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must be at least 4 characters.'
example: vmqeopfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjur
nullable: false
personal_information_id:
type: integer
description: ''
example: 17
nullable: false
required:
- name
- personal_information_id
'/api/v1/languages/{id}':
put:
summary: 'Update the student language.'
operationId: updateTheStudentLanguage
description: ''
parameters: []
responses: { }
tags:
- 'Student Language'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Must be at least 4 characters.'
example: vmqeopfuudtdsufvyvddqamniihfqcoynlazghdtqtqxbajwbpilpmufinllwloauydlsmsjur
nullable: false
delete:
summary: 'Remove the specified language.'
operationId: removeTheSpecifiedLanguage
description: ''
parameters: []
responses: { }
tags:
- 'Student Language'
parameters:
-
in: path
name: id
description: 'The ID of the language.'
example: 1
required: true
schema:
type: integer
'/api/v1/application_packet/{user_id}':
get:
summary: 'Endpoint to get the data for the packet used for his application'
operationId: endpointToGetTheDataForThePacketUsedForHisApplication
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:13.923430Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:13.923430Z'
tags:
- 'Student Management'
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
'/api/v1/students/{user_id}':
get:
summary: 'Endpoint to get the data for the student.'
operationId: endpointToGetTheDataForTheStudent
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.024219Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.024219Z'
tags:
- 'Student Management'
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
/api/v1/matches:
get:
summary: 'Get the matching for the authenticated student.'
operationId: getTheMatchingForTheAuthenticatedStudent
description: "Returns a ranked list of recommended majors for the authenticated student.\nEach item contains: type (\"major\"), score (0-100), a breakdown of contributing factors, and the related `major` and its `university` resource."
parameters:
-
in: query
name: limit
description: 'Optional. The maximum number of recommendations to return.'
example: 20
required: false
schema:
type: integer
description: 'Optional. The maximum number of recommendations to return.'
example: 20
nullable: false
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
type: major
major:
id: 1
name: 'Computer Science'
is_applications_open: true
university:
id: 5
name: 'Example University'
score: 87.2
breakdown:
field: 90
budget: 70
scholarship: 100
destination: 100
academic: 80
language: 100
category: 'Strong Match'
properties:
data:
type: array
example:
-
type: major
major:
id: 1
name: 'Computer Science'
is_applications_open: true
university:
id: 5
name: 'Example University'
score: 87.2
breakdown:
field: 90
budget: 70
scholarship: 100
destination: 100
academic: 80
language: 100
category: 'Strong Match'
items:
type: object
properties:
type:
type: string
example: major
major:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: 'Computer Science'
is_applications_open:
type: boolean
example: true
university:
type: object
properties:
id:
type: integer
example: 5
name:
type: string
example: 'Example University'
score:
type: number
example: 87.2
breakdown:
type: object
properties:
field:
type: integer
example: 90
budget:
type: integer
example: 70
scholarship:
type: integer
example: 100
destination:
type: integer
example: 100
academic:
type: integer
example: 80
language:
type: integer
example: 100
category:
type: string
example: 'Strong Match'
tags:
- 'Student Management'
/api/v1/admin/students:
get:
summary: 'Show the list of the students on the platform'
operationId: showTheListOfTheStudentsOnThePlatform
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.311387Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.311387Z'
tags:
- 'Student Management'
/api/v1/study_destinations:
get:
summary: 'Display a listing of all the study destinations.'
operationId: displayAListingOfAllTheStudyDestinations
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
success: true
data:
-
id: 209
region: Africa
regionTier: emerging
-
id: 210
region: Asia
regionTier: emerging
-
id: 211
region: Europe
regionTier: global
-
id: 212
region: USA
regionTier: global
-
id: 213
region: UK
regionTier: global
-
id: 214
region: UAE
regionTier: global
timestamp: '2026-04-18T17:44:13.794147Z'
properties:
success:
type: boolean
example: true
data:
type: array
example:
-
id: 209
region: Africa
regionTier: emerging
-
id: 210
region: Asia
regionTier: emerging
-
id: 211
region: Europe
regionTier: global
-
id: 212
region: USA
regionTier: global
-
id: 213
region: UK
regionTier: global
-
id: 214
region: UAE
regionTier: global
items:
type: object
properties:
id:
type: integer
example: 209
region:
type: string
example: Africa
regionTier:
type: string
example: emerging
timestamp:
type: string
example: '2026-04-18T17:44:13.794147Z'
tags:
- 'Study destination'
/api/v1/admin/study_destinations:
post:
summary: 'Store a newly created study destination.'
operationId: storeANewlyCreatedStudyDestination
description: ''
parameters: []
responses: { }
tags:
- 'Study destination'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
region:
type: string
description: ''
example: consequatur
nullable: false
region_tier:
type: string
description: ''
example: consequatur
nullable: false
required:
- region
- region_tier
'/api/v1/admin/study_destinations/{id}':
put:
summary: 'Update the specified study destination.'
operationId: updateTheSpecifiedStudyDestination
description: ''
parameters: []
responses: { }
tags:
- 'Study destination'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
region:
type: string
description: ''
example: null
nullable: false
region_tier:
type: string
description: ''
example: null
nullable: false
parameters:
-
in: path
name: id
description: 'The ID of the study destination.'
example: 209
required: true
schema:
type: integer
/api/v1/universities:
get:
summary: 'Display a listing of all universities.'
operationId: displayAListingOfAllUniversities
description: ''
parameters:
-
in: query
name: country
description: 'Filter by country name.'
example: Canada
required: false
schema:
type: string
description: 'Filter by country name.'
example: Canada
nullable: false
-
in: query
name: region
description: 'Filter by region.'
example: 'North America'
required: false
schema:
type: string
description: 'Filter by region.'
example: 'North America'
nullable: false
-
in: query
name: is_scholarship_available
description: 'Filter by scholarship availability (deprecated, use scholarship_availability).'
example: true
required: false
schema:
type: boolean
description: 'Filter by scholarship availability (deprecated, use scholarship_availability).'
example: true
nullable: false
-
in: query
name: scholarship_availability
description: 'Filter by specific scholarship level. One of: high, moderate, very high, low, very high (full), very high (need blind), very high (stipendium).'
example: 'very high'
required: false
schema:
type: string
description: 'Filter by specific scholarship level. One of: high, moderate, very high, low, very high (full), very high (need blind), very high (stipendium).'
example: 'very high'
nullable: false
-
in: query
name: affordability_tier
description: 'Filter by tier (e.g., Budget, Mid-Range).'
example: Mid-Range
required: false
schema:
type: string
description: 'Filter by tier (e.g., Budget, Mid-Range).'
example: Mid-Range
nullable: false
-
in: query
name: limit
description: 'Number of records per page/request.'
example: 15
required: false
schema:
type: integer
description: 'Number of records per page/request.'
example: 15
nullable: false
-
in: query
name: paginated
description: 'Whether to return paginated results. Default: false.'
example: true
required: false
schema:
type: boolean
description: 'Whether to return paginated results. Default: false.'
example: true
nullable: false
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.052427Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.052427Z'
tags:
- Universities
post:
summary: 'Store a newly created university.'
operationId: storeANewlyCreatedUniversity
description: ''
parameters: []
responses: { }
tags:
- Universities
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
name:
type: string
description: 'The name of the university.'
example: 'University of Toronto'
nullable: false
address:
type: string
description: 'Full physical address.'
example: "27 King's College Cir, Toronto, ON."
nullable: false
logo:
type: string
format: binary
description: 'nullable University logo image (max 2MB).'
nullable: true
country:
type: string
description: 'Country name.'
example: Canada
nullable: false
admission_rate:
type: number
description: 'Admission percentage (0-100).'
example: 43.5
nullable: false
is_scholarship_available:
type: boolean
description: 'nullable Indicates if scholarships available (deprecated).'
example: true
nullable: true
scholarship_availability:
type: string
description: 'Scholarship availability level. Must be one of: high, moderate, very high, low, very high (full), very high (need blind), very high (stipendium).'
example: 'very high'
nullable: false
study_destination_id:
type: uuid
description: 'The ID of the study destination.'
example: 9b1e967a-706d-4912-9c31
nullable: false
contact:
type: object
description: 'Contact information.'
example: []
nullable: false
properties:
email:
type: array
description: 'Array of email addresses.'
example:
- qkunze@example.com
items:
type: string
phone:
type: array
description: 'Array of phone numbers.'
example:
- consequatur
items:
type: string
website:
type: string
description: 'nullable Website URL.'
example: consequatur
nullable: true
required:
- email
- phone
university_description:
type: object
description: 'Detailed description and campus info.'
example: []
nullable: false
properties:
description:
type: string
description: 'nullable General description.'
example: 'Dolores dolorum amet iste laborum eius est dolor.'
nullable: true
campus_size:
type: string
description: 'Campus size.'
example: Large
nullable: false
student_life:
type: string
description: 'Student life description.'
example: consequatur
nullable: false
city_type:
type: string
description: 'City type.'
example: Urban
nullable: false
climate:
type: string
description: 'Climate type.'
example: Temperate
nullable: false
required:
- campus_size
- student_life
- city_type
- climate
annual_tuition:
type: object
description: 'Tuition details.'
example: []
nullable: false
properties:
international:
type: number
description: 'International student fee.'
example: 11613.31890586
nullable: false
local:
type: number
description: 'Local student fee.'
example: 11613.31890586
nullable: false
year:
type: integer
description: 'Academic year.'
example: 2024
nullable: false
currency_id:
type: uuid
description: 'UUID of the currency.'
example: consequatur
nullable: false
required:
- international
- local
- year
- currency_id
gallery:
type: array
description: 'nullable Array of gallery images (max 2MB each).'
items:
type: string
format: binary
nullable: true
application_fee:
type: number
description: 'The application cost.'
example: 100.0
nullable: false
application_flat_price:
type: number
description: 'Total flat price for application.'
example: 500.0
nullable: false
admission_requirements:
type: string
description: 'nullable Admission requirements text.'
example: consequatur
nullable: true
application_link:
type: string
description: 'nullable URL to application portal.'
example: consequatur
nullable: true
monthly_living_cost:
type: string
description: 'Monthly living cost estimate.'
example: '$1,200-$1,500'
nullable: false
affordability_tier:
type: string
description: 'Affordability category.'
example: Mid-Range
nullable: false
required:
- name
- address
- country
- admission_rate
- scholarship_availability
- study_destination_id
- contact
- university_description
- annual_tuition
- application_fee
- application_flat_price
- monthly_living_cost
- affordability_tier
'/api/v1/universities/{university_id}':
get:
summary: 'Display the specified university.'
operationId: displayTheSpecifiedUniversity
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.072659Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.072659Z'
tags:
- Universities
parameters:
-
in: path
name: university_id
description: 'The ID of the university.'
example: 00ce85a9-6d2d-4be1-a0cd-274d7c063eac
required: true
schema:
type: string
-
in: path
name: university
description: 'Optional parameter. uuid required The UUID of the university.'
required: true
schema:
type: string
examples:
omitted:
summary: 'When the value is omitted'
value: ''
present:
summary: 'When the value is present'
value: 9b1e967a-706d-4912-9c31
'/api/v1/universities/{id}':
put:
summary: 'Update the specified university.'
operationId: updateTheSpecifiedUniversity
description: ''
parameters: []
responses: { }
tags:
- Universities
requestBody:
required: false
content:
multipart/form-data:
schema:
type: object
properties:
name:
type: string
description: 'optional The name of the university.'
example: 'University of Toronto Updated'
nullable: false
address:
type: string
description: 'optional Full physical address.'
example: consequatur
nullable: false
logo:
type: string
format: binary
description: 'optional New university logo image (max 2MB).'
nullable: true
country:
type: string
description: 'optional Country name.'
example: Canada
nullable: false
admission_rate:
type: number
description: 'optional Admission percentage (0-100).'
example: 45.0
nullable: false
is_scholarship_available:
type: boolean
description: 'optional Indicates if scholarships available.'
example: true
nullable: false
scholarship_availability:
type: string
description: 'optional Scholarship availability level. One of: high, moderate, very high, low, very high (full), very high (need blind), very high (stipendium).'
example: 'very high (full)'
nullable: false
study_destination_id:
type: uuid
description: 'optional The ID of the study destination.'
example: consequatur
nullable: false
contact:
type: object
description: 'optional Contact information.'
example: []
nullable: false
properties:
email:
type: array
description: 'optional Array of email addresses.'
example:
- qkunze@example.com
items:
type: string
phone:
type: array
description: 'optional Array of phone numbers.'
example:
- consequatur
items:
type: string
website:
type: string
description: 'optional Website URL.'
example: consequatur
nullable: true
university_description:
type: object
description: 'optional Detailed description updates.'
example: []
nullable: false
properties:
description:
type: string
description: 'optional General description.'
example: 'Dolores dolorum amet iste laborum eius est dolor.'
nullable: false
campus_size:
type: string
description: 'optional Campus size.'
example: Large
nullable: false
student_life:
type: string
description: 'optional Student life description.'
example: consequatur
nullable: false
city_type:
type: string
description: 'optional City type.'
example: Urban
nullable: false
climate:
type: string
description: 'optional Climate type.'
example: Temperate
nullable: false
annual_tuition:
type: object
description: 'optional Tuition details updates.'
example: []
nullable: false
properties:
international:
type: number
description: 'optional International student fee.'
example: 11613.31890586
nullable: false
local:
type: number
description: 'optional Local student fee.'
example: 11613.31890586
nullable: false
year:
type: integer
description: 'optional Academic year.'
example: 2024
nullable: false
currency_id:
type: uuid
description: 'optional UUID of the currency.'
example: consequatur
nullable: false
application_fee:
type: number
description: 'optional The application cost.'
example: 11613.31890586
nullable: false
application_flat_price:
type: number
description: 'optional Total flat price for application.'
example: 11613.31890586
nullable: false
admission_requirements:
type: string
description: 'optional Admission requirements text.'
example: consequatur
nullable: true
application_link:
type: string
description: 'optional URL to application portal.'
example: consequatur
nullable: true
monthly_living_cost:
type: string
description: 'optional Monthly living cost estimate.'
example: consequatur
nullable: false
affordability_tier:
type: string
description: 'optional Affordability category.'
example: consequatur
nullable: false
gallery:
type: array
description: 'optional New gallery images (replaces old ones).'
items:
type: string
format: binary
nullable: true
delete:
summary: 'Remove the specified university.'
operationId: removeTheSpecifiedUniversity
description: ''
parameters: []
responses: { }
tags:
- Universities
parameters:
-
in: path
name: id
description: 'The ID of the university.'
example: 00ce85a9-6d2d-4be1-a0cd-274d7c063eac
required: true
schema:
type: string
-
in: path
name: university
description: 'Optional parameter. uuid required The UUID of the university.'
required: true
schema:
type: string
examples:
omitted:
summary: 'When the value is omitted'
value: ''
present:
summary: 'When the value is present'
value: 9b1e967a-706d-4912-9c31
'/api/v1/universities/country/{country}':
get:
summary: 'Get universities by country.'
operationId: getUniversitiesByCountry
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.096173Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.096173Z'
tags:
- Universities
parameters:
-
in: path
name: country
description: 'The country name.'
example: Germany
required: true
schema:
type: string
/api/v1/universities/scholarships/available:
get:
summary: 'Get universities with scholarships available.'
operationId: getUniversitiesWithScholarshipsAvailable
description: "This endpoint filters for universities where scholarship_availability is NOT 'low'."
parameters:
-
in: query
name: level
description: 'Filter by specific scholarship level (high, moderate, very high, etc.).'
example: consequatur
required: false
schema:
type: string
description: 'Filter by specific scholarship level (high, moderate, very high, etc.).'
example: consequatur
nullable: false
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.100207Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.100207Z'
tags:
- Universities
/api/v1/admin/universities:
post:
summary: 'Store a newly created university.'
operationId: storeANewlyCreatedUniversity
description: ''
parameters: []
responses: { }
tags:
- Universities
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
properties:
name:
type: string
description: 'The name of the university.'
example: 'University of Toronto'
nullable: false
address:
type: string
description: 'Full physical address.'
example: "27 King's College Cir, Toronto, ON."
nullable: false
logo:
type: string
format: binary
description: 'nullable University logo image (max 2MB).'
nullable: true
country:
type: string
description: 'Country name.'
example: Canada
nullable: false
admission_rate:
type: number
description: 'Admission percentage (0-100).'
example: 43.5
nullable: false
is_scholarship_available:
type: boolean
description: 'nullable Indicates if scholarships available (deprecated).'
example: true
nullable: true
scholarship_availability:
type: string
description: 'Scholarship availability level. Must be one of: high, moderate, very high, low, very high (full), very high (need blind), very high (stipendium).'
example: 'very high'
nullable: false
study_destination_id:
type: uuid
description: 'The ID of the study destination.'
example: 9b1e967a-706d-4912-9c31
nullable: false
contact:
type: object
description: 'Contact information.'
example: []
nullable: false
properties:
email:
type: array
description: 'Array of email addresses.'
example:
- qkunze@example.com
items:
type: string
phone:
type: array
description: 'Array of phone numbers.'
example:
- consequatur
items:
type: string
website:
type: string
description: 'nullable Website URL.'
example: consequatur
nullable: true
required:
- email
- phone
university_description:
type: object
description: 'Detailed description and campus info.'
example: []
nullable: false
properties:
description:
type: string
description: 'nullable General description.'
example: 'Dolores dolorum amet iste laborum eius est dolor.'
nullable: true
campus_size:
type: string
description: 'Campus size.'
example: Large
nullable: false
student_life:
type: string
description: 'Student life description.'
example: consequatur
nullable: false
city_type:
type: string
description: 'City type.'
example: Urban
nullable: false
climate:
type: string
description: 'Climate type.'
example: Temperate
nullable: false
required:
- campus_size
- student_life
- city_type
- climate
annual_tuition:
type: object
description: 'Tuition details.'
example: []
nullable: false
properties:
international:
type: number
description: 'International student fee.'
example: 11613.31890586
nullable: false
local:
type: number
description: 'Local student fee.'
example: 11613.31890586
nullable: false
year:
type: integer
description: 'Academic year.'
example: 2024
nullable: false
currency_id:
type: uuid
description: 'UUID of the currency.'
example: consequatur
nullable: false
required:
- international
- local
- year
- currency_id
gallery:
type: array
description: 'nullable Array of gallery images (max 2MB each).'
items:
type: string
format: binary
nullable: true
application_fee:
type: number
description: 'The application cost.'
example: 100.0
nullable: false
application_flat_price:
type: number
description: 'Total flat price for application.'
example: 500.0
nullable: false
admission_requirements:
type: string
description: 'nullable Admission requirements text.'
example: consequatur
nullable: true
application_link:
type: string
description: 'nullable URL to application portal.'
example: consequatur
nullable: true
monthly_living_cost:
type: string
description: 'Monthly living cost estimate.'
example: '$1,200-$1,500'
nullable: false
affordability_tier:
type: string
description: 'Affordability category.'
example: Mid-Range
nullable: false
required:
- name
- address
- country
- admission_rate
- scholarship_availability
- study_destination_id
- contact
- university_description
- annual_tuition
- application_fee
- application_flat_price
- monthly_living_cost
- affordability_tier
'/api/v1/admin/universities/{university_id}':
put:
summary: 'Update the specified university.'
operationId: updateTheSpecifiedUniversity
description: ''
parameters: []
responses: { }
tags:
- Universities
requestBody:
required: false
content:
multipart/form-data:
schema:
type: object
properties:
name:
type: string
description: 'optional The name of the university.'
example: 'University of Toronto Updated'
nullable: false
address:
type: string
description: 'optional Full physical address.'
example: consequatur
nullable: false
logo:
type: string
format: binary
description: 'optional New university logo image (max 2MB).'
nullable: true
country:
type: string
description: 'optional Country name.'
example: Canada
nullable: false
admission_rate:
type: number
description: 'optional Admission percentage (0-100).'
example: 45.0
nullable: false
is_scholarship_available:
type: boolean
description: 'optional Indicates if scholarships available.'
example: true
nullable: false
scholarship_availability:
type: string
description: 'optional Scholarship availability level. One of: high, moderate, very high, low, very high (full), very high (need blind), very high (stipendium).'
example: 'very high (full)'
nullable: false
study_destination_id:
type: uuid
description: 'optional The ID of the study destination.'
example: consequatur
nullable: false
contact:
type: object
description: 'optional Contact information.'
example: []
nullable: false
properties:
email:
type: array
description: 'optional Array of email addresses.'
example:
- qkunze@example.com
items:
type: string
phone:
type: array
description: 'optional Array of phone numbers.'
example:
- consequatur
items:
type: string
website:
type: string
description: 'optional Website URL.'
example: consequatur
nullable: true
university_description:
type: object
description: 'optional Detailed description updates.'
example: []
nullable: false
properties:
description:
type: string
description: 'optional General description.'
example: 'Dolores dolorum amet iste laborum eius est dolor.'
nullable: false
campus_size:
type: string
description: 'optional Campus size.'
example: Large
nullable: false
student_life:
type: string
description: 'optional Student life description.'
example: consequatur
nullable: false
city_type:
type: string
description: 'optional City type.'
example: Urban
nullable: false
climate:
type: string
description: 'optional Climate type.'
example: Temperate
nullable: false
annual_tuition:
type: object
description: 'optional Tuition details updates.'
example: []
nullable: false
properties:
international:
type: number
description: 'optional International student fee.'
example: 11613.31890586
nullable: false
local:
type: number
description: 'optional Local student fee.'
example: 11613.31890586
nullable: false
year:
type: integer
description: 'optional Academic year.'
example: 2024
nullable: false
currency_id:
type: uuid
description: 'optional UUID of the currency.'
example: consequatur
nullable: false
application_fee:
type: number
description: 'optional The application cost.'
example: 11613.31890586
nullable: false
application_flat_price:
type: number
description: 'optional Total flat price for application.'
example: 11613.31890586
nullable: false
admission_requirements:
type: string
description: 'optional Admission requirements text.'
example: consequatur
nullable: true
application_link:
type: string
description: 'optional URL to application portal.'
example: consequatur
nullable: true
monthly_living_cost:
type: string
description: 'optional Monthly living cost estimate.'
example: consequatur
nullable: false
affordability_tier:
type: string
description: 'optional Affordability category.'
example: consequatur
nullable: false
gallery:
type: array
description: 'optional New gallery images (replaces old ones).'
items:
type: string
format: binary
nullable: true
delete:
summary: 'Remove the specified university.'
operationId: removeTheSpecifiedUniversity
description: ''
parameters: []
responses: { }
tags:
- Universities
parameters:
-
in: path
name: university_id
description: 'The ID of the university.'
example: 00ce85a9-6d2d-4be1-a0cd-274d7c063eac
required: true
schema:
type: string
-
in: path
name: university
description: 'Optional parameter. uuid required The UUID of the university.'
required: true
schema:
type: string
examples:
omitted:
summary: 'When the value is omitted'
value: ''
present:
summary: 'When the value is present'
value: 9b1e967a-706d-4912-9c31
/api/v1/applications:
get:
summary: 'Get all applications'
operationId: getAllApplications
description: "Returns a paginated list of university applications.
\nYou can filter by status, student, major or university."
parameters:
-
in: query
name: status
description: 'Filter by status'
example: Submitted
required: false
schema:
type: string
description: 'Filter by status'
example: Submitted
nullable: false
-
in: query
name: student_id
description: 'Filter by student id'
example: 5
required: false
schema:
type: integer
description: 'Filter by student id'
example: 5
nullable: false
-
in: query
name: major_id
description: 'Filter by major id'
example: 12
required: false
schema:
type: integer
description: 'Filter by major id'
example: 12
nullable: false
-
in: query
name: applied_university_id
description: 'Filter by university id'
example: 8
required: false
schema:
type: integer
description: 'Filter by university id'
example: 8
nullable: false
-
in: query
name: page
description: 'Page number'
example: 1
required: false
schema:
type: integer
description: 'Page number'
example: 1
nullable: false
responses:
200:
description: 'Paginated list'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'University Applications Management'
post:
summary: 'Create a new application'
operationId: createANewApplication
description: ''
parameters: []
responses:
201:
description: ''
content:
application/json:
schema:
type: object
example:
id: 550e8400-e29b-41d4-a716-446655440000
application_date: '2025-12-11'
status: Draft
response_date: null
feedback: null
student:
id: 5
name: 'John Doe'
major:
id: 12
name: 'Data Science'
applied_university:
id: 8
name: 'Tech University'
properties:
id:
type: string
example: 550e8400-e29b-41d4-a716-446655440000
application_date:
type: string
example: '2025-12-11'
status:
type: string
example: Draft
response_date:
type: string
example: null
feedback:
type: string
example: null
student:
type: object
properties:
id:
type: integer
example: 5
name:
type: string
example: 'John Doe'
major:
type: object
properties:
id:
type: integer
example: 12
name:
type: string
example: 'Data Science'
applied_university:
type: object
properties:
id:
type: integer
example: 8
name:
type: string
example: 'Tech University'
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: Forbidden
properties:
message:
type: string
example: Forbidden
tags:
- 'University Applications Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
major_id:
type: string
description: 'The id of an existing record in the majors table.'
example: consequatur
nullable: false
application_date:
type: string
description: 'Must be a valid date.'
example: '2026-04-18T17:44:14'
nullable: false
applied_university_id:
type: string
description: 'The id of an existing record in the universities table.'
example: consequatur
nullable: false
required:
- major_id
- application_date
- applied_university_id
'/api/v1/applications/{id}':
get:
summary: 'Get single application'
operationId: getSingleApplication
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 550e8400-e29b-41d4-a716-446655440000
application_date: '2025-06-01'
status: Submitted
response_date: null
feedback: null
student:
id: 5
name: 'John Doe'
major:
id: 12
name: 'Data Science'
applied_university:
id: 8
name: 'Tech University'
properties:
id:
type: string
example: 550e8400-e29b-41d4-a716-446655440000
application_date:
type: string
example: '2025-06-01'
status:
type: string
example: Submitted
response_date:
type: string
example: null
feedback:
type: string
example: null
student:
type: object
properties:
id:
type: integer
example: 5
name:
type: string
example: 'John Doe'
major:
type: object
properties:
id:
type: integer
example: 12
name:
type: string
example: 'Data Science'
applied_university:
type: object
properties:
id:
type: integer
example: 8
name:
type: string
example: 'Tech University'
tags:
- 'University Applications Management'
put:
summary: 'Update application'
operationId: updateApplication
description: 'Only status, response_date and feedback can be edited after creation.'
parameters: []
responses:
200:
description: ''
content:
text/plain:
schema:
type: string
example: '{ ...updated resource... }'
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: Forbidden
properties:
message:
type: string
example: Forbidden
tags:
- 'University Applications Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: ''
example: null
nullable: false
response_date:
type: string
description: 'Must be a valid date.'
example: '2026-04-18T17:44:14'
nullable: true
feedback:
type: string
description: ''
example: consequatur
nullable: true
delete:
summary: 'Delete application'
operationId: deleteApplication
description: ''
parameters: []
responses:
204:
description: ''
content:
application/json:
schema:
type: object
example: { }
properties: { }
403:
description: ''
content:
application/json:
schema:
type: object
example:
message: Forbidden
properties:
message:
type: string
example: Forbidden
tags:
- 'University Applications Management'
parameters:
-
in: path
name: id
description: 'The ID of the application.'
example: 1b7f325d-b2cf-4dc4-8e39-2bb2fa02a1cd
required: true
schema:
type: string
'/api/v1/users/{user_id}':
post:
summary: 'Update user'
operationId: updateUser
description: "Admins can update any user. Users can only update their own name, email, profile picture, password, and majors.\nFor the password, the request must include a password_confirmation field that matches the new password.\nOnly admins can change user roles."
parameters: []
responses:
200:
description: 'User updated successfully'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'User not found'
content:
application/json:
schema:
type: object
nullable: true
422:
description: 'Validation error'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
requestBody:
required: false
content:
multipart/form-data:
schema:
type: object
properties:
name:
type: string
description: 'User name'
example: 'John Doe'
nullable: false
email:
type: string
description: 'User email (must be unique)'
example: john@example.com
nullable: false
role_id:
type: integer
description: 'Role ID - admin only (1=student, 2=manager, 3=admin, 4=adviser)'
example: 4
nullable: false
profile_picture:
type: string
format: binary
description: 'User profile image (jpeg, png, jpg, webp), max 2MB'
nullable: false
password:
type: string
description: 'New password (min 8 characters)'
example: newpassword123
nullable: false
major_ids:
type: array
description: 'List of Major IDs to associate with the user'
example:
- 1
- 5
- 12
items:
type: string
password_confirmation:
type: string
description: 'Must match password field'
example: newpassword123
nullable: false
parameters:
-
in: path
name: user_id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
/api/v1/admin/users:
get:
summary: 'List all users with filters'
operationId: listAllUsersWithFilters
description: "Admins can filter by role, search by name/email, and view all users.\nSupports search, filtering, sorting, and pagination."
parameters:
-
in: query
name: role_id
description: 'Filter by role ID (1=student, 2=manager, 3=admin, 4=adviser)'
example: 1
required: false
schema:
type: integer
description: 'Filter by role ID (1=student, 2=manager, 3=admin, 4=adviser)'
example: 1
nullable: false
-
in: query
name: search
description: 'Search by name or email'
example: John
required: false
schema:
type: string
description: 'Search by name or email'
example: John
nullable: false
-
in: query
name: sort_by
description: 'Sort field (name, email, created_at, updated_at, role_id)'
example: name
required: false
schema:
type: string
description: 'Sort field (name, email, created_at, updated_at, role_id)'
example: name
nullable: false
-
in: query
name: sort_order
description: 'Sort order (asc or desc)'
example: asc
required: false
schema:
type: string
description: 'Sort order (asc or desc)'
example: asc
nullable: false
-
in: query
name: per_page
description: 'Results per page (5-100)'
example: 15
required: false
schema:
type: integer
description: 'Results per page (5-100)'
example: 15
nullable: false
responses:
200:
description: 'Paginated list of users'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
role_id:
type: integer
description: 'The id of an existing record in the roles table.'
example: 17
nullable: true
search:
type: string
description: 'Must not be greater than 255 characters.'
example: mqeopfuudtdsufvyvddqa
nullable: true
sort_by:
type: string
description: ''
example: updated_at
nullable: true
enum:
- name
- email
- created_at
- updated_at
- role_id
sort_order:
type: string
description: ''
example: asc
nullable: true
enum:
- asc
- desc
per_page:
type: integer
description: 'Must be at least 5. Must not be greater than 100.'
example: 13
nullable: true
'/api/v1/admin/users/{id}':
get:
summary: 'Get user details'
operationId: getUserDetails
description: 'Returns user information including role, relationships, and student/adviser data.'
parameters: []
responses:
200:
description: 'User details with all relationships'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'User not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
put:
summary: 'Update user'
operationId: updateUser
description: "Admins can update any user. Users can only update their own name, email, profile picture, password, and majors.\nFor the password, the request must include a password_confirmation field that matches the new password.\nOnly admins can change user roles."
parameters: []
responses:
200:
description: 'User updated successfully'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'User not found'
content:
application/json:
schema:
type: object
nullable: true
422:
description: 'Validation error'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
requestBody:
required: false
content:
multipart/form-data:
schema:
type: object
properties:
name:
type: string
description: 'User name'
example: 'John Doe'
nullable: false
email:
type: string
description: 'User email (must be unique)'
example: john@example.com
nullable: false
role_id:
type: integer
description: 'Role ID - admin only (1=student, 2=manager, 3=admin, 4=adviser)'
example: 4
nullable: false
profile_picture:
type: string
format: binary
description: 'User profile image (jpeg, png, jpg, webp), max 2MB'
nullable: false
password:
type: string
description: 'New password (min 8 characters)'
example: newpassword123
nullable: false
major_ids:
type: array
description: 'List of Major IDs to associate with the user'
example:
- 1
- 5
- 12
items:
type: string
password_confirmation:
type: string
description: 'Must match password field'
example: newpassword123
nullable: false
delete:
summary: 'Delete user'
operationId: deleteUser
description: 'Only admins can delete users, and cannot delete their own account.'
parameters: []
responses:
204:
description: 'User deleted successfully'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized or cannot delete self'
content:
application/json:
schema:
type: object
nullable: true
422:
description: 'Cannot delete own account'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
parameters:
-
in: path
name: id
description: 'The ID of the user.'
example: 1
required: true
schema:
type: integer
/api/v1/admin/users-by-role:
get:
summary: 'Get users by role'
operationId: getUsersByRole
description: 'Retrieve all users with a specific role.'
parameters:
-
in: query
name: role_name
description: 'Role name (student, manager, admin, adviser)'
example: adviser
required: true
schema:
type: string
description: 'Role name (student, manager, admin, adviser)'
example: adviser
nullable: false
-
in: query
name: per_page
description: 'Results per page'
example: 15
required: false
schema:
type: integer
description: 'Results per page'
example: 15
nullable: false
responses:
200:
description: 'Paginated list of users with specified role'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
role_name:
type: string
description: ''
example: adviser
nullable: false
enum:
- student
- manager
- admin
- adviser
per_page:
type: integer
description: 'Must be at least 5. Must not be greater than 100.'
example: 21
nullable: true
required:
- role_name
/api/v1/admin/users-statistics:
get:
summary: 'Get user statistics'
operationId: getUserStatistics
description: 'Returns total user count and breakdown by role.'
parameters: []
responses:
200:
description: 'User statistics breakdown by role'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
/api/v1/admin/users/change-role:
post:
summary: 'Change user role'
operationId: changeUserRole
description: "Admin-only endpoint to change a user's role with audit trail."
parameters: []
responses:
200:
description: 'User role changed successfully'
content:
application/json:
schema:
type: object
example:
message: 'User role updated successfully'
old_role: adviser
new_role: manager
properties:
message:
type: string
example: 'User role updated successfully'
old_role:
type: string
example: adviser
new_role:
type: string
example: manager
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
404:
description: 'User not found'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
user_id:
type: integer
description: 'The user ID to modify'
example: 5
nullable: false
role_id:
type: integer
description: 'The new role ID (1=student, 2=manager, 3=admin, 4=adviser)'
example: 2
nullable: false
required:
- user_id
- role_id
/api/v1/admin/users/bulk-action:
post:
summary: 'Bulk user operations'
operationId: bulkUserOperations
description: 'Supports bulk delete and bulk role change. Authenticated user is automatically excluded from operations.'
parameters: []
responses:
200:
description: 'Bulk operation completed'
content:
application/json:
schema:
type: object
example:
message: 'Bulk operation completed'
affected: 5
action: delete
properties:
message:
type: string
example: 'Bulk operation completed'
affected:
type: integer
example: 5
action:
type: string
example: delete
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
user_ids:
type: array
description: 'Array of user IDs to operate on'
example: '[5, 6, 7]'
items:
type: string
action:
type: string
description: 'Action to perform: delete or change_role'
example: delete
nullable: false
role_id:
type: integer
description: 'Required if action is change_role'
example: 2
nullable: false
required:
- user_ids
- action
/api/v1/admin/users-export:
get:
summary: 'Export users to CSV'
operationId: exportUsersToCSV
description: 'Exports user data as CSV file. Admins and managers can export; optional role filter available.'
parameters:
-
in: query
name: role_id
description: 'Optional role ID to filter by'
example: 1
required: false
schema:
type: integer
description: 'Optional role ID to filter by'
example: 1
nullable: false
responses:
200:
description: 'CSV file content with columns: ID, Name, Email, Role, Created At, Updated At'
content:
application/json:
schema:
type: object
nullable: true
403:
description: 'Not authorized'
content:
application/json:
schema:
type: object
nullable: true
tags:
- 'User Management'
/api/v1/notifications:
get:
summary: ''
operationId: getApiV1Notifications
description: ''
parameters:
-
in: query
name: status
description: 'the kind of status to fetch example: unread, read, all.'
example: consequatur
required: false
schema:
type: string
description: 'the kind of status to fetch example: unread, read, all.'
example: consequatur
nullable: false
-
in: query
name: limit
description: 'the number of notifications to get.'
example: 17
required: false
schema:
type: integer
description: 'the number of notifications to get.'
example: 17
nullable: false
-
in: query
name: paginated
description: "choose if you need the pagination or not.\n\nGet latest 10 notifications (non-paginated):\n /api/notifications?limit=10"
example: false
required: false
schema:
type: boolean
description: "choose if you need the pagination or not.\n\nGet latest 10 notifications (non-paginated):\n /api/notifications?limit=10"
example: false
nullable: false
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.031029Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.031029Z'
tags:
- 'User Notification Management'
'/api/v1/notifications/{id}':
get:
summary: 'Display one notification and mark it as read.'
operationId: displayOneNotificationAndMarkItAsRead
description: ''
parameters:
-
in: query
name: status
description: 'the kind of status to fetch example: unread, read, all.'
example: consequatur
required: false
schema:
type: string
description: 'the kind of status to fetch example: unread, read, all.'
example: consequatur
nullable: false
-
in: query
name: limit
description: 'the number of notifications to get.'
example: 17
required: false
schema:
type: integer
description: 'the number of notifications to get.'
example: 17
nullable: false
-
in: query
name: paginated
description: "choose if you need the pagination or not.\n\nGet latest 10 notifications (non-paginated):\n /api/notifications?limit=10"
example: false
required: false
schema:
type: boolean
description: "choose if you need the pagination or not.\n\nGet latest 10 notifications (non-paginated):\n /api/notifications?limit=10"
example: false
nullable: false
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.035830Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.035830Z'
tags:
- 'User Notification Management'
parameters:
-
in: path
name: id
description: 'The ID of the notification.'
example: consequatur
required: true
schema:
type: string
/api/v1/notifications/read-all:
post:
summary: 'Mark all notifications as read.'
operationId: markAllNotificationsAsRead
description: ''
parameters:
-
in: query
name: status
description: 'the kind of status to fetch example: unread, read, all.'
example: consequatur
required: false
schema:
type: string
description: 'the kind of status to fetch example: unread, read, all.'
example: consequatur
nullable: false
-
in: query
name: limit
description: 'the number of notifications to get.'
example: 17
required: false
schema:
type: integer
description: 'the number of notifications to get.'
example: 17
nullable: false
-
in: query
name: paginated
description: "choose if you need the pagination or not.\n\nGet latest 10 notifications (non-paginated):\n /api/notifications?limit=10"
example: false
required: false
schema:
type: boolean
description: "choose if you need the pagination or not.\n\nGet latest 10 notifications (non-paginated):\n /api/notifications?limit=10"
example: false
nullable: false
responses: { }
tags:
- 'User Notification Management'
/api/v1/admin/roles:
get:
summary: 'Display a listing of all the roles.'
operationId: displayAListingOfAllTheRoles
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.259827Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.259827Z'
tags:
- 'Users roles'
post:
summary: 'Store a newly created resource in storage.'
operationId: storeANewlyCreatedResourceInStorage
description: ''
parameters: []
responses: { }
tags:
- 'Users roles'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: ''
example: consequatur
nullable: false
description:
type: string
description: ''
example: 'Dolores dolorum amet iste laborum eius est dolor.'
nullable: true
required:
- name
'/api/v1/admin/roles/{id}':
get:
summary: 'Display the specified role.'
operationId: displayTheSpecifiedRole
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.265461Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.265461Z'
tags:
- 'Users roles'
put:
summary: 'Update the role in the table.'
operationId: updateTheRoleInTheTable
description: ''
parameters: []
responses: { }
tags:
- 'Users roles'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: ''
example: consequatur
nullable: false
description:
type: string
description: ''
example: 'Dolores dolorum amet iste laborum eius est dolor.'
nullable: false
delete:
summary: 'Remove the specified role from the table.'
operationId: removeTheSpecifiedRoleFromTheTable
description: ''
parameters: []
responses: { }
tags:
- 'Users roles'
parameters:
-
in: path
name: id
description: 'The ID of the role.'
example: 1
required: true
schema:
type: integer
'/api/v1/admin/roles/users/{role_id}':
get:
summary: 'Get the users by a specified role'
operationId: getTheUsersByASpecifiedRole
description: ''
parameters: []
responses:
500:
description: ''
content:
application/json:
schema:
type: object
example:
success: false
errors: Unauthenticated.
timestamp: '2026-04-18T17:44:14.273944Z'
properties:
success:
type: boolean
example: false
errors:
type: string
example: Unauthenticated.
timestamp:
type: string
example: '2026-04-18T17:44:14.273944Z'
tags:
- 'Users roles'
parameters:
-
in: path
name: role_id
description: 'The ID of the role.'
example: 1
required: true
schema:
type: integer