Esta es la documentación para la API del blog. Todos los endpoints están prefijados con /api.
Las rutas protegidas requieren un token de autenticación de Sanctum. Este token debe ser enviado en la cabecera de la solicitud:
Authorization: Bearer <token>
POST /api/registerCuerpo de la Solicitud (Request Body):
{
"name": "Nuevo Usuario",
"email": "nuevo@example.com",
"password": "password123",
"password_confirmation": "password123"
}
Respuesta Exitosa (201 Created):
{
"user": {
"name": "Nuevo Usuario",
"email": "nuevo@example.com",
"updated_at": "2023-10-27T10:00:00.000000Z",
"created_at": "2023-10-27T10:00:00.000000Z",
"id": 11
},
"token": "1|aBcDeFgHiJkLmNoPqRsTuVwXyZ123456"
}
POST /api/loginCuerpo de la Solicitud (Request Body):
{
"email": "test@example.com",
"password": "password"
}
Respuesta Exitosa (200 OK):
{
"user": {
"id": 1,
"name": "Usuario de Prueba",
"email": "test@example.com",
"email_verified_at": null,
"created_at": "2023-10-27T09:00:00.000000Z",
"updated_at": "2023-10-27T09:00:00.000000Z"
},
"token": "2|aBcDeFgHiJkLmNoPqRsTuVwXyZ123457"
}
Respuesta de Error (401 Unauthorized):
{
"message": "Credenciales inválidas"
}
POST /api/logoutRespuesta Exitosa (200 OK):
{
"message": "Cierre de sesión exitoso."
}
POST /api/change-passwordCuerpo de la Solicitud (Request Body):
{
"current_password": "password",
"new_password": "new_password123",
"new_password_confirmation": "new_password123"
}
Respuesta Exitosa (200 OK):
{
"message": "Contraseña cambiada exitosamente."
}
Respuesta de Error (422 Unprocessable Entity):
{
"message": "La contraseña actual es incorrecta.",
"errors": {
"current_password": [
"La contraseña actual es incorrecta."
]
}
}
GET /api/posteospage: Número de página (ej: ?page=2).sort: Ordena los resultados. Valores: latest (defecto), oldest (ej: ?sort=oldest).category_id: Filtra por el ID de una categoría (ej: ?category_id=5).titulo: Filtra los posteos buscando un texto dentro del título (búsqueda parcial). (ej: ?titulo=guia)Respuesta Exitosa (200 OK):
La respuesta ahora incluye la lista de posteos paginada en el objeto data y un objeto adicional last_post que siempre contiene el último posteo creado en toda la base de datos, sin importar los filtros aplicados.
{
"data": [
{
"id": 1,
"titulo": "Título del Posteo",
"descripcion": "Una breve descripción o resumen del posteo.",
"contenido": "Contenido del posteo...",
"fecha_publicacion": "2023-10-26T18:30:00.000000Z",
"autor": {
"id": 1,
"name": "Usuario de Prueba"
},
"categorias": [
{
"id": 5,
"nombre": "Tecnología"
}
],
"imagenes": [
{
"id": 1,
"url": "http://example.com/imagen1.jpg"
}
]
}
],
"links": {
"first": "http://localhost/api/posteos?page=1",
"last": "http://localhost/api/posteos?page=10",
"prev": null,
"next": "http://localhost/api/posteos?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"path": "http://localhost/api/posteos",
"per_page": 15,
"to": 15,
"total": 150
},
"last_post": {
"id": 500,
"titulo": "El posteo más reciente de todos",
"descripcion": "Descripción del último post...",
"contenido": "Contenido del último post...",
"fecha_publicacion": "2023-10-27T15:00:00.000000Z",
"autor": {
"id": 7,
"name": "Autor Siete"
},
"categorias": [
{
"id": 12,
"nombre": "Noticias"
}
],
"imagenes": [
{
"id": 99,
"url": "http://example.com/img99.jpg"
}
]
}
}
GET /api/posteos/{posteo}Respuesta Exitosa (200 OK):
{
"data": {
"id": 1,
"titulo": "Título del Posteo",
"descripcion": "Una breve descripción o resumen del posteo.",
"contenido": "Contenido del posteo...",
"fecha_publicacion": "2023-10-26T18:30:00.000000Z",
"autor": {
"id": 1,
"name": "Usuario de Prueba"
},
"categorias": [
{
"id": 5,
"nombre": "Tecnología"
}
],
"imagenes": [
{
"id": 1,
"url": "http://example.com/imagen1.jpg"
}
]
}
}
POST /api/posteosCuerpo de la Solicitud (Request Body):
{
"titulo": "Mi Nuevo Posteo",
"descripcion": "Esta es la descripción de mi nuevo posteo.",
"contenido": "Este es el contenido de mi nuevo posteo.",
"fecha_de_publicacion": "2023-11-15 10:00:00",
"urls_imagenes": [
"http://example.com/imagen_nueva_1.jpg",
"http://example.com/imagen_nueva_2.jpg"
],
"categorias": [1, 5]
}
Respuesta Exitosa (201 Created): (La estructura es la misma que al ver un posteo)
PUT /api/posteos/{posteo}Cuerpo de la Solicitud (Request Body): (Todos los campos son opcionales)
{
"titulo": "Título Actualizado",
"descripcion": "Descripción actualizada.",
"contenido": "Contenido actualizado.",
"urls_imagenes": [
"http://example.com/imagen_actualizada.jpg"
],
"categorias": [5, 8]
}
Respuesta Exitosa (200 OK): (La estructura es la misma que al ver un posteo)
Respuesta de Error (403 Forbidden):
{
"message": "No autorizado para realizar esta acción."
}
DELETE /api/posteos/{posteo}Respuesta Exitosa (204 No Content): (Sin cuerpo de respuesta)
GET /api/categoriasRespuesta Exitosa (200 OK):
[
{
"id": 1,
"nombre": "Viajes"
},
{
"id": 2,
"nombre": "Tecnología"
}
]
GET /api/categorias/{categoria}Respuesta Exitosa (200 OK):
{
"id": 1,
"nombre": "Viajes"
}
POST /api/categoriasCuerpo de la Solicitud (Request Body):
{
"nombre": "Gastronomía"
}
Respuesta Exitosa (201 Created):
{
"id": 21,
"nombre": "Gastronomía"
}
Respuesta de Error (422 Unprocessable Entity):
{
"message": "The nombre has already been taken.",
"errors": {
"nombre": [
"The nombre has already been taken."
]
}
}
PUT /api/categorias/{categoria}Cuerpo de la Solicitud (Request Body):
{
"nombre": "Cocina Internacional"
}
Respuesta Exitosa (200 OK):
{
"id": 21,
"nombre": "Cocina Internacional"
}
DELETE /api/categorias/{categoria}Respuesta Exitosa (204 No Content): (Sin cuerpo de respuesta)