REST API · Laravel 13

Notes.
Built to be
consumed.

A clean REST API for creating, managing, and attaching files to notes. Paginated lists, search, soft deletes, S3 file storage — all in JSON.

Laravel 13 PHP 8.3 MySQL · RDS AWS S3 EC2

Everything you need, nothing you don't.

CRUD + Search

Full lifecycle

Create, read, update, delete. Paginated lists with full-text search across title and body. 15 per page, query string filtering.

S3 Storage

File attachments

Upload jpg, png, or pdf (max 5 MB) to AWS S3 private buckets. Old files cleaned up automatically on replace or delete. IAM roles, no keys.

Soft Deletes

Recoverable

Notes are soft-deleted by default. Restore them with one call, or permanently delete with S3 file cleanup. Nothing lost by accident.

Validation

Form requests

Dedicated request classes validate every input. File type and size limits enforced server-side. Clean error responses.

API Resources

Consistent JSON

Every response wrapped in Laravel API Resources with proper status codes, pagination meta, and a predictable structure.

AWS Infra

EC2 + RDS + S3

Deployed on EC2, MySQL on RDS, files on S3. IAM roles for S3 access — no access keys in environment files.

Quick start

1

Create a note

curl -X POST https://your-server.com/api/notes \ -H "Content-Type: application/json" \ -d '{"title": "First note", "body": "Hello world."}'
2

Upload a file

curl -X POST https://your-server.com/api/notes/1/file \ -F "file=@document.pdf"
3

Search notes

curl https://your-server.com/api/notes?search=hello
4

Soft-delete and restore

curl -X DELETE https://your-server.com/api/notes/1 # soft delete curl -X POST https://your-server.com/api/notes/1/restore # bring it back

Endpoints

GET /api/notes List all notes ▼

Returns a paginated list of all notes. Use search to filter by title or body.

NameTypeDescription
searchstringoptionalFilter by title or body
pageintegeroptionalPage number (default: 1, 15 per page)
{
  "data": [{
    "id": 1,
    "title": "Meeting notes",
    "body": "Discussed Q4 targets.",
    "file_url": null,
    "deleted_at": null,
    "created_at": "2026-09-30T06:00:00Z",
    "updated_at": "2026-09-30T06:00:00Z"
  }],
  "meta": { "total": 1, "per_page": 15, "current_page": 1, "last_page": 1 }
}
POST /api/notes Create a note ▼

Creates a new note. Optionally attach a file (jpg, png, pdf — max 5 MB) stored on S3.

NameTypeDescription
titlestringrequiredNote title (max 255)
bodystringrequiredNote body
filefileoptionalAttachment (jpg, png, pdf — max 5 MB)
{
  "data": {
    "id": 1,
    "title": "Meeting notes",
    "body": "Discussed Q4 targets.",
    "file_url": "https://haseeb-notes-files.s3.eu-north-1.amazonaws.com/notes/1/agenda.pdf",
    "deleted_at": null,
    "created_at": "2026-09-30T06:00:00Z",
    "updated_at": "2026-09-30T06:00:00Z"
  }
}
GET /api/notes/{id} Get a note ▼

Returns a single note by ID.

{
  "data": {
    "id": 1,
    "title": "Meeting notes",
    "body": "Discussed Q4 targets.",
    "file_url": null,
    "deleted_at": null,
    "created_at": "2026-09-30T06:00:00Z",
    "updated_at": "2026-09-30T06:00:00Z"
  }
}
{ "message": "No query results for model [App\\Models\\Note]." }
PUT /api/notes/{id} Update a note ▼

Updates title, body, or file. All fields optional. New file replaces old S3 file automatically.

NameTypeDescription
titlestringoptionalNew title
bodystringoptionalNew body
filefileoptionalReplacement file
{
  "data": {
    "id": 1,
    "title": "Updated title",
    "body": "Updated body.",
    "file_url": null,
    "deleted_at": null,
    "created_at": "2026-09-30T06:00:00Z",
    "updated_at": "2026-09-30T07:00:00Z"
  }
}
DELETE /api/notes/{id} Soft-delete ▼

Soft-deletes a note. Hidden from list but can be restored.

POST /api/notes/{id}/restore Restore ▼

Restores a previously soft-deleted note.

{
  "data": {
    "id": 1,
    "title": "Meeting notes",
    "body": "Discussed Q4 targets.",
    "file_url": null,
    "deleted_at": null,
    "created_at": "2026-09-30T06:00:00Z",
    "updated_at": "2026-09-30T08:00:00Z"
  }
}
DELETE /api/notes/{id}/force Permanent delete ▼

Permanently deletes a soft-deleted note and removes its S3 file. Cannot be undone.

POST /api/notes/{id}/file Upload file ▼

Uploads or replaces the file attachment. Stored on S3 at notes/{id}/{filename}.

NameTypeDescription
filefilerequiredjpg, png, or pdf — max 5 MB
{
  "data": {
    "id": 1,
    "title": "Meeting notes",
    "body": "Discussed Q4 targets.",
    "file_url": "https://haseeb-notes-files.s3.eu-north-1.amazonaws.com/notes/1/agenda.pdf",
    "deleted_at": null,
    "created_at": "2026-09-30T06:00:00Z",
    "updated_at": "2026-09-30T09:00:00Z"
  }
}

Schema

ColumnTypeDescription
idbigintPKAuto-incrementing primary key
titlevarchar(255)requiredNote title
bodytextrequiredNote body
file_urlvarchar(255)nullableS3 path of attached file
created_attimestampCreation time
updated_attimestampLast update
deleted_attimestampnullableSoft-delete timestamp