Documentación & Modelos para la App Android en Kotlin

Endpoints REST para la App Móvil Android

Esta API entrega las noticias limpias, categorizadas y paginadas. Diseñada para consumo mediante Retrofit o Ktor en Kotlin.

Abrir Swagger OpenAPI (/docs)

Endpoints Principales

GET /api/v1/news
Listado paginado (?page=1&limit=20&category=Seguridad&q=alcalde)
GET /api/v1/news/{id}
Detalle con cuerpo completo HTML y texto plano
GET /api/v1/categories
Categorías activas con conteo de noticias
GET /health
Healthcheck del contenedor (Dokploy / Docker)

Modelos Kotlin (data class) para Android

package cl.puentealto.app.data.model

import com.google.gson.annotations.SerializedName

// Modelo para la lista de noticias (RecyclerView / Jetpack Compose)
data class NewsArticle(
    @SerializedName("id") val id: Int,
    @SerializedName("guid") val guid: String,
    @SerializedName("title") val title: String,
    @SerializedName("slug") val slug: String?,
    @SerializedName("excerpt") val excerpt: String?,
    @SerializedName("original_url") val originalUrl: String,
    @SerializedName("image_url") val imageUrl: String?,
    @SerializedName("source_code") val sourceCode: String,
    @SerializedName("source_name") val sourceName: String,
    @SerializedName("category") val category: String,
    @SerializedName("author") val author: String?,
    @SerializedName("published_at") val publishedAt: String,
    @SerializedName("is_featured") val isFeatured: Boolean,
    @SerializedName("views_count") val viewsCount: Int
)

// Respuesta paginada de la API
data class NewsResponse(
    @SerializedName("total") val total: Int,
    @SerializedName("page") val page: Int,
    @SerializedName("limit") val limit: Int,
    @SerializedName("total_pages") val totalPages: Int,
    @SerializedName("has_next") val hasNext: Boolean,
    @SerializedName("items") val items: List<NewsArticle>
)

// Interfaz Retrofit para Android
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface PuenteAltoNewsApi {
    @GET("api/v1/news")
    suspend fun getNews(
        @Query("page") page: Int = 1,
        @Query("limit") limit: Int = 20,
        @Query("category") category: String? = null,
        @Query("source") source: String? = null,
        @Query("q") query: String? = null,
        @Query("featured") featured: Boolean? = null
    ): NewsResponse

    @GET("api/v1/news/{id}")
    suspend fun getNewsDetail(
        @Path("id") articleId: Int
    ): NewsArticle
}