question

Mihai avatar image
Mihai asked

Alexa does not respond to Upsell request coming from the handler of an intent with auto delegation enabled

Hi,

I am trying to call the UpsellResponseHandler (below) from another handler in order to upsell a subscription (the only premium product in the skill) to the user in a certain scenario. However, Alexa does not follow up and doesn't start the upsell process when the request is sent. The upsell message is not read and there is no other output (just silence).


UpsellResponseHandler in my Lambda function

class UpsellResponseHandler(AbstractRequestHandler):
    """This handles the Connections.Response event after an upsell occurs."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return (is_request_type("Connections.Response")(handler_input) and
                handler_input.request_envelope.request.name == "Upsell")

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        logger.info("In UpsellResponseHandler")

        if handler_input.request_envelope.request.status.code == "200":

            if handler_input.request_envelope.request.payload.get("purchaseResult") == PurchaseResult.DECLINED.value:
                declines = ["<prosody volume='x-loud' rate='slow'>Noob</prosody> mode - activated!",
                            "I hope you're feeling comfortable as a <prosody volume='x-loud' rate='slow'>noob</prosody>.",
                            "Novice mode - re-activated!",
                            "My little trainee, I'm proud of you even if you're a <prosody volume='x-loud' rate='slow'>noob</prosody>.",
                            "I hope you're enjoying the <prosody volume='x-loud' rate='slow'>noob</prosody> club!"]
                speech = (random.choice(declines))
                handler_input.attributes_manager.session_attributes["lastSpeech"] = speech
                reprompt = "So, would you like to hear a <prosody volume='loud'>price</prosody>?"

                return handler_input.response_builder.speak("{} {}".format(speech, get_random_yes_no_question())).ask(reprompt).response

            elif handler_input.request_envelope.request.payload.get("purchaseResult") == PurchaseResult.ACCEPTED.value:
                speech = ("You have unlocked the Premium subscription, and promoted to the <prosody volume='loud'>crypto</prosody> Superstar level! What price can I help you with?")
                reprompt = get_random_yes_no_question()

                return handler_input.response_builder.speak(speech).ask(reprompt).response

        else:
            logger.log("Connections.Response indicated failure. Error: {}".format(handler_input.request_envelope.request.status.message))

            return handler_input.response_builder.speak(
                "There was an error handling your Upsell request. "
                "Please try again or contact us for help.").response


Directive from another handler

upsell_msg = ("Sorry, noobie! You just reached the daily limit for the Free Subscription! To get access to 10 prices per day, you can upgrade to the amazing Premium Subscription. {} Want to learn more?").format(subscription_pack[0].summary)

handler_input.attributes_manager.session_attributes["lastSpeech"] = upsell_msg

return handler_input.response_builder.add_directive(
                        SendRequestDirective(
                            name = "Upsell",
                            payload = {
                                "InSkillProduct": {
                                    "productId": subscription_pack[0].product_id,
                                },
                                "upsellMessage": upsell_msg,
                            },
                            token = "correlationToken")).response


JSON input

{
    "version": "1.0",
    "session": {
        "new": false,
        "sessionId": "amzn1.echo-api.session.1b9b6075-28f7-49ba-a9a2-bfe4c90fa5ad",
        "application": {
            "applicationId": "amzn1.ask.skill.8d3500e7-7057-4ae9-9afa-884e4987ac27"
        },
        "attributes": {
            "counter_prices": 3,
            "lastSpeech": "The current price of Litecoin is 121.47 Euros on Coinbase.<audio src='soundbank://soundlibrary/human/amzn_sfx_crowd_applause_04'/> Now, because I'm a crypto addict, I must add that 1 Euro is worth 0.00823249 Litecoin <audio src='soundbank://soundlibrary/foley/amzn_sfx_glasses_clink_03'/>",
            "counter_prices_time": "06/21/19 15:07:07"
        },
        "user": {
            "userId": "amzn1.ask.account.AHDF5NG3JYV3CVTDXZ47SZD36CBEKPIVMNSZCKX556C2VOL72RHK5MTOENBFTUJR7Q2XVGM5AKWK546FZ4UBDHTK5KYLU4PY37USLA2P5XMWAOLECZK32KJ5H554IZONZ2YB2DRPSZ7DK3Y3HZ3FAROWXD3AXNB2S2OZ4HLBOWT6URJIVFCZRTP6TH2EDLYABGTUROWUMUJ7BNI"
        }
    },
    "context": {
        "System": {
            "application": {
                "applicationId": "amzn1.ask.skill.8d3500e7-7057-4ae9-9afa-884e4987ac27"
            },
            "user": {
                "userId": "amzn1.ask.account.AHDF5NG3JYV3CVTDXZ47SZD36CBEKPIVMNSZCKX556C2VOL72RHK5MTOENBFTUJR7Q2XVGM5AKWK546FZ4UBDHTK5KYLU4PY37USLA2P5XMWAOLECZK32KJ5H554IZONZ2YB2DRPSZ7DK3Y3HZ3FAROWXD3AXNB2S2OZ4HLBOWT6URJIVFCZRTP6TH2EDLYABGTUROWUMUJ7BNI"
            },
            "device": {
                "deviceId": "amzn1.ask.device.AGBOBM66QENCNFILOCQDIIGDOL4UNECYCORD3OP2D54XD6N773C5EEOQKHCFXR7KP3JXVCOEFQ2OSTNLAF2GULLNXRTJJJKRMLESAIJMFFTP25MCJZZ2BR4RWCWM4RVLU5L6UW4FH3KWVNTC6B2O4QLPLYWLV5CVXAHGJFKLIME7BCNZLONCE",
                "supportedInterfaces": {}
            },
            "apiEndpoint": "https://api.amazonalexa.com",
            "apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLjhkMzUwMGU3LTcwNTctNGFlOS05YWZhLTg4NGU0OTg3YWMyNyIsImV4cCI6MTU2MTEyOTk1MSwiaWF0IjoxNTYxMTI5NjUxLCJuYmYiOjE1NjExMjk2NTEsInByaXZhdGVDbGFpbXMiOnsiY29udGV4dCI6IkFBQUFBQUFBQUFCSXFMVDdVVW9TUTZLTXVNTGVpcTRqS3dFQUFBQUFBQUNURGt6VTFXUnhtQ0xwdEZoamZOZEVWRFJrcjBtQjJ4T1JScHF6YlhVbTVzRmpSbW1aMFZBSjFKK2FyTUl6KytEa3V3S1lGTDl5eThBbk9xbUF6RWNYL2dJUnJhWk43ZTV6azA3cTV1bzN1Y2FpdkpLbjlnWi9xZERPaUFLRVZLc1lrNlNzb2hjSkdlcGc4a3F5Myt6b1IrNFdMTzMwR0txYk0rekFyNzNMRFF1VHloNHlLZWYzaXo3cmJPczZkbU9yVmtmbUlaQjRxYzl6QUNXd2hGeXE4YnhoK1FKUWpQZm9lMzJXOVk1MmQxMDdJN0tmTWpsVTdMSG9QeXJveGFEM00wOHFodEJ3UDRMdWg0VzFtRHdUZngyK1Q4VU50K2g1d1YrOXgzYXE1ZVo0Rng3UFlINFBBWTZuV01iYS8rcTZCV3pmcEJGc216Y0VqZm5uNW9WaCsxdThJVkpaS1pFYWk2aVlLTklBQVk3Qm5BdWNSOTNVSHFpMjBrN1J3bkl0ZElOUHAxZHY5ZThnOFE9PSIsImNvbnNlbnRUb2tlbiI6bnVsbCwiZGV2aWNlSWQiOiJhbXpuMS5hc2suZGV2aWNlLkFHQk9CTTY2UUVOQ05GSUxPQ1FESUlHRE9MNFVORUNZQ09SRDNPUDJENTRYRDZONzczQzVFRU9RS0hDRlhSN0tQM0pYVkNPRUZRMk9TVE5MQUYyR1VMTE5YUlRKSkpLUk1MRVNBSUpNRkZUUDI1TUNKWloyQlI0UldDV000UlZMVTVMNlVXNEZIM0tXVk5UQzZCMk80UUxQTFlXTFY1Q1ZYQUhHSkZLTElNRTdCQ05aTE9OQ0UiLCJ1c2VySWQiOiJhbXpuMS5hc2suYWNjb3VudC5BSERGNU5HM0pZVjNDVlREWFo0N1NaRDM2Q0JFS1BJVk1OU1pDS1g1NTZDMlZPTDcyUkhLNU1UT0VOQkZUVUpSN1EyWFZHTTVBS1dLNTQ2Rlo0VUJESFRLNUtZTFU0UFkzN1VTTEEyUDVYTVdBT0xFQ1pLMzJLSjVINTU0SVpPTloyWUIyRFJQU1o3REszWTNIWjNGQVJPV1hEM0FYTkIyUzJPWjRITEJPV1Q2VVJKSVZGQ1pSVFA2VEgyRURMWUFCR1RVUk9XVU1VSjdCTkkifX0.LAxAhY3LYCPtPvpd1lZpEh5ekzQ26nuwvNg9hXXpkYrFDQ2ZGk1ePB5fWBXvSfDTOfzvPUASzBwBMB_KnnkEcOOphKcdiiyjipWSyMjADGVVD4OHHcdnCqJiaoZ4ajZQ7Hy1p0KF9KvUf6M46UbqWU0h-Nthv3m8NyW56KlWzFrfpO6zXDeGMQgFntE5wwwaIcgyOz2b6I94NoiSQRBQzNj3guub_zTUYg-JDbvtHZo44VNVzYAjxcrRhu_FZ_gQRjrB5qQiSmX1nUuE99QotwU98Q_0ztUNuHH7_bA6H1BgJnxxm1p9GeKWOKRLuMX7-QgZ0o39OVnwL4zYzSGN5A"
        },
        "Viewport": {
            "experiences": [
                {
                    "arcMinuteWidth": 246,
                    "arcMinuteHeight": 144,
                    "canRotate": false,
                    "canResize": false
                }
            ],
            "shape": "RECTANGLE",
            "pixelWidth": 1024,
            "pixelHeight": 600,
            "dpi": 160,
            "currentPixelWidth": 1024,
            "currentPixelHeight": 600,
            "touch": [
                "SINGLE"
            ],
            "video": {
                "codecs": [
                    "H_264_42",
                    "H_264_41"
                ]
            }
        }
    },
    "request": {
        "type": "IntentRequest",
        "requestId": "amzn1.echo-api.request.221e1653-f6f8-4e63-9c73-8e5ad09b22b9",
        "timestamp": "2019-06-21T15:07:31Z",
        "locale": "en-US",
        "intent": {
            "name": "PriceIntent",
            "confirmationStatus": "NONE",
            "slots": {
                "fiat": {
                    "name": "fiat",
                    "value": "dollars",
                    "resolutions": {
                        "resolutionsPerAuthority": [
                            {
                                "authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.8d3500e7-7057-4ae9-9afa-884e4987ac27.fiatCoin",
                                "status": {
                                    "code": "ER_SUCCESS_MATCH"
                                },
                                "values": [
                                    {
                                        "value": {
                                            "name": "USD",
                                            "id": "3518f8944d42212dd37daffe097d216e"
                                        }
                                    }
                                ]
                            }
                        ]
                    },
                    "confirmationStatus": "NONE",
                    "source": "USER"
                },
                "exchange": {
                    "name": "exchange",
                    "value": "kraken",
                    "resolutions": {
                        "resolutionsPerAuthority": [
                            {
                                "authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.8d3500e7-7057-4ae9-9afa-884e4987ac27.theExchange",
                                "status": {
                                    "code": "ER_SUCCESS_MATCH"
                                },
                                "values": [
                                    {
                                        "value": {
                                            "name": "Kraken",
                                            "id": "049a956dfeb0eb2e19c417a1dde4d680"
                                        }
                                    }
                                ]
                            }
                        ]
                    },
                    "confirmationStatus": "NONE",
                    "source": "USER"
                },
                "crypto": {
                    "name": "crypto",
                    "value": "bitcoin",
                    "resolutions": {
                        "resolutionsPerAuthority": [
                            {
                                "authority": "amzn1.er-authority.echo-sdk.amzn1.ask.skill.8d3500e7-7057-4ae9-9afa-884e4987ac27.cryptoCoin",
                                "status": {
                                    "code": "ER_SUCCESS_MATCH"
                                },
                                "values": [
                                    {
                                        "value": {
                                            "name": "Bitcoin",
                                            "id": "d023ec040f79f1a9b2ac960b43785089"
                                        }
                                    },
                                    {
                                        "value": {
                                            "name": "Bitcoin Cash",
                                            "id": "9e93cde96df71557d56cdc14d0962727"
                                        }
                                    }
                                ]
                            }
                        ]
                    },
                    "confirmationStatus": "NONE",
                    "source": "USER"
                }
            }
        },
        "dialogState": "COMPLETED"
    }
}


JSON output

{
    "body": {
        "version": "1.0",
        "response": {
            "directives": [
                {
                    "type": "Connections.SendRequest",
                    "name": "Upsell",
                    "payload": {
                        "InSkillProduct": {
                            "productId": "amzn1.adg.product.7a43a869-2b1e-4acb-b832-ec59ec253259"
                        },
                        "upsellMessage": "Sorry, noobie! You just reached the daily limit for the Free Subscription! To get access to 10 prices per day, you can upgrade to the amazing Premium Subscription. The Premium subscription allows you to get the real-time price of Bitcoin, Ethereum, Litecoin, XRP, or Bitcoin Cash, in US dollars, or Euros, 10 times a day! Want to learn more?"
                    },
                    "token": "correlationToken"
                }
            ],
            "type": "_DEFAULT_RESPONSE"
        },
        "sessionAttributes": {
            "counter_prices": 3,
            "lastSpeech": "Sorry, noobie! You just reached the daily limit for the Free Subscription! To get access to 10 prices per day, you can upgrade to the amazing Premium Subscription. The Premium subscription allows you to get the real-time price of Bitcoin, Ethereum, Litecoin, XRP, or Bitcoin Cash, in US dollars, or Euros, 10 times a day! Want to learn more?",
            "counter_prices_time": "06/21/19 15:07:07"
        },
        "userAgent": "ask-python/1.10.1 Python/3.7.3"
    }
}


No errors are shown in the Cloudwatch logs.

I've been struggling with this issue since yesterday and still I don't know what I'm missing here.


P.S. I have another skill which uses the exact same upsell directive and handler (with other speeches, of course) and it works like a charm. Comparing the two JSONs In/Out for the two skills side by side, the only differences (that I noticed) when asking for an upsell are:

In JSON Input of working skill: "dialogState": "STARTED"

In JSON Input of non-working skill: "dialogState": "COMPLETED"


In JSON Output of working skill: "userAgent": "ask-python/1.9.0 Python/3.7.3"

In JSON Output of non-working skill: "userAgent": "ask-python/1.10.1 Python/3.7.3"


Working skill: upsells to a one-time purchase

Non-working skill: upsells to a subscription


Skill ID: amzn1.ask.skill.8d3500e7-7057-4ae9-9afa-884e4987ac27


Any help would be greatly appreciated! Thanks!


alexa skills kitalexa
10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Mihai avatar image
Mihai answered

By the way, the Buy and Cancel directives work perfectly when buying or refunding the subscription. Only the Upsell directive gets no response whatsoever.

10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Mihai avatar image
Mihai answered

After further digging, it seems that the problem is the Upsell directive being inside a intent handler having a dialog model handled by Alexa (Dialog Delegation Strategy - auto delegation).


I have made the following test: moved the Upsell directive to another intent handler in my Lambda function (just for testing) and it works perfectly when that intent gets triggered. However, in the original intent handler (the one having the dialog delegation set to auto), the Upsell request gets no response from Alexa. here is the intent handler causing this:


Intent handler

class CompletedPriceIntent(AbstractRequestHandler):
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return (is_intent_name("PriceIntent")(handler_input)
            and handler_input.request_envelope.request.dialog_state == DialogState.COMPLETED)

    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        logger.info("In CompletedPriceIntent")
        filled_slots = handler_input.request_envelope.request.intent.slots
        slot_values = get_slot_values(filled_slots)
        #print(slot_values)

        in_skill_response = in_skill_product_response(handler_input)

        if in_skill_response:
            entitled = [l for l in in_skill_response.in_skill_products if l.entitled == EntitledState.ENTITLED]
            not_entitled = [l for l in in_skill_response.in_skill_products if l.entitled == EntitledState.NOT_ENTITLED]
            subscription_pack = [l for l in in_skill_response.in_skill_products if l.reference_name == "premium_pack"]

        persist_attr = handler_input.attributes_manager.persistent_attributes

        if ((not persist_attr) or (persist_attr and (persist_attr['counter_prices'] < 3) and (entitled) and (datetime.now().date() > datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date())) or (persist_attr and (persist_attr['counter_prices'] < 3) and (not_entitled) and (datetime.now().date() > datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date())) or (persist_attr and (3 <= persist_attr['counter_prices'] < 10) and (entitled) and (datetime.now().date() > datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date())) or (persist_attr and (persist_attr['counter_prices'] >= 10) and (entitled) and (datetime.now().date() > datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date()))):
            pass

        elif ((persist_attr and (persist_attr['counter_prices'] < 3) and (entitled) and (datetime.now().date() == datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date())) or (persist_attr and (persist_attr['counter_prices'] < 3) and (not_entitled) and (datetime.now().date() == datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date())) or (persist_attr and (3 <= persist_attr['counter_prices'] < 10) and (entitled) and (datetime.now().date() == datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date()))):
            pass

        elif (persist_attr and (persist_attr['counter_prices'] >= 10) and (entitled) and (datetime.now().date() == datetime.strptime(persist_attr['counter_prices_time'], "%m/%d/%y %H:%M:%S").date())):
            pass

        else:
            upsell_msg = ("Sorry, noobie! You just reached the daily limit for the Free Subscription! To get access to 10 prices per day, you can upgrade to the amazing Premium Subscription. {} Want to learn more?").format(subscription_pack[0].summary)

            handler_input.attributes_manager.session_attributes["lastSpeech"] = upsell_msg

            return handler_input.response_builder.add_directive(
                SendRequestDirective(
                    name="Upsell",
                    payload={
                        "InSkillProduct": {
                            "productId": subscription_pack[0].product_id,
                        },
                        "upsellMessage": upsell_msg,
                    },
                    token="correlationToken")).response


JSON (truncated only for this intent)

{
    "name": "PriceIntent",
    "slots": [
        {
            "name": "crypto",
            "type": "cryptoCoin",
            "samples": [
                "Give me the {crypto} price"
            ]
        },
        {
            "name": "fiat",
            "type": "fiatCoin",
            "samples": [
                "the {fiat} price please"
            ]
        },
        {
            "name": "exchange",
            "type": "theExchange"
        }
    ],
    "samples": [
        "what is the price of {crypto} in {fiat} on {exchange}"
    ]
}

...

"dialog": {
    "intents": [
        {
            "name": "PriceIntent",
            "delegationStrategy": "ALWAYS",
            "confirmationRequired": false,
            "prompts": {},
            "slots": [
                {
                    "name": "crypto",
                    "type": "cryptoCoin",
                    "confirmationRequired": false,
                    "elicitationRequired": true,
                    "prompts": {
                        "elicitation": "Elicit.Slot.69186907495.1229392271052"
                    }
                },
                {
                    "name": "fiat",
                    "type": "fiatCoin",
                    "confirmationRequired": false,
                    "elicitationRequired": true,
                    "prompts": {
                        "elicitation": "Elicit.Slot.69186907495.1330830443661"
                    }
                },
                {
                    "name": "exchange",
                    "type": "theExchange",
                    "confirmationRequired": false,
                    "elicitationRequired": false,
                    "prompts": {}
                }
            ]
        }
    ],
    "delegationStrategy": "ALWAYS"
},
"prompts": [
    {
        "id": "Elicit.Slot.69186907495.1419981262022",
        "variations": [
            {
                "type": "PlainText",
                "value": "I can tell you the price of {crypto} from Kraken, Coinbase, or Bitstamp. Pick one"
            }
        ]
    },
    {
        "id": "Elicit.Slot.69186907495.1330830443661",
        "variations": [
            {
                "type": "PlainText",
                "value": "Please tell me what currency would you like me to use for the price of {crypto} . US dollars, or Euros?"
            }
        ]
    },
    {
        "id": "Elicit.Slot.69186907495.1229392271052",
        "variations": [
            {
                "type": "PlainText",
                "value": "I can tell you the current price of Bitcoin, Ethereum, Litecoin, XRP, or Bitcoin Cash. Pick one"
            }
        ]
    }
]
6 comments
10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Hi. Thanks a lot for taking the time to post these details as well as the result of your further research.


As a test, I created a sample skill with in-skill purchasing and then enabled "Intent Confirmation" on the intent that generates the "Upsell" directive.


I too ran into the same issue you described where when auto dialog delegation was enabled, Alexa simply didn't respond but worked without issue once it was disabled.


I've reported the issue to the appropriate internal team and will follow up when I have more information to share.

2 Likes 2 ·
Mihai avatar image Mihai KirkC@Amazon ♦♦ ·

Hi Kirk,

I'm glad you were able to reproduce this issue. Any updates thus far? I am literally waiting for this to be fixed so I can submit my skill for certification. Without the upsell feature I cannot release the skill to the public yet, unfortunately.

Thank you.

0 Likes 0 ·

Hi Mihai. I spoke with our engineers again today but as of yet I have no new information to share as the issue is still being investigated.

2 Likes 2 ·
Show more comments

Interesting workaround but it doesn't work exactly as an upsell. The difference is that the upsell message that you pass in speak() is mentioned and then the buy directive is triggered automatically. If this were a true upsell the upsell message is read and then the mic is open waiting for a confirmation, if the user says yes yo go into the purchase process. So the difference with a real upsell is the open mic waiting for confirmation which is not present in the workaround!

0 Likes 0 ·
newuser-649b183f-6876-4dd0-80c2-8ec258cba9b6 avatar image
newuser-649b183f-6876-4dd0-80c2-8ec258cba9b6 answered

I have the same problem. Same structure. The JSON output looks like it should work. However no talking :/

2 comments
10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

This issue is currently under investigation. Hope it gets fixed soon.

0 Likes 0 ·

In the meantime, I am using a workaround with the Buy directive instead of Upsell and it works.


upsell_msg = ("Sorry, noobie! You just reached the daily limit for the Free Subscription! To get access to 10 prices per day, you can upgrade to the amazing Premium Subscription. <audio src='soundbank://soundlibrary/foley/amzn_sfx_glasses_clink_01'/>")

return handler_input.response_builder.speak(upsell_msg).add_directive(
                SendRequestDirective(
                    name="Buy",
                    payload={
                        "InSkillProduct": {
                            "productId": subscription_pack[0].product_id
                        }
                    },
                    token="correlationToken")).response


Hope this helps in any way.

0 Likes 0 ·
newuser-649b183f-6876-4dd0-80c2-8ec258cba9b6 avatar image
newuser-649b183f-6876-4dd0-80c2-8ec258cba9b6 answered

I have the same problem. The JSON output looks fine. However, Alexa doesnt talk :/

10 |3000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.