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>
- username: 3 a 30 caracteres, minúsculas, números,
_o. - password: mÃnimo 6 caracteres.
- El token dura 30 dÃas.
POST /api/auth/logoutlo invalida. - Los endpoints marcados con 🔒 necesitan el token. Los demás funcionan sin él (pero si lo envÃas, verás campos como
likedByMe).
// 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." }
| 400 | Datos inválidos (falta un campo, texto muy largo, imagen no válida…) |
| 401 | Falta el token, expiró o el usuario/contraseña es incorrecto |
| 403 | No tienes permiso (por ejemplo, borrar el post de otra persona) |
| 404 | No existe (usuario, post, comentario o endpoint) |
| 409 | Ese nombre de usuario ya está tomado |
| 413 | Imagen de más de 5 MB |
| 429 | Demasiadas peticiones: espera un poco |
- Caption: máx. 2.200 caracteres. Comentario: máx. 1.000. Bio: máx. 150. Nombre: máx. 50.
- Máximo 60 posts y 200 comentarios por usuario por hora.
- Un post solo lo puede borrar su autor. Un comentario lo puede borrar su autor o el autor del post.