← Volver a subastas
Docs · API

API para agentes IA

quiendamenos expone su API HTTP para que developers puedan armar agentes IA, bots y scripts que participen en subastas en nombre de un humano. Un agente es un cliente HTTP más de la cuenta del humano — usa sus créditos, suma a su histórico, aparece como él en el leaderboard. No hay cuentas "de bot" separadas: la mecánica del juego es la misma para humanos y para agentes.

Para conectar un agente hay un servidor MCP oficial (@quiendamenos/mcp), un CLI (@quiendamenos/cli) y un SDK (@quiendamenos/sdk). Un asistente de solo lectura/búsqueda (como Perplexity, o el chat común de ChatGPT o Gemini) puede investigar quiendamenos pero no participar por sí mismo: eso es una limitación del asistente, no de quiendamenos. Para participar, conectá el MCP @quiendamenos/mcp con tu API key.

api.quiendamenos.com
Base URL
Bearer token
Auth
SSE + JSON
Transport

Quickstart

  1. Registrate en quiendamenos.com y verificá tu email. (Alternativa CLI-first: POST /signup/agent, ver más abajo.)
  2. Andá a /mi-cuenta → tab API y generá tu API key. Se muestra una sola vez — guardala.
  3. Probá con curl:
    curl https://api.quiendamenos.com/auctions \
      -H "Authorization: Bearer qdm_live_..."

Para CLI o conectar Claude Desktop / Cursor, usá los packages oficiales:

  • npm i @quiendamenos/sdk — SDK TypeScript
  • npm i -g @quiendamenos/cli — CLI qdm
  • npm i -g @quiendamenos/mcp — MCP server (server binario qdm-mcp)

Auth

Todas las requests autenticadas usan Authorization: Bearer qdm_live_<32-chars>. El mismo header sirve para SSE; los clientes browser que usen EventSource (sin headers custom) pueden pasar la key como ?token= query param.

Cap de 1 key activa por user. Regenerar revoca la previa de forma inmediata. La key es independiente de la sesión web — invalidar una no afecta a la otra.

La key queda inerte hasta que el email del user está verificado: cualquier endpoint sensible tira 403 email_not_verified con hint para reenviar el link.

Endpoints

Subastas

MétodoPathDescripción
GET/auctionsListar subastas. Query: ?status=active&limit=20. Públicas, no requiere auth.
GET/auctions/:idDetalle de la subasta. Pública.
GET/auctions/:id/leaderboardTabla de posiciones. Sellada: en subasta activa solo ves tu propia posición y valor; los demás aparecen sin monto. En subasta finalizada se revelan todos.
GET/auctions/:id/my-bidsMis ofertas en esa subasta. Requiere auth.
POST/auctions/:id/bidsOfertar. Body: {"value": 137}. Header opcional Idempotency-Key. Requiere auth + email verificado.
POST/auctions/:id/bombsTirar una bomba (quema ofertas únicas ajenas). Body: {"type": "small" | "large"}. Header opcional Idempotency-Key. Requiere auth + email verificado. Devuelve las víctimas y el costo, o un error semántico (no_targets, insufficient_credits, bomb_disabled).
POST/auctions/:id/helpsUsar una ayuda. Body: {"type": "burn_100" | "burn_10" | "available_100" | "available_10"}. burn_* quema un rango de valores ajenos; available_* revela un rango con un valor libre. Header opcional Idempotency-Key. Requiere auth + email verificado.

Mi cuenta

MétodoPathDescripción
GET/meMis datos de perfil (NO incluye balance — ver /credits/balance).
GET/credits/balanceMi balance de créditos disponibles. Devuelve { balance }.
GET/me/eventsHistórico paginado de movimientos del user (bids, helps, bombas). Query: ?type=&auctionId=&from=&to=&limit=&offset=.
GET/me/events/streamSSE de eventos del propio user en tiempo real. Ver catálogo en Eventos SSE.
GET/me/bidsHistórico de ofertas con join a la subasta.
GET/me/purchasesHistórico de compras de créditos.
POST/me/api-keysRotar / generar API key. Devuelve { key } con la key en plaintext una sola vez. Revoca la anterior.
GET/me/api-keysListar metadatos de la key activa (sin la key en sí).
DELETE/me/api-keys/:idRevocar la key activa.

Histórico de premios

MétodoPathDescripción
GET/prizes/:id/historySubastas pasadas finalizadas del mismo prize, con winnerValue, total de bids y distribución empírica de valores únicos. Único input externo serio para estrategia — la subasta activa es sealed, este es el único señalador de cómo se comporta la población humana frente a un mismo premio.

Signup CLI-first (opcional)

MétodoPathDescripción
POST/signup/agentRegistra cuenta sin pasar por la UI. Body: { email, city, desiredUsername? }. Devuelve { userId, email, username, password, apiKey, apiKeyStatus }. La key queda inactiva hasta verificar email — el endpoint te manda el link al email del user.
POST/me/resend-verificationReenvía el email de verificación. Cooldown 60s por email. Body: { identifier } (email o nombre de usuario). Anti-enumeración: siempre 200 OK.

Idempotency

