{"openapi":"3.0.3","info":{"title":"API de Whatsup","version":"1.0.0","description":"Para conectar Whatsup con tu tienda, tu ERP o lo que ya uses.\n\nLa clave va en la cabecera `X-API-Key`. Se crea en Ajustes > Integraciones y se\nenseña una sola vez: de la clave solo guardamos una huella, así que no se puede\nrecuperar.\n\nCupo: 120 peticiones por minuto y clave, y\n300 por minuto y dirección. Cada respuesta\ntrae `RateLimit-Remaining`, así que puedes frenar tú antes de que te frenemos.\n\nLos errores llegan siempre igual: `{ \"error\": { \"codigo\", \"mensaje\" } }`. Compara\nel código, no el mensaje."},"servers":[{"url":"https://api.whatsup.avanc3.pe/v1"}],"security":[{"ClaveDeApi":[]}],"components":{"securitySchemes":{"ClaveDeApi":{"type":"apiKey","in":"header","name":"X-API-Key","description":"También se admite `Authorization: Bearer <clave>`."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}},"Conversacion":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"estado":{"type":"string","enum":["open","bot","pending","resolved"],"description":"`bot` la atiende el agente de IA, `pending` espera a una persona, `resolved` está cerrada."},"agenteAsignado":{"type":"string","format":"uuid","nullable":true},"cliente":{"type":"object","properties":{"telefono":{"type":"string","example":"51917919061"},"nombre":{"type":"string","nullable":true}}},"ultimoMensajeEn":{"type":"string","format":"date-time","nullable":true},"creadaEn":{"type":"string","format":"date-time"}}},"Mensaje":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sentido":{"type":"string","enum":["entrante","saliente"]},"tipo":{"type":"string","enum":["text","image","document","audio","video"]},"contenido":{"type":"string"},"estado":{"type":"string","enum":["sent","delivered","read","failed"]},"creadoEn":{"type":"string","format":"date-time"}}},"Cliente":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"telefono":{"type":"string"},"nombre":{"type":"string","nullable":true},"creadoEn":{"type":"string","format":"date-time"}}}}},"paths":{"/ping":{"get":{"summary":"Comprobar que la clave funciona","description":"No cambia nada. Es lo primero que conviene probar al integrar.","responses":{"200":{"description":"La clave vale y esta es la empresa a la que pertenece.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"empresa":{"type":"object","properties":{"id":{"type":"string"},"nombre":{"type":"string","nullable":true}}},"momento":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Falta la clave o no vale.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}},"429":{"description":"Se pasó del cupo: 120 peticiones por minuto y clave.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}}}}},"/conversaciones":{"get":{"summary":"Listar conversaciones","description":"De la que tuvo actividad más reciente a la más antigua.","parameters":[{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Cuántos elementos devolver."},{"name":"desde","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Cuántos saltar. Para la página siguiente, súmale el límite."},{"name":"estado","in":"query","schema":{"type":"string","enum":["open","bot","pending","resolved"]},"description":"Para quedarse solo con las que están en ese estado."}],"responses":{"200":{"description":"Las conversaciones.","content":{"application/json":{"schema":{"type":"object","properties":{"datos":{"type":"array","items":{"$ref":"#/components/schemas/Conversacion"}},"paginacion":{"type":"object","properties":{"limite":{"type":"integer"},"desde":{"type":"integer"}}}}}}}},"401":{"description":"Falta la clave o no vale.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}},"429":{"description":"Se pasó del cupo: 120 peticiones por minuto y clave.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}}}}},"/conversaciones/{id}/mensajes":{"get":{"summary":"Listar los mensajes de una conversación","description":"Del más antiguo al más reciente, que es como se lee una conversación.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Cuántos elementos devolver."},{"name":"desde","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Cuántos saltar. Para la página siguiente, súmale el límite."}],"responses":{"200":{"description":"Los mensajes.","content":{"application/json":{"schema":{"type":"object","properties":{"datos":{"type":"array","items":{"$ref":"#/components/schemas/Mensaje"}},"paginacion":{"type":"object","properties":{"limite":{"type":"integer"},"desde":{"type":"integer"}}}}}}}},"401":{"description":"Falta la clave o no vale.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}},"404":{"description":"No existe, o no es de tu empresa. No se distingue a propósito.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}},"429":{"description":"Se pasó del cupo: 120 peticiones por minuto y clave.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}}}}},"/clientes":{"get":{"summary":"Listar los clientes que han escrito","parameters":[{"name":"limite","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Cuántos elementos devolver."},{"name":"desde","in":"query","schema":{"type":"integer","minimum":0,"default":0},"description":"Cuántos saltar. Para la página siguiente, súmale el límite."},{"name":"telefono","in":"query","schema":{"type":"string"},"description":"Para buscar uno concreto. Los símbolos y espacios se ignoran."}],"responses":{"200":{"description":"Los clientes.","content":{"application/json":{"schema":{"type":"object","properties":{"datos":{"type":"array","items":{"$ref":"#/components/schemas/Cliente"}},"paginacion":{"type":"object","properties":{"limite":{"type":"integer"},"desde":{"type":"integer"}}}}}}}},"401":{"description":"Falta la clave o no vale.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}},"429":{"description":"Se pasó del cupo: 120 peticiones por minuto y clave.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}}}}},"/mensajes":{"post":{"summary":"Mandar un mensaje de texto","description":"A una conversación que ya existe. No se puede empezar una desde aquí, y no es\nlimitación nuestra: WhatsApp solo deja escribir texto libre a quien te escribió\nen las últimas 24 horas. Para dirigirte a alguien que no ha escrito hace falta\nuna plantilla aprobada, que es lo que hacen las campañas.\n\nEl mensaje no se atribuye a nadie del equipo: lo manda un programa, y ponerle el\nnombre de una persona falsearía quién contestó.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"telefono":{"type":"string","description":"Con código de país. Los símbolos se ignoran.","example":"51917919061"},"conversacionId":{"type":"string","format":"uuid","description":"Alternativa al teléfono, si ya la tienes."},"texto":{"type":"string","maxLength":4096}},"required":["texto"]},"examples":{"porTelefono":{"summary":"Por teléfono","value":{"telefono":"51917919061","texto":"Tu pedido ya salió"}},"porConversacion":{"summary":"Por conversación","value":{"conversacionId":"0f2f7c99-efca-4126-9049-ee193cbdc64e","texto":"Tu pedido ya salió"}}}}}},"responses":{"201":{"description":"Aceptado y entregado a WhatsApp.","content":{"application/json":{"schema":{"type":"object","properties":{"datos":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"conversacionId":{"type":"string","format":"uuid"},"estado":{"type":"string","example":"sent"}}}}}}}},"401":{"description":"Falta la clave o no vale.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}},"404":{"description":"`sin_conversacion`: ese número no ha escrito nunca, o no en esta cuenta. `no_encontrada`: esa conversación no existe o no es tuya.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}},"429":{"description":"Se pasó del cupo: 120 peticiones por minuto y clave.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"codigo":{"type":"string","description":"Estable. Es lo que hay que comparar en el código."},"mensaje":{"type":"string","description":"Para leer. Puede cambiar de redacción."}},"required":["codigo","mensaje"]}}}}}}}}}},"x-webhooks":{"descripcion":"Además de que preguntes, podemos avisarte. Se configura en Ajustes >\nIntegraciones. Mandamos un POST con `{ evento, entregaId, emitidoEn, datos }`.\n\nCada aviso lleva la cabecera `x-whatsup-firma` con el formato\n`t=<segundos>,v1=<hmac>`, donde el hmac es SHA-256 de `<t>.<cuerpo crudo>` con el\nsecreto de esa dirección. Comprueba la firma y descarta lo que venga con una `t`\nde hace más de cinco minutos: sin eso, cualquiera que adivine tu URL puede\ninventarte mensajes.\n\n`entregaId` se repite en los reintentos. Úsalo para no procesar dos veces lo mismo.","eventos":["mensaje.recibido","mensaje.enviado","mensaje.estado","conversacion.asignada","conversacion.resuelta"]}}