A visual, hands-on introduction for new developers. Covers APIs, domains, endpoints, Laravel routing, Form Requests, authentication and debugging. Read top to bottom and use the simulators.
API = Application Programming Interface. A agreed set of rules that lets one program ask another program for data or for an action, without knowing how the other program works inside.
GET /users, POST /login.Almost every modern app is split in three layers. Each layer has one job.
A domain is the human-friendly name of a server (devlapan.com). Computers find each other by IP address (198.51.100.7). DNS is the phone book that translates one into the other.
https: how to talk. HTTPS = encrypted HTTP. Always use it.api: a sub-section you create. www, erp, api, admin can each point to a different server.devlapan: the name you buy and own (registrar: Namecheap, GoDaddy…).com: top-level domain. Others: .na, .co.za, .org.:443: which door on the server. 443 = HTTPS, 80 = HTTP (hidden when default). Dev servers use 3000, 5173, 8000…/v1/users/42: which resource. This is the endpoint.?active=true: optional filters, joined with &.| Record | Meaning | Example |
|---|---|---|
| A | name → IPv4 address | api.devlapan.com → 198.51.100.7 |
| CNAME | name → another name (alias) | www → devlapan.com |
| MX | where email goes | mail.devlapan.com |
| TXT | verification, SPF/DKIM email auth | v=spf1 … |
What really happens when a user opens app.devlapan.com and clicks Login. Step through it.
Every API call is a request followed by exactly one response. Both have the same shape.
POST /v1/login ← method + endpoint Host: api.devlapan.com Content-Type: application/json Authorization: Bearer eyJhbGci… ← who I am { "email": "a@b.com", "password": "secret" } ← body
HTTP/1.1 200 OK ← status code Content-Type: application/json { "token": "eyJhbGci…", "user": { "id": 42, "name": "Mike" } }
| Method | Does | Example | Body? |
|---|---|---|---|
| GET | Read | GET /users/42 | no |
| POST | Create / submit | POST /users | yes |
| PUT | Replace / update | PUT /users/42 | yes |
| DELETE | Remove | DELETE /users/42 | no |
200 OK · 201 Created · 204 No content400 bad data · 401 not logged in · 403 not allowed · 404 not found · 422 validation · 429 too many500 crash · 502/503 server down · 504 timeoutAn endpoint is one specific address on your API that does one specific job. It is the combination of an HTTP method and a URL path. The same path with a different method is a different endpoint.
A resource is a thing your system manages: invoices, loans, customers. REST gives every resource the same set of endpoints, so the team always knows where things are.
| Method | Endpoint | What it does | Laravel controller method | Success code |
|---|---|---|---|---|
| GET | /api/v1/invoices | List invoices (paginated) | index | 200 |
| POST | /api/v1/invoices | Create an invoice | store | 201 |
| GET | /api/v1/invoices/{id} | Read one invoice | show | 200 |
| PUT | /api/v1/invoices/{id} | Update an invoice | update | 200 |
| DELETE | /api/v1/invoices/{id} | Delete an invoice | destroy | 204 |
Route::apiResource('invoices', InvoiceController::class); Run php artisan route:list to see every endpoint your app exposes./invoices, not /getInvoice./loan-applications./customers/7/loans./v1/… so you can change things later without breaking old apps.| Path parameter Identifies one record | /invoices/15 |
| Query parameter Filters, sorting, paging | /invoices?status=paid&page=2 |
Data you are creating goes in the JSON body, never in the URL.
routes/api.php with /api. Whether your final URL is api.devlapan.com/api/v1/… or api.devlapan.com/v1/… depends on your server setup, so confirm it with route:list.A request passes through a fixed pipeline of layers. Each layer has one job and can stop the request early with an error. Click a layer.
php artisan serve | run locally on :8000 |
php artisan route:list | list all endpoints |
php artisan make:controller InvoiceController --api | new controller |
php artisan make:request StoreInvoiceRequest | new form request |
php artisan make:resource InvoiceResource | new API resource |
php artisan make:model Invoice -m | model + migration |
php artisan migrate | apply DB changes |
php artisan config:clear | after editing .env |
A Form Request is a dedicated class that validates the user's input and checks permission before anything else happens. Laravel runs it automatically before your controller or service is called. If anything is wrong, the request is rejected right there, so bad data can never reach your business logic or your database.
403 Forbidden.422 with an error per field.POST /api/v1/invoices with StoreInvoiceRequest// rules() 'customer_email' => required|email 'amount' => required|numeric|min:1 'due_date' => required|date|after:today
Press "Send request".
errors.<field> from the 422 response and show each message under the matching input. Frontend checks are for convenience. The Form Request is the real protection, because anyone can bypass the browser and call the API directly.A service is a plain PHP class (usually in app/Services) that holds your business logic: the real rules and steps of what your system does. The controller handles the web part, the service does the actual work.
For a very simple create-and-save you can skip the service. Add one when logic grows beyond a line or two.
private InvoiceService $invoices) and Laravel builds it automatically. This is called dependency injection.The files below work together. First the setup (route, migration, model), then the layers a request passes through: Form Request, Controller, Service, Resource.
$request->validated(), never $request->all(). all() includes fields the user invented ("status":"paid", "user_id":1). validated() returns only the fields listed in rules(). Pair it with $fillable on the model.| Term | Meaning |
|---|---|
| Route | The line in routes/api.php that connects a method + URL to controller code. |
| Controller | Receives the request, calls the model, returns a response. Should stay short. |
| Form Request | Validates the input and checks permission for one endpoint. Runs before the controller and service and rejects bad requests with 422 or 403. |
| Service | A plain PHP class holding business logic and multi-step workflows. Called by controllers, jobs and commands. |
| Model (Eloquent) | PHP class that represents one DB table. Invoice::find(1) instead of raw SQL. |
| Migration | Versioned script that creates or changes tables, so every developer has the same database. |
| API Resource | Decides exactly which fields appear in the JSON output and how they are formatted. |
| Middleware | A gate on the route: authentication, rate limiting, CORS. |
| Policy | Rules for "may this user view/update/delete this specific record?" |
| Sanctum | Laravel's token authentication package. Issues the API token the frontend sends in the Authorization: Bearer header. |
How the browser side sends the create-invoice request and handles the three outcomes: success, validation errors (422) and other failures.
Click the button.
The browser only lets app.devlapan.com call api.devlapan.com if the API says so with a header. It is the backend that must allow it.
Access-Control-Allow-Origin: https://app.devlapan.com
Different subdomain, port or protocol counts as a different "origin". Postman/curl ignore CORS; only browsers enforce it.
| Local | http://localhost:8000 |
| Staging | https://staging-api.devlapan.com |
| Production | https://api.devlapan.com |
Keep the base URL in an env var (VITE_API_URL), never hard-coded.