Descuentazos

API pública

Descuentazos permite publicar ofertas y cupones programáticamente. El flujo tiene dos pasos: canjeás tu API key por un token corto y usás ese token contra la API de ofertas.

1. Canjeá tu API key por un token

Los tokens duran 1 hora y llevan el scope deals:write.

curl
curl -X POST https://auth.descuentazos.example/v1/auth/token \
  -H "Content-Type: application/json" \
  -d '{"apiKey": "dk_live_TU_API_KEY"}'

# → {"accessToken": "eyJ...", "expiresIn": 3600, "tokenType": "api_key", "scopes": ["deals:write"]}

2. Publicá una oferta

curl
curl -X POST https://api.descuentazos.example/v1/deals \
  -H "Authorization: Bearer eyJ..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.fravega.com/p/heladera-x",
    "title": "Heladera X 300L a mitad de precio",
    "description": "Precio histórico, envío gratis a todo el país",
    "price": 499999,
    "originalPrice": 999999,
    "categorySlug": "electrodomesticos",
    "store": "Frávega"
  }'

3. Publicá un cupón

Una oferta es un link cuyo precio ya bajó; un cupón es un código que se pega al pagar. No lleva link, ni precio, ni título: lleva una tienda, un código, un beneficio y una fecha de vencimiento. No entra a los feeds ni a la búsqueda —su lugar es la pantalla de la tienda y el detalle de sus ofertas—.

curl
curl -X POST https://api.descuentazos.example/v1/coupons \
  -H "Authorization: Bearer eyJ..." \
  -H "Content-Type: application/json" \
  -d '{
    "storeSlug": "fravega",
    "code": "FRAVE30",
    "benefitKind": "percent",
    "benefitValue": 30,
    "capAmount": 15000,
    "minPurchase": 50000,
    "conditions": "No acumulable con otras promociones",
    "expiresAt": "2026-10-31T23:59:59Z"
  }'

Reglas

  1. 01Título: 8–140 caracteres. Descripción: mínimo 5 palabras.
  2. 02categorySlug: consultá GET /v1/categories.
  3. 03discountLabel: opcional, la etiqueta de descuento tal como la muestra la tienda («31% OFF»). Se usa solo si no mandás originalPrice para calcularlo.
  4. 04Cupo de publicación por cuenta: un mínimo de espera entre ofertas, un tope por hora y otro por día. Las ventanas son móviles — cada oferta libera su lugar 24h después, no a medianoche. Ver Límites.
  5. 05URLs duplicadas activas devuelven 409.
  6. 06Las ofertas creadas por API quedan marcadas con source: api.
  7. 07expiresAt es obligatorio en un cupón y opcional en una oferta, y no puede pasar de un año: un cupón sin fecha es un cupón que va a mentir.
  8. 08capAmount es el tope de reintegro («30% OFF con tope de $15.000») y sólo va con benefitKind: percent. Sobre un monto fijo el tope sería el descuento diciéndose a sí mismo, y los otros dos tipos no tienen magnitud que acotar.
  9. 09La tienda de un cupón tiene que estar en el catálogo: su única casa es la pantalla de esa tienda, y esa pantalla se direcciona por slug.
  10. 10Códigos de referido: no se aceptan. Un cupón es de la tienda, no de una persona. No se pueden detectar por su forma, así que la regla se aplica con los reportes de abuso —y una key que los publique es una key que se revoca—.
  11. 11El token sólo sirve para publicar: POST /v1/deals y POST /v1/coupons. Editar o borrar lo publicado, votar, comentar, decir si un código funcionó y todo lo de la cuenta se hace desde la app, y responden 403 a una API key —incluso sobre lo que esa key publicó—. Las lecturas (feeds, búsqueda, categorías, cupones) son públicas y no piden token.

Límites

Hay dos límites distintos, y los dos responden 429 con el mismo code: rate_limited. Lo que los diferencia es un campo:

  1. 01Frecuencia: requests por minuto, en todos los endpoints. Trae Retry-After: 60 y no trae retryAfterSeconds. El canje de API key (/v1/auth/token) es el más bajo: canjeala una vez y reusá el token la hora que dura.
  2. 02Cupo de publicación: sólo en POST /v1/deals. Trae Retry-After con el plazo exacto y el mismo número en retryAfterSeconds. POST /v1/coupons no tiene cupo propio: los códigos vivos de una tienda son un puñado, y el mismo código no se puede cargar dos veces.

Es decir: ante un 429 sin retryAfterSeconds, reintentar más lento alcanza. Con él, hay que esperar el plazo que indica.

HTTP/1.1 429 Too Many Requests
Retry-After: 40

{"error": {"code": "rate_limited", "message": "..."}, "retryAfterSeconds": 40}

Errores

Todas las respuestas de error usan el mismo envelope:

{"error": {"code": "...", "message": "..."}}
El uso de la API se rige por los Términos y condicionesTérminos y condiciones →