Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Alexa Smart Home Skill Adapter for Home Assistant
Copyright 2019 Jason Hu <awaregit at>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.
import os
import json
import logging
import urllib3
_debug = bool(os.environ.get('DEBUG'))
_logger = logging.getLogger('HomeAssistant-SmartHome')
_logger.setLevel(logging.DEBUG if _debug else logging.INFO)
def lambda_handler(event, context):
"""Handle incoming Alexa directive."""
_logger.debug('Event: %s', event)
base_url = os.environ.get('BASE_URL')
assert base_url is not None, 'Please set BASE_URL environment variable'
directive = event.get('directive')
assert directive is not None, 'Malformatted request - missing directive'
assert directive.get('header', {}).get('payloadVersion') == '3', \
'Only support payloadVersion == 3'
scope = directive.get('endpoint', {}).get('scope')
if scope is None:
# token is in grantee for Linking directive
scope = directive.get('payload', {}).get('grantee')
if scope is None:
# token is in payload for Discovery directive
scope = directive.get('payload', {}).get('scope')
assert scope is not None, 'Malformatted request - missing endpoint.scope'
assert scope.get('type') == 'BearerToken', 'Only support BearerToken'
token = scope.get('token')
if token is None and _debug:
token = os.environ.get('LONG_LIVED_ACCESS_TOKEN') # only for debug purpose
verify_ssl = not bool(os.environ.get('NOT_VERIFY_SSL'))
http = urllib3.PoolManager(
cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE',
timeout=urllib3.Timeout(connect=2.0, read=10.0)
response = http.request(
'Authorization': 'Bearer {}'.format(token),
'Content-Type': 'application/json',
if response.status >= 400:
return {
'event': {
'payload': {
if response.status in (401, 403) else 'INTERNAL_ERROR',
return json.loads('utf-8'))

This comment has been minimized.

Copy link
Owner Author

@matt2005 matt2005 commented Jul 2, 2019

Updated to allow linking when alexa proactive messaging Forum Issue


This comment has been minimized.

Copy link

@Mirabis Mirabis commented Dec 22, 2020

Thankyou for the awesome code and Youtube tutorial. My HomeAssistant was only available through client certificates but the following link explained how to add that into the code :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment