API REST · v1

LMCS Social

Una red social sencilla tipo Instagram: usuarios, fotos, comentarios, likes y seguidores. Úsala desde cualquier página web con fetch().

URL base:

Inicio rápido

Todas las respuestas son JSON. Puedes llamar a la API desde cualquier sitio (CORS abierto). Prueba esto en la consola de tu navegador:

const API = '';

// 1. Crear una cuenta (devuelve un token)
const res = await fetch(`${API}/api/auth/signup`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ username: 'ana', password: 'secreto123', name: 'Ana' }),
});
const { token, user } = await res.json();

// 2. Usar el token en las demás peticiones
const feed = await fetch(`${API}/api/feed`, {
  headers: { Authorization: `Bearer ${token}` },
}).then((r) => r.json());

console.log(user, feed.posts);

Registro, login y token

Al registrarte o iniciar sesión recibes un token. Guárdalo (por ejemplo en localStorage) y envíalo en cada petición que lo requiera:

Authorization: Bearer <token>
// Login
const { token } = await fetch(`${API}/api/auth/login`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ username: 'ana', password: 'secreto123' }),
}).then((r) => r.json());

Todos los endpoints

Las listas de posts aceptan ?limit=20 (máx. 50) y ?before=<id> para "cargar más": cada respuesta trae nextBefore, que pasas como before en la siguiente petición (null = no hay más).

Publicar una foto

Opción A: con un enlace a una imagen

await fetch(`${API}/api/posts`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
  body: JSON.stringify({ caption: 'Atardecer 🌅', imageUrl: 'https://picsum.photos/800' }),
});

Opción B: subiendo un archivo (desde un <input type="file">)

const form = new FormData();
form.append('image', document.querySelector('input[type=file]').files[0]); // JPG, PNG, GIF o WebP, máx. 5 MB
form.append('caption', 'Mi foto');

await fetch(`${API}/api/posts`, {
  method: 'POST',
  headers: { Authorization: `Bearer ${token}` }, // ¡sin Content-Type! el navegador lo pone solo
  body: form,
});

Like, comentario y seguir

const auth = { Authorization: `Bearer ${token}` };

await fetch(`${API}/api/posts/12/like`, { method: 'POST', headers: auth });      // dar like
await fetch(`${API}/api/posts/12/like`, { method: 'DELETE', headers: auth });    // quitar like

await fetch(`${API}/api/posts/12/comments`, {
  method: 'POST',
  headers: { ...auth, 'Content-Type': 'application/json' },
  body: JSON.stringify({ text: '¡Qué buena foto!' }),
});

await fetch(`${API}/api/users/luis/follow`, { method: 'POST', headers: auth });   // seguir
await fetch(`${API}/api/users/luis/follow`, { method: 'DELETE', headers: auth }); // dejar de seguir

Formato de las respuestas

Post

{
  "id": 12,
  "caption": "Atardecer 🌅",
  "imageUrl": "https://…/uploads/3f9c….jpg",
  "createdAt": "2026-11-12T17:00:00.000Z",
  "author": {
    "id": 3, "username": "ana",
    "name": "Ana", "avatarUrl": null
  },
  "likeCount": 4,
  "commentCount": 2,
  "likedByMe": true
}

Perfil (GET /api/users/:username)

{
  "id": 3, "username": "ana", "name": "Ana",
  "bio": "Hola 📸", "avatarUrl": null,
  "createdAt": "2026-11-12T16:00:00.000Z",
  "stats": { "posts": 5, "followers": 10, "following": 7 },
  "isMe": false,
  "isFollowing": true,
  "followsYou": false
}

Comentario

{
  "id": 40, "postId": 12, "text": "¡Genial!",
  "createdAt": "…",
  "author": { "id": 5, "username": "luis", … }
}

Listas: { "posts": [...], "nextBefore": 11 }, { "users": [...] }, { "comments": [...] }.

Errores y límites

Si algo sale mal, la respuesta tiene un código HTTP de error y un mensaje en español:

// HTTP 409
{ "error": "El usuario \"ana\" ya existe. Elige otro." }
400Datos inválidos (falta un campo, texto muy largo, imagen no válida…)
401Falta el token, expiró o el usuario/contraseña es incorrecto
403No tienes permiso (por ejemplo, borrar el post de otra persona)
404No existe (usuario, post, comentario o endpoint)
409Ese nombre de usuario ya está tomado
413Imagen de más de 5 MB
429Demasiadas peticiones: espera un poco