Kidde Smart Alarms - Smoke / CO detectors

Not sure if they have an API, but it old be great to get this integrated


Seconded - if their app can connect, would be great to have an HA integration.

1 Like

Just picked up the new kidde wifi smoke/Co with air quality and was wondering if it connected to HA. It looks like it connects to Amazon and Google.


Any updates on an HA integration with Kidde HomeSafe? Looking at these new detectors and would be great to have the information populated in my HA.

Any updates on this?

Looks like a neat device. I don’t have one ($90 is a lot when I have a few years left on my detectors). I was able to mitm the app and login,but cannot go further without a device.

I recommend you learn how to mitm and build an integration. Just takes some research. If someone wants to PM me a username and password with a device already configured, I might play around. However, I could always set off your alarm by accident! Looking at the returns from the API, seems some of their devices are ESP-32 based, perhaps one could flash it. Not sure if the smoke detector is ESP based.

To get someone started:

import requests

headers = {
    'homeboy-app-platform': 'android',
    'homeboy-app-version': '4.0.12',
    'homeboy-app-platform-version': '12',
    'homeboy-app-id': 'afc41e9816b1f0d7',
    'homeboy-app-brand': 'google',
    'homeboy-app-device': 'sdk_gphone64_x86_64',
    'cache-control': 'max-age=0',
    'homeboy-app': '',
    'user-agent': '',
    'homeboy-auth': 'bd723f7a8ba40461a51ca439c75cd5b4780bdbb3',
    'content-type': 'application/json; charset=UTF-8',

json_data = {
    'email': '[email protected]',
    'password': 'yourpassword',
    'timezone': 'America/New_York',

response ='', headers=headers, json=json_data)

Anyone have any progress on this?


I’m interested in this and have (5) Kidde Smoke + Carbon Monoxide Alarm with Indoor Air Quality Monitor detectors (Smoke + Carbon Monoxide Alarm with Indoor Air Quality Monitor | Kidde)… we can work together on it, I’m more techie than the avg person, some light programming skills, and lots of networking/pc knowledge from working on them since the late 1980s… shoot me a msg and I can share my acct to you, and we can get started…

1 Like

i’m interested as well.
I would like a fire alarm that I can use as a burglar alarm.

Would really hope the integration can help with that.
I am a techie but really on the backend side. would like to collaborate if someone can guide.

I got somewhere with this. I was able to query the devices and pull TVOC, Humidity, etc and all kinds of other stats. I don’t know enough to go further with building an integration, but the API is accessible if you know your credentials. I used a MITM attack to get the API key for my account. This allows me to pull my “ID” (unique account number) and add that to the GET request. < unique ID here > /device

1 Like

Glad you figured it out. I never got one of these. The code I posted above lets you get your ID. I am surprised that is all you need, as my ID is just a 5 digit number. Hopefully there is more to it than that or the ID you found is different!

Writing an integration is not too bad. You can look at some of my simple ones like which show how to make sensors from json.

An easier option is you can use a RESTful Sensor RESTful Sensor - Home Assistant ( You figured out the API address, so should be simple to make a restfull sensor pull out all the values you want. Look at the " FETCH MULTIPLE JSON ATTRIBUTES AND PRESENT THEM AS VALUES" section.

1 Like

ID is unique to your account. Once you get your ID and API key (homeboy-auth), you can use that to access the devices.

I use something different for monitoring my home IoT stuff, and I’m not the most keen on this stuff, so I’m not the qualified one to get the integration going. I’m happy to help out with getting it done, however, I’m not sure on directing newbies to get their API key, etc. Not even sure how long my key will last.

Thanks for the tips on getting started with this! I just installed a “smart” Kidde smoke detector and am attempting to extract information from it. I made the call to get my ID and access_token. I then substituted the access_token for the original value for homeboy-auth in the header and made the suggested call:*xxxxxx*/device
with ‘xxxxxx’ being my user ID.

The call is successful but the response is this:
{"error":"Field \'model\' required","error_code":"model_required"}

I tried a couple of variations of passing ‘?model=value’ in the URL but none are recognized. The Kidde app tells me my model is ‘P4010ACS_w_1381’.

Did that “device” call return a list of devices for you? I would think that you would need to make a call to get a list of all devices in your account before knowing how to query individual ones.


Any chance someone who has gotten the /location/ID/device information to download could post a walkthrough? I was able to “login” to the API but cannot pass the token properly to get the actual device data. Any help would be appreciated.

1 Like

Make a call like this to get your userId and access_token, using headers and json_data structures as shown by jaaem:

response ='', headers=headers, json=json_data)

I don’t see that we need the userId at this point but you do need the access_token returned by that call. Backfill the access_token that call returns into the headers structures in preparation for the next call.

Python example shown – be sure to “import json” :

data = json.loads(response.text)
tok = data['access_token']
headers['homeboy-auth'] = tok

Make this call to get your location_id and location information:

response = requests.get("", headers=headers, json=json_data)

Data returned:

	"id":XXXXXX,"label":"My Home","user_id":xxxxxx,"country":"United States","zip":"xxxxx","state":"xx","city":"Anytown","street":"1 Any Street ","unit":"","weather_zone_desc":"Northern xxxxx","weather_county_desc":"xxxxx","emergency":"911","emergency_desc":"Call 911","longitude":-xx.xx,"latitude":xx.xx,"arm_type":"manual","geo_size":1,"min_weather_alert_level":0,"plan":"basic","viewers_enabled":true,"viewers_delay":0,"weather_alert":false,"smoke_mitigation":false,"tvoc_mitigation":false

I’ve x’d out and otherwise obscured my personal location information in that data set.

The “id” returned there is a 6-digit value that is a key to your location information.
Using that 6-digit location ID returned above (substitute your value here for the “XXXXXX” value) make this call:

response = requests.get("", headers=headers, json=json_data)

This returns a large set of data about my device including the environmental measurements.
I only have one device so I’m not sure how it returns data for more than one.

1 Like

Worked perfectly - thanks so much. Embarrassingly, I was using the wrong ID string when authenticating.

I was able to get all the way to location/ID/devices and get the Status of all the Smoke Detectors.

From the App I see there are options to:

  1. Ping
  2. Test
  3. Hush

The smoke detectors.

Does somebody here know the API calls to access those setting?

For test I am using direct CUrL commands. Once everything works will try to work on an integration.

1 Like

Here are the relevant endpoints from the smali code in the APK. Happy hunting! public static final AIRQUALITY_DATA:Ljava/lang/String; = "v4/airquality" public static final AUTHORIZE:Ljava/lang/String; = "v4/authorize" public static final AUTH_PREFIX:Ljava/lang/String; = "v4/auth/" public static final AWS_LOGS:Ljava/lang/String; = "v4/upload/logs" public static final AYLA_DEVICE_LATEST_REGISTER:Ljava/lang/String; = "v4/ayla/device/latest/register" public static final AYLA_DEVICE_PREFIX:Ljava/lang/String; = "v4/ayla/device/" public static final AYLA_DEVICE_REGISTER:Ljava/lang/String; = "v4/ayla/device/{dsn}/register" public static final AYLA_PREFIX:Ljava/lang/String; = "v4/ayla/" public static final DEVICE_STATS:Ljava/lang/String; = "v4/device/{devid}/stats" public static final EVENT_RESOLVE:Ljava/lang/String; = "v4/location/{locid}/event/{eventid}/resolve" public static final EVENT_SILENCE:Ljava/lang/String; = "v4/location/{locid}/event/{eventid}/silence" public static final FIRMWARE:Ljava/lang/String; = "v4/firmware" public static final GOOGLE:Ljava/lang/String; = "v4/auth/google" public static final INVITE_CODE:Ljava/lang/String; = "v4/invite/{code}" public static final INVITE_CODE_ACCEPT:Ljava/lang/String; = "v4/invite/{code}/accept" public static final INVITE_PREFIX:Ljava/lang/String; = "v4/invite/" public static final LOCATION:Ljava/lang/String; = "v4/location" public static final LOCATION_ACTION:Ljava/lang/String; = "v4/location/{locid}/{action}" public static final LOCATION_ARM:Ljava/lang/String; = "v4/location/{locid}/arm" public static final LOCATION_AWAY:Ljava/lang/String; = "v4/location/{locid}/away" public static final LOCATION_AYLA_DEVICE:Ljava/lang/String; = "v4/location/{locid}/ayladevice" public static final LOCATION_DEVICE:Ljava/lang/String; = "v4/location/{locid}/device" public static final LOCATION_DEVICE_CANCEL:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/cancel" public static final LOCATION_DEVICE_CAPTURE:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/capture" public static final LOCATION_DEVICE_HUSH:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/hush" public static final LOCATION_DEVICE_ID:Ljava/lang/String; = "v4/location/{locid}/device/{devid}" public static final LOCATION_DEVICE_IDENTIFY:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/identify" public static final LOCATION_DEVICE_IDENTIFY_CANCEL:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/identifycancel" public static final LOCATION_DEVICE_JOIN:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/join" public static final LOCATION_DEVICE_LOCATE:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/locate" public static final LOCATION_DEVICE_TEST:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/test" public static final LOCATION_DISARM:Ljava/lang/String; = "v4/location/{locid}/disarm" public static final LOCATION_EVENT:Ljava/lang/String; = "v4/location/{locid}/event" public static final LOCATION_EVENT_MEDIA:Ljava/lang/String; = "v4/location/{locid}/event/{eventid}/media" public static final LOCATION_HOME:Ljava/lang/String; = "v4/location/{locid}/home" public static final LOCATION_ID:Ljava/lang/String; = "v4/location/{locid}" public static final LOCATION_INVITE:Ljava/lang/String; = "v4/location/{locid}/invite" public static final LOCATION_INVITE_ID:Ljava/lang/String; = "v4/location/{locid}/invite/{invid}" public static final LOCATION_MEMBER:Ljava/lang/String; = "v4/location/{locid}/member" public static final LOCATION_MEMBER_ID:Ljava/lang/String; = "v4/location/{locid}/member/{userid}" public static final LOCATION_RESOLVE:Ljava/lang/String; = "v4/location/{locid}/resolve" public static final LOCATION_ROOM:Ljava/lang/String; = "v4/location/{locid}/room" public static final LOCATION_SILENCE:Ljava/lang/String; = "v4/location/{locid}/silence" public static final LOCATION_SUBSCRIPTION:Ljava/lang/String; = "v4/location/{locid}/subscription" public static final LOCATION_SUBSCRIPTION_CANCEL:Ljava/lang/String; = "v4/location/{locid}/subscription/cancel" public static final LOCATION_SUBSCRIPTION_META:Ljava/lang/String; = "v4/location/{locid}/subscription?meta=true" public static final LOCATION_SUBSCRIPTION_PREVIEW:Ljava/lang/String; = "v4/location/{locid}/subscription/preview" public static final LOCATION_SUBSCRIPTION_REACTIVATE:Ljava/lang/String; = "v4/location/{locid}/subscription/reactivate" public static final LOCATION_ZONE:Ljava/lang/String; = "v4/location/{locid}/zone" public static final LOGIN:Ljava/lang/String; = "v4/auth/login" public static final LOGOUT:Ljava/lang/String; = "v4/auth/logout" public static final RECALIBRATE:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/recalibrate" public static final SIGN:Ljava/lang/String; = "v4/sign" public static final TOKEN:Ljava/lang/String; = "v4/token" public static final UPDATE_FIRMWARE:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/otaupgrade" public static final UPDATE_STATUS:Ljava/lang/String; = "v4/location/{locid}/device/{devid}/otastatus" public static final USER:Ljava/lang/String; = "v4/user" public static final USER_AVATAR:Ljava/lang/String; = "v4/user/avatar" public static final USER_BILLING:Ljava/lang/String; = "v4/user/billing" public static final USER_CONSENT:Ljava/lang/String; = "v4/user/consent" public static final USER_CONSENTS:Ljava/lang/String; = "v4/user/consents" public static final USER_CONSENT_ACK:Ljava/lang/String; = "v4/user/consent/{id}/{ack}" public static final USER_CONSENT_ACK_PREFIX:Ljava/lang/String; = "v4/user/consent/" public static final USER_EMAIL_CHANGE:Ljava/lang/String; = "v4/user/email/change" public static final USER_EMAIL_RESEND:Ljava/lang/String; = "v4/user/email/resend" public static final USER_EMAIL_VERIFY:Ljava/lang/String; = "v4/user/email/verify" public static final USER_EXPERIENCE_STATS:Ljava/lang/String; = "v4/user/experience/stats" public static final USER_FEEDBACK_COMMENT:Ljava/lang/String; = "v4/user/comments" public static final USER_INVITE:Ljava/lang/String; = "v4/user/invite" public static final USER_INVITE_ACCEPT:Ljava/lang/String; = "v4/user/invite/{invid}/accept" public static final USER_INVITE_ID:Ljava/lang/String; = "v4/user/invite/{invid}" public static final USER_INVITE_ID_PREFIX:Ljava/lang/String; = "v4/user/invite/" public static final USER_LOGIN_LOCATION:Ljava/lang/String; = "v4/user?location=true" public static final USER_PASSWORD_CHANGE:Ljava/lang/String; = "v4/user/password/change" public static final USER_PASSWORD_RESET_REDEEM:Ljava/lang/String; = "v4/user/password/reset/redeem" public static final USER_PASSWORD_RESET_REQUEST:Ljava/lang/String; = "v4/user/password/reset/request" public static final USER_PHONE:Ljava/lang/String; = "v4/user/phone" public static final USER_PHONE_VERIFY:Ljava/lang/String; = "v4/user/phone/verify" public static final USER_PUSH:Ljava/lang/String; = "v4/user/push" public static final USER_SERVICES_AYLA_ADD:Ljava/lang/String; = "v4/user/services/ayla/add"        value = "v4/user/consent/{id}/{ack}"        value = "v4/user/services/ayla/add"        value = "v4/user/comments"        value = "v4/location/{locid}/arm"        value = "v4/location/{locid}/ayladevice"        value = "v4/location/{locid}/device"        value = "v4/location/{locid}/event/{eventid}/media"        path = "v4/location/{locid}/event"        value = "v4/location/{locid}/device/{devid}/cancel"        value = "v4/location/{locid}/subscription/cancel"        value = "v4/location/{locid}/device/{devid}/capture"        value = "v4/location/{locid}/subscription"        value = "v4/user/password/change"        value = "v4/location/{locid}/invite"        value = "v4/location"        value = "v4/location/{locid}/subscription"        value = "v4/user"        value = "v4/user/avatar"        value = "v4/user/billing"        value = "v4/location/{locid}/device/{devid}"        value = "v4/location/{locid}"        value = "v4/location/{locid}/member/{userid}"        value = "v4/location/{locid}/member/{userid}"        value = "v4/location/{locid}/disarm"        value = "v4/user/phone"        value = "v4/location/{locid}/away"        value = "v4/location/{locid}/home"        value = "v4/upload/logs"        value = "v4/ayla/device/latest/register"        value = "v4/ayla/device/{dsn}/register"        value = "v4/user/billing"        value = "v4/airquality"        value = "v4/location/{locid}/device/{devid}"        value = "v4/device/{devid}/stats"        value = "v4/location"        value = "v4/user"        value = "v4/user/consent"        value = "v4/user/consents"        value = "v4/user/invite"        value = "v4/firmware"        value = "v4/location/{locid}"        value = "v4/location/{locid}/device"        value = "v4/location/{locid}/event"        value = "v4/location/{locid}/member"        value = "v4/location/{locid}/room"        value = "v4/location/{locid}/subscription?meta=true"        value = "v4/location/{locid}/zone"        value = "v4/sign"        value = "v4/location/{locid}/device/{devid}/otastatus"        value = "v4/user/experience/stats"        value = "v4/user?location=true"        value = "v4/location/{locid}/subscription?meta=true"        value = "v4/auth/google"        value = "v4/location/{locid}/device/{devid}/hush"        value = "v4/location/{locid}/device/{devid}/identify"        value = "v4/location/{locid}/device/{devid}/identifycancel"        value = "v4/invite/{code}/accept"        value = "v4/user/invite/{invid}/accept"        value = "v4/invite/{code}"        value = "v4/user/invite/{invid}"        value = "v4/location/{locid}/device/{devid}/join"        value = "v4/location/{locid}/invite"        value = "v4/location/{locid}/device/{devid}/locate"        value = "v4/auth/login"        value = "v4/auth/logout"        value = "v4/location/{locid}/device/{devid}"        value = "v4/location/{locid}/invite/{invid}"        value = "v4/location/{locid}"        value = "v4/location/{locid}/member/{userid}"        value = "v4/user"        value = "v4/user/email/change"        value = "v4/user/phone"        value = "v4/location/{locid}/event"        value = "v4/location/{locid}/subscription/preview"        value = "v4/location/{locid}/subscription/reactivate"        value = "v4/location/{locid}/device/{devid}/recalibrate"        value = "v4/user/password/reset/redeem"        value = "v4/user/email/resend"        value = "v4/user/email/resend"        value = "v4/user/password/reset/request"        value = "v4/location/{locid}/event/{eventid}/resolve"        value = "v4/location/{locid}/resolve"        value = "v4/location/{locid}/invite/{invid}"        value = "v4/user/push"        value = "v4/user/billing"        value = "v4/user/experience/stats"        value = "v4/location/{locid}/event/{eventid}/silence"        value = "v4/location/{locid}/silence"        value = "v4/location/{locid}/device/{devid}/test"        value = "v4/location/{locid}/device/{devid}/otaupgrade"        value = "v4/user/avatar"        value = "v4/user/email/verify"        value = "v4/user/phone/verify"    const-string v5, "v4/user"    const-string v0, "v4/user/push"    const-string v0, "v4/user/avatar"    const-string v0, "v4/user/email/change"    const-string v0, "v4/user/email/resend"    const-string v0, "v4/user/email/verify"    const-string v0, "v4/user/password/change"    const-string v0, "v4/user/password/reset/request"    const-string v0, "v4/user/password/reset/redeem"    const-string v0, "v4/user/consent/"    const-string v0, "v4/user/consents"    const-string v0, "v4/user/consent"    const-string v0, "v4/user/invite"    const-string v2, "v4/user/invite/"    const-string v0, "v4/user/phone/verify"    const-string v0, "v4/user/phone"    const-string v0, "v4/user/billing"    const-string v0, "v4/user/services/ayla/add"    const-string v5, "v4/authorize"    const-string v5, "v4/token"    const-string v5, "v4/firmware"    const-string v5, "v4/auth/"    const-string v0, "v4/auth/login"    const-string v0, "v4/auth/google"    const-string v0, "v4/auth/logout"    const-string v5, "v4/ayla/"    const-string v0, "v4/ayla/device/latest/register"    const-string v0, "v4/ayla/device/"    const-string v5, "v4/location"    const-string v0, "v4/invite/"

Not adding anything new, but a gist containing a jupyter notebook with the steps already described above.

Thanks for the tips everyone.

During login I got a notification on my Kidde app, needing to allow new login. I wonder if the access token expires and a new login is needed - then a new notification would probably pop up

Threw a Python wrapper together and a quick integration to use it. Working on adding the logo to the brands repo. Not sure if everything is working but have to sign off for a bit and wanted to put this out there. Needs a lot of work to even be ready for HACS, let alone adding to HomeAssistant itself.