0

Endpoint — one addressable URL + method combination in an API

Beginner5 min read·eng-13-012

Concept

Endpoint — one specific, addressable combination of a URL path and an HTTP method. Not just a URL — the METHOD matters.

GET /users and POST /users are TWO DIFFERENT endpoints. They share a path but do different things.

Components of an endpoint:

  • Method: GET, POST, PUT, PATCH, DELETE, etc.
  • URL path: /users/{id} — may include route parameters.
  • Query parameters (optional): /users?role=admin — additional filters, not part of the path.
  • Request body (for POST/PUT/PATCH): What data the endpoint expects.
  • Response: What status code and body the endpoint returns.

Resource vs action endpoints:

  • Resource endpoint (RESTful): GET /orders/{id}, POST /orders, DELETE /orders/{id}. Named after what it operates on.
  • Action endpoint (RPC-style): POST /orders/{id}/cancel, POST /payments/charge. Named after what it does. Sometimes more readable for complex operations.

Base URL vs endpoint URL:

  • Base URL: https://api.example.com/v1
  • Endpoint: GET /users/{id}
  • Full URL: https://api.example.com/v1/users/42

Endpoint documentation: An endpoint definition includes method, path, description, parameters, request body schema, and response schemas. Tools like Swagger/OpenAPI capture this.

API surface: The total set of endpoints your API exposes. Keep it minimal — every endpoint is a commitment to maintain, version, and secure.

Laravel route listing: php artisan route:list shows every registered endpoint — method, URI, middleware, controller action.

Code Example

php
<?php
// ENDPOINTS — each line below is a distinct endpoint
Route::get('/users',              [UserController::class, 'index']);    // endpoint 1
Route::post('/users',             [UserController::class, 'store']);    // endpoint 2
Route::get('/users/{id}',         [UserController::class, 'show']);     // endpoint 3
Route::put('/users/{id}',         [UserController::class, 'update']);   // endpoint 4
Route::patch('/users/{id}',       [UserController::class, 'update']);   // endpoint 5 (partial)
Route::delete('/users/{id}',      [UserController::class, 'destroy']);  // endpoint 6

// Same PATH — different METHODS — different endpoints!
// GET /users   → list all users
// POST /users  → create a new user
// Both are at /users but they're distinct endpoints

// Action endpoints (non-RESTful but clearer for complex operations)
Route::post('/orders/{order}/cancel',  [OrderController::class, 'cancel']);  // action endpoint
Route::post('/orders/{order}/ship',    [OrderController::class, 'ship']);
Route::post('/payments/refund',        [PaymentController::class, 'refund']);

// api() resource registers 5 standard endpoints at once
Route::apiResource('orders', OrderController::class);
// GET    /orders           → index
// POST   /orders           → store
// GET    /orders/{order}   → show
// PUT    /orders/{order}   → update
// DELETE /orders/{order}   → destroy

// Viewing all endpoints
// php artisan route:list
// Output:
// GET|HEAD  /users              users.index     UserController@index
// POST      /users              users.store     UserController@store
// GET|HEAD  /users/{user}       users.show      UserController@show
// PUT|PATCH /users/{user}       users.update    UserController@update
// DELETE    /users/{user}       users.destroy   UserController@destroy

// OpenAPI/Swagger documentation for an endpoint
// Using a package like dedoc/scramble or via attributes:

/**
 * @OA\Get(
 *     path="/users/{id}",
 *     summary="Get a user by ID",
 *     @OA\Parameter(name="id", in="path", required=true, @OA\Schema(type="integer")),
 *     @OA\Response(response=200, description="User resource"),
 *     @OA\Response(response=404, description="User not found"),
 * )
 */
class UserController
{
    public function show(int $id): JsonResponse
    {
        return response()->json(User::findOrFail($id));
    }
}