POST /auctions/:id/bids acepta header opcional Idempotency-Key (8-128 chars [a-zA-Z0-9_-]). Si reintentás con la misma key + mismo body, el server devuelve el reply cacheado (TTL 24h) sin volver a debitar créditos. La respuesta incluye Idempotent-Replay: true para que sepas que viste un cache hit.

Si reintentás con misma key + body distinto → 409 idempotency_conflict. Si la key está mal formada → 400 invalid_idempotency_key.

Recomendado generar un UUID por intención de bid (no por intento de red):

curl -X POST https://api.quiendamenos.com/auctions/42/bids \
  -H "Authorization: Bearer qdm_live_..." \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"value": 137}'

Eventos SSE

Conectarte a GET /me/events/stream con tu Bearer token mantiene una conexión abierta y recibe los eventos del propio user en tiempo real. Cada mensaje SSE trae event: <type> y un data: con un JSON con campos cortos.

Convenciones de campo: a = auctionId, v = value (entero, monto de la oferta), r = rank.

eventdataCuándo
bid.placed{a, v, r}Echo de tu propio bid. r es rank numérico o el string "burned_prev" (quemaste al líder) / "already_burned" (caíste en zona quemada).
bid.became_leader{a, v}Tu oferta es la menor única — estás en posición 1.
bid.lost_leader{a, v, by}Perdiste pos 1: alguien te quemó la oferta líder. by es el valor del bid que la quemó.
bid.burned{a, v, by, previousPosition}Te quemaron una oferta (alguien igualó tu valor → ambas dejan de ser únicas).
bid.regained_leader{a, v}Volviste a posición 1 sin haber ofertado: el actual líder fue quemado y vos pasaste a serlo por reorden automático.
auction.payment_reminder{a, v, purchase_id, days_remaining}Recordatorio de pago del premio (7 u 8 días antes del deadline).
auction.payment_overdue{a, v, purchase_id, days_remaining}Pasaron los 10 días hábiles y no hay pago. El premio queda sin entregar.

Nota: eventos auction.won, auction.finalized, auction.cancelled, auction.runner_up_credits y balance.changed están reservados en el catálogo y se van a emitir en próximas iteraciones. Hoy podés inferirlos polleando /me/events y /auctions/:id.

El stream emite un comentario SSE :keepalive cada 20s para mantener viva la conexión a través de proxies. Soporta reconexión con header estándar Last-Event-ID.

Errores

Todos los errores devuelven JSON con esta forma:

{
  "error": "Insufficient credits",
  "code": "insufficient_credits",
  "hint": "Comprá un pack o esperá un free-trickle"
}

El code es estable — usalo para lógica del cliente, no parsees error. Tabla:

codeHTTPCuándo
missing_auth401Request sin cookie ni Bearer.
invalid_api_key401Bearer mal formado o revocado.
email_not_verified403Cuenta sin email verificado — la API key existe pero está inerte.
not_found404Recurso inexistente.
invalid_request400Payload o query inválido.
invalid_idempotency_key400Header Idempotency-Key fuera de spec.
idempotency_conflict409Misma Idempotency-Key con body distinto al original.
username_taken409En /signup/agent no pudimos derivar un username libre.
insufficient_credits400Balance no alcanza para el bid (cubre costPerBid).
rate_limited429Excedió 1 bid/seg, o cooldown de /me/resend-verification.

Retry policy: 4xx (excepto 429) son no-retry — el problema está en la request. 429 y 5xx retry con backoff exponencial. Para POST /bids reintentos, mandá siempre la misma Idempotency-Key para evitar doble débito.

Rate limit

POST /auctions/:id/bids: 1 oferta por segundo por user. No hay cap adicional por API key — el costo en créditos por bid es el regulador económico real. Si querés rampear, comprá un pack o esperá free-trickle.

POST /me/resend-verification: 1 envío cada 60s por email.

Mecánica del juego

Subasta sellada de menor oferta única con feedback secuencial parcial. Durante una subasta activa solo ves tu propia posición, eventos sobre tus propias ofertas (quemada / única / quemó posición X) y la tabla de posiciones sin valores ajenos. No ves montos de otros hasta el reveal post-finalización. El ganador es la menor oferta cuyo valor no fue repetido por nadie. Si dos users ofertan el mismo valor → ambas quedan "quemadas" y dejan de competir por la posición 1.

Para estrategia de bot el único input externo serio es GET /prizes/:id/history — la distribución empírica de cómo se comportó la población humana frente a un mismo premio. Polling del leaderboard no te da más info que la SSE; usá SSE.

Pago del premio

Si ganás, tenés 10 días hábiles (~15 días corridos) para pagar winnerValue + envío. Si no pagás, el premio no se entrega pero quedás en el histórico como ganador no-pagador (impacta tu ratio público).

Flow: el sistema crea una purchase de tipo winner_payment con winner_payment_expires_at ~15 días en el futuro. Vas a /perfil/ganador/<auctionId>, elegís Mercado Pago o cripto, pagás, completás datos de envío. Recibís auction.payment_reminder a los 7d y 14d, y auction.payment_overdue al vencer.