Acortador de URLs como Bitly. El usuario registra una URL larga, elige un slug personalizado y recibe un enlace corto. Cada visita redirige automáticamente y suma un clic al contador.
users| Campo | Tipo | Notas |
|---|---|---|
id | UUID | PK, auto-generado |
email | TEXT | UNIQUE, NOT NULL |
password_hash | TEXT | NOT NULL. Almacenar hash (bcrypt/argon2) |
created_at | DATETIME | DEFAULT NOW |
links| Campo | Tipo | Notas |
|---|---|---|
id | UUID | PK, auto-generado |
user_id | UUID | FK → users.id, NOT NULL |
slug | TEXT | UNIQUE, NOT NULL |
original_url | TEXT | NOT NULL |
enabled | BOOL | DEFAULT true |
clicks | INT | DEFAULT 0 |
created_at | DATETIME | DEFAULT NOW |
updated_at | DATETIME | DEFAULT NOW |
/api/auth/register público
{ // Request
"email": "user@example.com",
"password": "mipass"
}
// Response 201
{ "id": "uuid", "email": "user@example.com" }
// Error 409 — email ya registrado
/api/auth/login público
{ // Request
"email": "user@example.com",
"password": "mipass"
}
// Response 200
{ "token": "jwt...", "user": { "id": "uuid", "email": "user@example.com" } }
// Error 401 — credenciales inválidas
Todos requieren Authorization: Bearer <token>
/api/links auth
{ // Request
"url": "https://ejemplo.com/articulo/muy/largo",
"slug": "mislug"
}
// Response 201
{
"id": "uuid",
"slug": "mislug",
"short_url": "https://go.innovaisoft.com/mislug",
"original_url": "https://ejemplo.com/articulo/muy/largo",
"clicks": 0
}
// Error 409 — slug ya existe
/api/links auth
// Response 200 — lista de links del usuario autenticado
[
{
"id": "uuid",
"slug": "mislug",
"original_url": "https://ejemplo.com/articulo/muy/largo",
"enabled": true,
"clicks": 42,
"created_at": "2025-10-06T..."
}
]
/api/links/{id} auth
{ // Request (ambos campos opcionales)
"url": "https://nueva-url.com",
"slug": "nuevo-slug"
}
// Response 200 — link actualizado
// Error 409 — slug ya ocupado
/api/links/{id} auth
// Response 204 — sin contenido
/api/links/{id}/toggle auth
// Response 200
{ "id": "uuid", "enabled": false }
Cualquier visita a GET /{slug} (sin auth) se resuelve así:
| Situación | Código | Respuesta |
|---|---|---|
✅ Slug existe + enabled: true | 302 | Redirige a la URL original. Contador +1. |
🔧 Slug existe + enabled: false | 200 | Página HTML "Enlace en mantenimiento" |
| ❌ Slug no existe | 404 | Página HTML 404 personalizada |
innovaisoft.comgo.innovaisoft.com o inn.innovaisoft.comBASE_URL)| Componente | Destino |
|---|---|
| API (.NET + SQLite) | Dokploy (contenedor Docker) |
| Web Client | Cloudflare Pages (estático) |
| Spec HTML | Cloudflare Pages (vista previa) |
Innova IA Soft — Spec v1.0 — Octubre 2025