Tabla de contenido

Construiste una API REST bien diseñada. Los endpoints funcionan, el JSON llega correctamente, las respuestas tienen los códigos HTTP adecuados. Pero llega un nuevo developer al equipo y no tiene idea de cómo usarla. O tu cliente frontend te pregunta qué parámetros acepta el endpoint de login. Sin documentación, tu API perfecta se vuelve un obstáculo.

¿Por qué documentar tu API?

La documentación de una API no es un lujo: es parte del producto. Una API sin documentar tiene exactamente el mismo problema que una API que no existe, desde la perspectiva de quien la quiere usar.

Beneficios concretos:

  • El equipo de frontend puede trabajar en paralelo sin esperar al backend
  • Los nuevos integrantes se incorporan más rápido
  • Los clientes externos pueden integrarse sin soporte constante
  • La documentación actúa como contrato: define el comportamiento esperado

¿Qué es OpenAPI?

OpenAPI (antes llamado Swagger Specification) es el estándar más adoptado para describir APIs REST. Es un formato en JSON o YAML que describe de forma precisa: todos los endpoints, sus parámetros, cuerpos de petición, respuestas posibles, códigos de error y esquemas de datos.

Swagger es el ecosistema de herramientas alrededor de OpenAPI: Swagger UI (la interfaz web interactiva), Swagger Editor (editor online) y Swagger Codegen (genera código cliente).

Estructura básica de un documento OpenAPI

Un documento OpenAPI mínimo en YAML:

openapi: "3.0.3"
info:
  title: API de 8devmx
  version: "1.0.0"
  description: API REST para gestión de usuarios y publicaciones
  contact:
    email: hola@8devmx.com

servers:
  - url: https://api.8devmx.com/v1
    description: Producción
  - url: http://localhost:8000/api
    description: Desarrollo local

paths:
  /usuarios:
    get:
      summary: Obtener lista de usuarios
      description: Retorna todos los usuarios registrados, paginados de 20 en 20
      tags:
        - Usuarios
      parameters:
        - name: page
          in: query
          description: Número de página
          schema:
            type: integer
            default: 1
      responses:
        "200":
          description: Lista de usuarios exitosa
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ListaUsuarios"
        "401":
          description: No autenticado

Documentar endpoints con ejemplos reales

Veamos un documento más completo para una API de usuarios:

openapi: "3.0.3"
info:
  title: API Usuarios 8devmx
  version: "1.0.0"

servers:
  - url: http://localhost:8000/api

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

  schemas:
    Usuario:
      type: object
      properties:
        id:
          type: integer
          example: 42
        nombre:
          type: string
          example: "Abraham Pech"
        email:
          type: string
          format: email
          example: "hola@8devmx.com"
        ciudad:
          type: string
          example: "Cancún"
        created_at:
          type: string
          format: date-time
          example: "2026-03-26T10:00:00Z"

    CrearUsuario:
      type: object
      required:
        - nombre
        - email
        - password
      properties:
        nombre:
          type: string
          minLength: 2
          maxLength: 100
          example: "Abraham Pech"
        email:
          type: string
          format: email
          example: "hola@8devmx.com"
        password:
          type: string
          minLength: 8
          example: "MiPassword123"
        ciudad:
          type: string
          example: "Cancún"

    Error:
      type: object
      properties:
        error:
          type: string
          example: "Recurso no encontrado"
        code:
          type: integer
          example: 404

paths:
  /auth/login:
    post:
      summary: Iniciar sesión
      tags:
        - Autenticación
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email, password]
              properties:
                email:
                  type: string
                  example: "hola@8devmx.com"
                password:
                  type: string
                  example: "MiPassword123"
            example:
              email: "hola@8devmx.com"
              password: "MiPassword123"
      responses:
        "200":
          description: Login exitoso
          content:
            application/json:
              example:
                token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
                tipo: bearer
                expira_en: "3600 segundos"
        "401":
          description: Credenciales incorrectas
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

  /usuarios:
    get:
      summary: Listar usuarios
      tags:
        - Usuarios
      security:
        - BearerAuth: []
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: ciudad
          in: query
          description: Filtrar por ciudad
          schema:
            type: string
            example: "Cancún"
      responses:
        "200":
          description: Lista de usuarios
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/Usuario"
                  total:
                    type: integer
                    example: 150
                  page:
                    type: integer
                    example: 1

    post:
      summary: Crear usuario
      tags:
        - Usuarios
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CrearUsuario"
      responses:
        "201":
          description: Usuario creado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Usuario"
        "422":
          description: Error de validación
          content:
            application/json:
              example:
                errors:
                  email: ["El email ya está registrado"]
                  password: ["La contraseña debe tener al menos 8 caracteres"]

  /usuarios/{id}:
    get:
      summary: Obtener usuario por ID
      tags:
        - Usuarios
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
          example: 42
      responses:
        "200":
          description: Usuario encontrado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Usuario"
        "404":
          description: Usuario no encontrado
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"

    delete:
      summary: Eliminar usuario
      tags:
        - Usuarios
      security:
        - BearerAuth: []
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        "204":
          description: Usuario eliminado exitosamente
        "404":
          description: Usuario no encontrado

Swagger UI: la documentación interactiva

Swagger UI convierte tu documento YAML/JSON en una interfaz web donde puedes:

  • Ver todos los endpoints organizados por tags
  • Ver los parámetros, tipos y ejemplos de cada endpoint
  • Hacer peticiones reales directamente desde el navegador (con autenticación incluida)

Agregar Swagger UI a Laravel:

composer require darkaonline/l5-swagger
php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"

Genera la documentación:

php artisan l5-swagger:generate

Accede a ella en: http://tu-api.com/api/documentation

HTML estático (sin framework):

<!DOCTYPE html>
<html>
<head>
  <title>API Docs - 8devmx</title>
  <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist/swagger-ui.css">
</head>
<body>
  <div id="swagger-ui"></div>
  <script src="https://unpkg.com/swagger-ui-dist/swagger-ui-bundle.js"></script>
  <script>
    SwaggerUIBundle({
      url: "/openapi.yaml",  // ruta a tu archivo OpenAPI
      dom_id: '#swagger-ui',
      deepLinking: true,
    });
  </script>
</body>
</html>

Herramientas para generar documentación automáticamente

Escribir el YAML a mano es tedioso para APIs grandes. Estas herramientas ayudan:

PHPDoc + anotaciones (Laravel): El paquete l5-swagger puede leer anotaciones en los controllers y generar el YAML automáticamente:

/**
 * @OA\Get(
 *   path="/usuarios",
 *   summary="Listar usuarios",
 *   tags={"Usuarios"},
 *   @OA\Response(response=200, description="Lista de usuarios")
 * )
 */
public function index() { ... }

Postman → OpenAPI: Si ya tienes una colección de Postman, puedes exportarla directamente como OpenAPI.

Insomnia: Similar a Postman, exporta directamente a OpenAPI.

Buenas prácticas de documentación

  • Documenta los errores: No solo el happy path (200), sino también 400, 401, 403, 404, 422, 500
  • Usa ejemplos reales: Los ejemplos deben ser datos que puedan existir en producción, no “string” o “integer”
  • Organiza con tags: Agrupa los endpoints por recurso (Usuarios, Pedidos, Productos)
  • Versionea la documentación: Guarda el openapi.yaml en tu repositorio Git junto al código
  • Mantén la documentación actualizada: Desactualizada es peor que inexistente

Una API bien documentada es una señal de madurez técnica del equipo. Invierte el tiempo en hacerlo bien y te lo agradecerás (y tus compañeros también) en el futuro.