Tres endpoints de solo lectura para navegar el catálogo. Sobre Turso, sincronizado diario. Los mismos datos manejan las páginas humanas en /catalog.
GET/api/v1/catalog
brand
string
filtrar por id de marca (e.g. amazon-mexico)
category
string
nombre de categoría (e.g. Tienda)
q
string
búsqueda libre sobre nombre + descripción
type
enum
text · qr · url · combo · card
limit
integer
1–500, default 100
cursor
string
cursor de paginación (basado en sku)
{
"items": [
{
"id": "01HZ...",
"sku": "amazon-mexico-300",
"brandId": "amazon-mexico",
"amount": 30000,
"redemptionType": "text",
"currency": "MXN",
"active": true,
"brand": { "id": "amazon-mexico", "name": "Amazon México", "image": "https://..." }
},
...
],
"next_cursor": null,
"count": 28
}GET/api/v1/brands/{id}
Devuelve toda la metadata de la marca (términos, ubicaciones, vigencia) más todos los SKUs activos.
{
"brand": {
"id": "cinepolis",
"name": "Cinépolis",
"description": "Boleto Tradicional 2D",
"validityDescription": "30 días después de la compra",
"redemptionType": "text",
"terms": "<p>...</p>",
...
},
"items": [ { "sku": "cinepolis-entrada-tradicional-52", "amount": 5200 }, ... ]
}GET/api/v1/items/{sku}
{
"item": { "id": "01HZ...", "sku": "netflix-300", "amount": 30000, ... },
"brand": { "id": "netflix", "name": "Netflix", "redemptionType": "text", ... }
}El catálogo se actualiza con un Vercel Cron a las 09:00 UTC diario (03:00 CDMX). Los SKUs eliminados quedan en la DB con active=false — no aparecen en listas pero las órdenes históricas siguen resolviendo.