All endpoints are JSON and live under /api/* unless noted.
- Base URL (local):
http://localhost:8000 - Auth: Bearer token via Laravel Sanctum (personal access tokens)
- Default Content-Type:
application/json
POST /api/auth/token
Body (JSON)
{
"email": "instructor1@example.com",
"password": "password"
}Response (200)
{ "token": "PASTE_ME" }Postman auto‑save: In the collection, the Tests tab for this request saves the returned token to both the environment and collection variables named
token. You can reuse it in headers asBearer {{token}}.
// Parse JSON response
const response = pm.response.json();
// Save token to environment and collection variables if present
if (response.token) {
pm.environment.set("token", response.token);
pm.collectionVariables.set("token", response.token);
console.log("Token saved to environment and collection variables");
} else {
console.warn("⚠️ No token field found in response");
}Authorization: Bearer PASTE_ME
Accept: application/json
You can also generate a token manually via Tinker if needed:
php artisan tinker
>>> $u = \App\Models\User::where('email','instructor1@example.com')->first();
>>> $token = $u->createToken('cli')->plainTextToken; // copy this valueReturns a list of courses. Supports simple search and published filtering.
Query params
search(optional): substring match on title/descriptionpublished(optional):1or0
Example
curl -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" "http://localhost:8000/api/courses?search=php&published=1"Response 200 (array)
[
{
"id": 5,
"title": "Intro to PHP",
"slug": "intro-to-php",
"description": "Basics",
"published": true,
"instructor_id": 2
}
]Creates a course.
Body
{
"title": "API Design 101",
"description": "Structure, versioning, docs.",
"published": true
}Example
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" -d '{"title":"API Design 101","description":"Structure, versioning, docs.","published":true}' http://localhost:8000/api/coursesResponse 201
{
"id": 12,
"title": "API Design 101",
"slug": "api-design-101",
"description": "Structure, versioning, docs.",
"published": true,
"instructor_id": 2
}Fetch a single course.
curl -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://localhost:8000/api/courses/12Response 200
{
"id": 12,
"title": "API Design 101",
"slug": "api-design-101",
"description": "Structure, versioning, docs.",
"published": true,
"instructor_id": 2
}curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" -d '{"published":false}' http://localhost:8000/api/courses/12Response 200 – updated course JSON.
curl -X DELETE -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://localhost:8000/api/courses/12Response 204 – no content.
List lessons of a course.
curl -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://localhost:8000/api/courses/12/lessonsResponse 200
[
{"id":101,"course_id":12,"order":1,"title":"Intro","content":"..."},
{"id":102,"course_id":12,"order":2,"title":"HTTP","content":"..."}
]Create a lesson (JSON).
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" -d '{"title":"Auth","content":"Tokens and cookies"}' http://localhost:8000/api/courses/12/lessonsResponse 201
{"id":110,"course_id":12,"order":3,"title":"Auth","content":"Tokens and cookies"}Fetch a single lesson.
curl -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://localhost:8000/api/lessons/110Response 200
{"id":110,"course_id":12,"order":3,"title":"Auth","content":"Tokens and cookies"}Create a lesson with file using multipart form-data.
title(text, required)content(text, optional)attachment(file, optional)
Example (curl)
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -F "title=Lesson 1 - Overview" -F "content=Lesson intro..." -F "attachment=@/path/to/file.pdf" http://localhost:8000/api/courses/11/lessonsResponse 201
{
"id": 119,
"course_id": 11,
"order": 1,
"title": "Lesson 1 - Overview",
"content": "Lesson intro...",
"has_attachment": true,
"attachment_url": "http://localhost:8000/api/lessons/119/attachment",
"created_at": "2025-11-06T21:35:50.000000Z"
}Notes
- If you upload a file,
has_attachmentshould betrueandattachment_urlwill be available for download.- Attachments can later be replaced or removed via
PATCH /api/lessons/{id}(see below).
Supports updating text fields and managing the attachment.
- JSON fields:
title,content - Multipart fields:
attachment(file) → replaces existing fileremove_attachment=1(text/boolean) → removes existing file
Examples Replace file:
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -F "attachment=@/path/to/new.pdf" http://localhost:8000/api/lessons/119Remove file:
curl -X PATCH -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -F "remove_attachment=1" http://localhost:8000/api/lessons/119Response 200
{
"id": 119,
"course_id": 11,
"order": 1,
"title": "Lesson 1 - Overview",
"content": "Lesson intro.",
"has_attachment": false,
"attachment_url": null,
"created_at": "2025-11-06T21:35:50.000000Z"
}Downloads the lesson’s attachment (uses content-disposition filename).
curl -L -H "Authorization: Bearer $TOKEN" http://localhost:8000/api/lessons/11/attachment -o lesson-11-attachmentcurl -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://localhost:8000/api/lessons/110/commentsResponse 200
[
{"id":1,"user_id":3,"lesson_id":110,"body":"Great!","created_at":"2025-11-05T16:23:10Z"}
]Allowed for instructor of the course or enrolled students.
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" -H "Content-Type: application/json" -d '{"body":"Thanks for the lesson!"}' http://localhost:8000/api/lessons/110/commentsResponse 201
{"id":9,"user_id":3,"lesson_id":110,"body":"Thanks for the lesson!","created_at":"2025-11-05T16:40:00Z"}Enrolls the authenticated student into a published course (idempotent).
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://localhost:8000/api/courses/12/enrollResponse 200
{"status":"ok","message":"Enrolled"}Returns courses the current user is enrolled in (and taught, if instructor).
curl -H "Authorization: Bearer $TOKEN" -H "Accept: application/json" http://localhost:8000/api/me/coursesResponse 200
{
"enrolled": [
{"id":12,"title":"API Design 101","slug":"api-design-101","published":true}
],
"instructed": [
{"id":5,"title":"Intro to PHP","slug":"intro-to-php","published":true}
]
}- 401 Unauthorized — missing or invalid token.
- 403 Forbidden — authenticated but not permitted.
- 404 Not Found — resource doesn’t exist or you don’t have access.
- 422 Unprocessable Entity — validation failed (check
errorsin JSON).
Example 422
{
"message": "The given data was invalid.",
"errors": { "title": ["The title field is required."] }
}- All write endpoints require auth; course creation/updating/deleting is instructor-only (policy).
- Slugs are generated automatically on create; you may pass one explicitly if needed.
- Lesson order is maintained per course; UI offers up/down controls on the web side.
- When testing with Postman, prefer the collection/environment
tokenvariable and setAuthorization: Bearer {{token}}on requests.