Ir al contenido
howmuchuserswtf
Entrar
← Documentación

Referencia completa

Todo lo que hay. Tres rutas, sin SDK — lo que sigue es el contrato exacto que ya cumple el código, no un resumen.

Autenticación

La clave va en la cabecera, de cualquiera de las dos formas:

Authorization: Bearer hmu_sk_live_9f3ac1d2_...X-HMU-Key: hmu_sk_live_9f3ac1d2_...

La segunda existe para entornos donde un proxy ya usa "Authorization" para otra cosa.

hmu_pk_live_…hmu_sk_live_…
Dónde viveEn el navegador. Es pública por definición.Sólo en tu servidor.
Puede mandarpage.viewed, session.started, eventos personalizadosTodo lo de la pública, más user.created, user.deleted, user.activated, subscription.*
Puede importarNo

La distinción no es una convención: está en el código. Un user.created mandado con clave pública se rechaza con secret_key_required y queda anotado como señal para revisión — es lo que hace que el número publicado en un ranking no sea "lo que cualquier visitante quiso que fuera".

La clave secreta se muestra una sola vez, al crearla. En nuestra base sólo está su hash.

POST /v1/events

Un evento
{ "event": "user.created", "user_id": "usr_123", "created_at": "2026-08-08T20:00:00Z" }
O hasta 100 de una
{ "events": [ { "event": "user.created", "user_id": "usr_123" }, … ] }

Campos

CampoTipoNotas
eventrequeridoMinúsculas, hasta tres niveles: checkout.completed. No puede empezar con user., subscription. ni hmu. salvo que sea uno de los nuestros.
user_idrequerido para eventos de usuarioUn id estable y no personal. Lo hasheamos antes de guardarlo, pero mandar emails igual está mal: no los necesitamos.
created_atopcionalISO 8601. Si falta, ahora. Se acepta 2026-08-08 (se ancla al mediodía UTC).
idempotency_keyopcionalSi reintentás, el evento no se cuenta dos veces.
propsopcionalObjeto plano, hasta 20 claves, valores simples. No mandes datos personales acá.

Respuesta — 202

{ "accepted": 97, "duplicated": 2, "rejected": [ { "index": 4, "code": "missing_user_id", "message": "…" } ] }

Un evento malo no tira el lote. Se aceptan los buenos y se devuelve el detalle de cada rechazado con su índice. Si el lote entero fallara, tu reintento volvería a fallar por el mismo evento, para siempre.

Códigos de rechazo por evento

codeQué pasó
secret_key_requiredUn evento autoritativo con clave pública.
missing_user_idFalta user_id en un evento que lo necesita.
future_timestampcreated_at en el futuro. Mirá el reloj del servidor.
timestamp_too_oldMás de 10 años atrás. Para historia, usá la importación.
reserved_event_nameEl nombre pisa uno reservado.
invalid_eventNo cumple el esquema (el mensaje dice qué campo).

Errores de la petición entera

401 invalid_key · 403 project_inactive · 413 payload_too_large · 429 rate_limited (con Retry-After) · 400 invalid_request

Eventos que entendemos

user.created · user.deleted · user.activated · subscription.started · subscription.cancelled · session.started · page.viewed · los tuyos.

session.started es lo que alimenta los activos diarios/semanales/mensuales; page.viewed no mueve esa métrica a propósito (una sesión son decenas de vistas).

POST /v1/users/import

Los usuarios que ya tenías antes de instalarnos. Sólo con clave secreta, hasta 1.000 por pedido, 5 pedidos por hora.

{ "users": [ { "user_id": "usr_1", "created_at": "2025-11-03" } ] }

Respuesta 202: { "imported": 843, "duplicated": 12, "failed": 0 }

Quedan marcados como importados, para siempre: suman a tu total y se dice en tu perfil, pero no cuentan para los rankings de crecimiento ni para el mínimo de usuarios observados que pide la elegibilidad. Es lo que evita que importar mil usuarios inventados sea el camino corto al primer puesto.

GET /v1/status

Para confirmar que la clave anda y que estamos recibiendo.

{
  "project": { "id": "…", "slug": "plata", "name": "Plata" },
  "key": { "kind": "secret", "prefix": "hmu_sk_live_9f3ac1d2" },
  "live": true,
  "last_event_at": "2026-08-08T20:14:02Z",
  "total_users": 1284,
  "today": { "accepted": 312, "rejected": 0, "duplicated": 4, "last_error": null }
}

Embebibles

No necesitan clave: dibujan sólo lo que el dueño publicó.

GET /api/badge/<slug>.svg?theme=dark|light|neon|minimal&lang=en|es
GET /api/counter/<slug>.svg?theme=…&lang=…

El HTML que hay que pegar sale del panel, y lleva el enlace de vuelta con atribución (/r/b/<slug>). Ese enlace es lo que permite saber que una visita vino de ESE badge — y no "de ningún lado", que es como se ve el tráfico de badges sin él.

Límites

Límite
Eventos con clave secreta600 pedidos/min por proyecto
Eventos con clave pública120 pedidos/min por proyecto
Importación5 pedidos/hora
Cuerpo de /v1/events256 KB
Eventos por pedido100

Al pasarse: 429 con Retry-After en segundos. Agrupá eventos en lotes antes de subir la frecuencia.

Privacidad

No queremos —ni guardamos— nombres, emails, teléfonos ni direcciones de tus usuarios. El user_id que mandás se convierte en un hash irreversible, distinto para cada proyecto, antes de tocar la base. Medimos productos, no personas.

Platawtf1 KFrambuesa97