Webhook compatible con Twilio WhatsApp Business API.
- Crea una cuenta en Twilio y activa el Sandbox de WhatsApp (gratuito) o solicita un número WhatsApp Business.
- En la configuración del Sandbox / número, en «When a message comes in», pega esta URL como webhook POST:
https://gtfs-rt-arroyoencomienda.lovable.app/api/public/whatsapp/webhookUna vez configurado, envía por WhatsApp el número o nombre de una parada (p. ej. 100) y recibirás las próximas llegadas con la ubicación del bus.
Siri (Atajos de iOS)
Crea un atajo personal para preguntar a Siri.
- Abre la app Atajos en tu iPhone y crea un nuevo atajo.
- Añade la acción «Pedir entrada» con el texto «¿Qué parada?».
- Añade «Obtener contenido de URL»:
- Método:
GET - URL:
https://gtfs-rt-arroyoencomienda.lovable.app/api/public/voice/stop?q=+ Entrada proporcionada
- Método:
- Añade «Obtener valor del diccionario» y elige la clave
speech. - Termina con «Hablar texto». Renombra el atajo a «Próximo bus» y di a Siri: «Próximo bus».
https://gtfs-rt-arroyoencomienda.lovable.app/api/public/voice/stop?q=100ProbarAmazon Alexa
Endpoint para una skill personalizada en la Alexa Developer Console.
- Entra en developer.amazon.com/alexa/console/ask y crea una skill Custom en español, con hosting «Provision your own».
- En Endpoint → HTTPS, pega esta URL:
https://gtfs-rt-arroyoencomienda.lovable.app/api/public/alexa/skill- Selecciona el certificado «My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority».
- En Interaction Model → JSON Editor, pega este modelo de intents:
{
"interactionModel": {
"languageModel": {
"invocationName": "arroyo bus",
"intents": [
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.YesIntent",
"samples": []
},
{
"name": "AMAZON.NoIntent",
"samples": []
},
{
"name": "AMAZON.RepeatIntent",
"samples": []
},
{
"name": "AMAZON.FallbackIntent",
"samples": []
},
{
"name": "AMAZON.NavigateHomeIntent",
"samples": []
},
{
"name": "ParadaIntent",
"slots": [
{
"name": "parada",
"type": "AMAZON.SearchQuery"
}
],
"samples": [
"próximo bus en la parada {parada}",
"cuándo llega el bus a {parada}",
"parada {parada}",
"qué buses pasan por {parada}",
"consulta la parada {parada}"
]
},
{
"name": "LineaParadaIntent",
"slots": [
{
"name": "linea",
"type": "LINEA"
},
{
"name": "parada",
"type": "PARADA"
}
],
"samples": [
"cuándo pasa la línea {linea} por {parada}",
"cuándo llega la {linea} a {parada}",
"próxima {linea} en {parada}",
"cuándo pasa la {linea}"
]
},
{
"name": "DondeLineaIntent",
"slots": [
{
"name": "linea",
"type": "LINEA"
}
],
"samples": [
"dónde está la línea {linea}",
"dónde va la {linea}",
"por dónde va el {linea}"
]
},
{
"name": "BusesActivosIntent",
"slots": [
{
"name": "linea",
"type": "LINEA"
}
],
"samples": [
"cuántos buses hay circulando",
"cuántos autobuses hay",
"hay buses ahora",
"cuántos buses de la {linea} hay"
]
},
{
"name": "AvisosIntent",
"samples": [
"hay avisos",
"hay incidencias",
"hay algún problema",
"cómo va el servicio",
"hay retrasos"
]
},
{
"name": "LineasIntent",
"samples": [
"qué líneas hay",
"qué líneas tiene arroyo bus",
"dime las líneas"
]
},
{
"name": "TarifasIntent",
"samples": [
"cuánto cuesta el billete",
"precio del bus",
"tarifas",
"cuánto vale el autobús"
]
},
{
"name": "BuscylIntent",
"samples": [
"qué es la tarjeta buscyl",
"cómo consigo la buscyl",
"tarjeta buscyl",
"abono"
]
},
{
"name": "ComoLlegarIntent",
"slots": [
{
"name": "destino",
"type": "AMAZON.SearchQuery"
}
],
"samples": [
"cómo voy a {destino}",
"cómo llego a {destino}",
"cómo ir a {destino}",
"combinar con auvasa para ir a {destino}"
]
},
{
"name": "BuhoIntent",
"samples": [
"horario del búho",
"a qué hora pasa el búho",
"bus nocturno"
]
},
{
"name": "TelefonoIntent",
"samples": [
"teléfono de atención",
"a quién llamo",
"número de teléfono"
]
},
{
"name": "PeticionIntent",
"samples": [
"la petición de change",
"qué es la petición",
"recogida de firmas"
]
},
{
"name": "RefrescarIntent",
"samples": [
"actualiza",
"otra vez",
"vuelve a consultar"
]
}
],
"types": [
{
"name": "PARADA",
"values": [
{
"name": {
"value": "Estación de Autobuses de Valladolid",
"synonyms": [
"1"
]
}
},
{
"name": {
"value": "Paseo de Zorrilla 130 junto El Corte Inglés",
"synonyms": [
"2"
]
}
},
{
"name": {
"value": "Avenida de Medina del Campo esquina Centro de Salud",
"synonyms": [
"3"
]
}
},
{
"name": {
"value": "Avenida de Salamanca junto Cash IFA",
"synonyms": [
"4"
]
}
},
{
"name": {
"value": "Calle Federación de Fútbol",
"synonyms": [
"5"
]
}
},
{
"name": {
"value": "Avenida de Colón 175 frente pistas polideportivas",
"synonyms": [
"6"
]
}
},
{
"name": {
"value": "Avenida de Colón 132",
"synonyms": [
"7"
]
}
},
{
"name": {
"value": "Avenida de Colón frente Multiusos de la Vega",
"synonyms": [
"8"
]
}
},
{
"name": {
"value": "Paseo de Juan Carlos I",
"synonyms": [
"9"
]
}
},
{
"name": {
"value": "Avenida de José Luís Lasa 27",
"synonyms": [
"10"
]
}
},
{
"name": {
"value": "Avenida de José Luis Lasa junto Glorieta de la Flecha",
"synonyms": [
"11"
]
}
},
{
"name": {
"value": "Calle Presentación junto La Vaca",
"synonyms": [
"12"
]
}
},
{
"name": {
"value": "Calle Ramón y Cajal frente edificio ADE",
"synonyms": [
"13"
]
}
},
{
"name": {
"value": "Calle Ramón y Cajal Rotonda Alboroque",
"synonyms": [
"14"
]
}
},
{
"name": {
"value": "Calle Juan de la Cierva",
"synonyms": [
"15"
]
}
},
{
"name": {
"value": "Calle Juan de la Cierva frente Campos de Rugby",
"synonyms": [
"16"
]
}
},
{
"name": {
"value": "Avenida de Valdezarce 1",
"synonyms": [
"17"
]
}
},
{
"name": {
"value": "Calle Almazara 11",
"synonyms": [
"18"
]
}
},
{
"name": {
"value": "Camino Viejo frente Campo de Golf",
"synonyms": [
"19"
]
}
},
{
"name": {
"value": "Avenida Aguachales 15",
"synonyms": [
"20"
]
}
},
{
"name": {
"value": "Calle Arnaldo Vilanova junto Centro Deportivo",
"synonyms": [
"21"
]
}
},
{
"name": {
"value": "Calle Arnaldo Vilanova frente CEIP Kantica",
"synonyms": [
"22"
]
}
},
{
"name": {
"value": "Calle Ramón y Cajal junto Rotonda de los Olivos",
"synonyms": [
"23"
]
}
},
{
"name": {
"value": "Centro Comercial Rio Shopping",
"synonyms": [
"24"
]
}
},
{
"name": {
"value": "Calle Ramón y Cajal frente Rotonda de los Olivos",
"synonyms": [
"25"
]
}
},
{
"name": {
"value": "Avenida Aranzana 39",
"synonyms": [
"26"
]
}
},
{
"name": {
"value": "Avenida Aranzana 29",
"synonyms": [
"27"
]
}
},
{
"name": {
"value": "Avenida Aranzana frente IESO Arroyo",
"synonyms": [
"28"
]
}
},
{
"name": {
"value": "Avenida Aranzana 9",
"synonyms": [
"29"
]
}
},
{
"name": {
"value": "Calle Picones 15 junto Glorieta del Cañazo",
"synonyms": [
"30"
]
}
},
{
"name": {
"value": "Plaza de España esquina Ayuntamiento",
"synonyms": [
"31"
]
}
},
{
"name": {
"value": "Calle Almendrera frente CEIP Raimundo de Blas",
"synonyms": [
"32"
]
}
},
{
"name": {
"value": "Calle Almendrera 16 Casa de Cultura",
"synonyms": [
"33"
]
}
},
{
"name": {
"value": "Calle Camino de Zaratán 40A",
"synonyms": [
"34"
]
}
},
{
"name": {
"value": "Calle Camino de Zaratán 22",
"synonyms": [
"35"
]
}
},
{
"name": {
"value": "Calle Camino de Zaratán 2",
"synonyms": [
"36"
]
}
},
{
"name": {
"value": "Avenida de Medina del Campo 15 frente Centro de Salud Arturo Eyries",
"synonyms": [
"37"
]
}
},
{
"name": {
"value": "Paseo de Zorrilla 65 frente El Corte Inglés",
"synonyms": [
"38"
]
}
},
{
"name": {
"value": "Paseo de Filipinos frente Campo Grande",
"synonyms": [
"39"
]
}
},
{
"name": {
"value": "Calle Camino de Zaratán 2",
"synonyms": [
"40"
]
}
},
{
"name": {
"value": "Calle Camino de Zaratán 22",
"synonyms": [
"41"
]
}
},
{
"name": {
"value": "Calle Clavel 10",
"synonyms": [
"42"
]
}
},
{
"name": {
"value": "Calle Clavel frente Casa de Cultura",
"synonyms": [
"43"
]
}
},
{
"name": {
"value": "Calle Almendrera junto CEIP Raimundo de Blas",
"synonyms": [
"44"
]
}
},
{
"name": {
"value": "Plaza de España frente Ayuntamiento",
"synonyms": [
"45"
]
}
},
{
"name": {
"value": "Calle Picones 8 junto Farmacia",
"synonyms": [
"46"
]
}
},
{
"name": {
"value": "Avenida Aranzana 9",
"synonyms": [
"47"
]
}
},
{
"name": {
"value": "Avenida Aranzana junto IESO Arroyo",
"synonyms": [
"48"
]
}
},
{
"name": {
"value": "Avenida Aranzana 29",
"synonyms": [
"49"
]
}
},
{
"name": {
"value": "Avenida Aranzana 37",
"synonyms": [
"50"
]
}
},
{
"name": {
"value": "Calle Arnaldo Vilanova frente Centro Deportivo",
"synonyms": [
"51"
]
}
},
{
"name": {
"value": "Avenida de Valdezarce 1",
"synonyms": [
"52"
]
}
},
{
"name": {
"value": "Calle Juan de la Cierva junto Campos de Rugby",
"synonyms": [
"53"
]
}
},
{
"name": {
"value": "Cale Ramón y Cajal junto Rotonda Alboroque",
"synonyms": [
"54"
]
}
},
{
"name": {
"value": "Calle Ramón y Cajal frente edificio ADE",
"synonyms": [
"55"
]
}
},
{
"name": {
"value": "Avenida de José Luís Lasa junto Centro Deportivo La Vega",
"synonyms": [
"56"
]
}
},
{
"name": {
"value": "Avenida de José Luís Lasa 16",
"synonyms": [
"57"
]
}
},
{
"name": {
"value": "Paseo de Juan Carlos I",
"synonyms": [
"58"
]
}
},
{
"name": {
"value": "Avenida de Colón 82 junto Multiusos de la Vega",
"synonyms": [
"59"
]
}
},
{
"name": {
"value": "Avenida de Colón 132 esquina Calle Bartolomé de las Casas",
"synonyms": [
"60"
]
}
},
{
"name": {
"value": "Avenida de Colón 175 junto pistas polideportivas",
"synonyms": [
"61"
]
}
},
{
"name": {
"value": "Calle Federación de Fútbol",
"synonyms": [
"62"
]
}
},
{
"name": {
"value": "Avenida de Salamanca junto Hipercor",
"synonyms": [
"63"
]
}
},
{
"name": {
"value": "Plaza del Poniente",
"synonyms": [
"64"
]
}
},
{
"name": {
"value": "Carretera de Segovia frente Universidad",
"synonyms": [
"65"
]
}
},
{
"name": {
"value": "Plaza de Santa Cruz",
"synonyms": [
"66"
]
}
},
{
"name": {
"value": "Paseo Prado de La Magdalena 18 Filosofía y Letras",
"synonyms": [
"67"
]
}
},
{
"name": {
"value": "Calle Arnaldo Vilanova junto CEIP Kantica",
"synonyms": [
"68"
]
}
},
{
"name": {
"value": "Avenida Aguachales 15 esquina Calle Estefanía",
"synonyms": [
"69"
]
}
},
{
"name": {
"value": "Camino Viejo frente Campo de Golf",
"synonyms": [
"70"
]
}
},
{
"name": {
"value": "Avenida Valdezarce esquina Calle Almazara",
"synonyms": [
"71"
]
}
},
{
"name": {
"value": "Calle Juan de la Cierva esquina Calle Torres Quevedo",
"synonyms": [
"72"
]
}
},
{
"name": {
"value": "Calle Arnaldo Vilanova junto CEIP Kantica",
"synonyms": [
"73"
]
}
},
{
"name": {
"value": "Camino del Cementerio 35 junto Campus",
"synonyms": [
"74"
]
}
}
]
},
{
"name": "LINEA",
"values": [
{
"name": {
"value": "azul",
"synonyms": [
"línea azul"
]
}
},
{
"name": {
"value": "roja",
"synonyms": [
"línea roja",
"rojo"
]
}
},
{
"name": {
"value": "verde",
"synonyms": [
"línea verde",
"universidades"
]
}
},
{
"name": {
"value": "búho",
"synonyms": [
"buho",
"nocturno",
"el búho"
]
}
}
]
}
]
}
}
}Si ya tenías la skill creada, sustituye el modelo antiguo por este, pulsa Save y Build Model. Prueba con «Alexa, abre arroyo bus».
Qué le puedes preguntar
- 🚏 «próximo bus en la parada 100»
- 🔵 «cuándo pasa la línea azul por Plaza España»
- 📍 «dónde está la línea roja»
- 🚌 «cuántos buses hay circulando»
- ⚠️ «hay avisos» / «hay incidencias»
- 🗺️ «qué líneas hay»
- 🎫 «cuánto cuesta el billete»
- 💳 «qué es la tarjeta BusCyL»
- 🏥 «cómo voy al hospital Río Hortega»
- 🎓 «cómo llego a la universidad»
- 🦉 «horario del búho»
- 📞 «teléfono de atención»
- ✍️ «la petición de change»
- 🔁 «repite» / «actualiza» (vuelve a consultar la última parada)
Alexa mantiene la conversación abierta: tras cada respuesta puedes hacer otra pregunta sin repetir «abre arroyo bus». Di «no» o «para» para terminar.
Opcional: para restringir el endpoint a tu skill, configura el secreto ALEXA_SKILL_ID con el ID de tu skill (amzn1.ask.skill...).
¿Y Google Assistant?
Google retiró las Conversational Actions en 2023. Una skill de voz pública para Google Assistant ya no es posible sin una app Android nativa con App Actions. Como alternativa, en Android puedes crear un atajo del navegador que llame al mismo endpoint que Siri (/api/public/voice/stop?q=…).