npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

homebridge-smartthings-scenes

v1.0.1

Published

Expose SmartThings scenes (aka Routines) as Switch accessories for Home app automations.

Readme

homebridge-smartthings-scenes

Expose Samsung SmartThings scenes as Switch accessories in Homebridge (the plugin calls POST /v1/scenes/{sceneId}/execute). Use them in Home automations—for example: When [Routine switch] turns On → your SmartThings scene runs.

On startup the plugin logs all scenes (GET /v1/scenes, merged global and per-location lists); each switch runs the matching scene by name (or optional sceneId).

Two separate steps

| Step | Where | What you do | |------|--------|----------------| | 1. One-time OAuth setup | Your own computer (any machine with Node; not Homebridge-specific) | Start the OAuth helper, open its web form at http://127.0.0.1:38400/, and follow the steps there with ngrok and the SmartThings CLI to create the app and obtain Client ID, Client Secret, access token, and refresh token. Use the form’s Exchange code (via this server) for tokens (optional curl fallback). | | 2. Plugin configuration | Homebridge—usually the web UI (Homebridge UI / Config UI X) | Open this plugin's settings and copy/paste those values into the matching fields, add your routine names, and save. Homebridge runs the plugin only; it does not run the Express OAuth server for normal operation. |

OAuth gives long-lived access. SmartThings requires an HTTPS redirect URI for registration (not localhost), which is why the one-time step uses ngrok (or similar) to reach the local helper.


Requirements

  • A SmartThings account with scenes you want to run from Home (names must match what the API returns—see startup logs)
  • ngrok (or equivalent) for HTTPS during OAuth setup
  • Node.js (see package.json engines)

The SmartThings CLI is needed to create the OAuth app. Install is optional: use npx @smartthings/cli … (downloads the CLI on demand) or install globally / via Homebrew—see SmartThings CLI — Get started. Authentication uses the CLI's browser login when a command needs your account (or a Personal Access Token in config—see those docs).


Install the plugin

npm install -g homebridge-smartthings-scenes

If you use Homebridge Config UI X, you can search for the plugin and install it from the UI instead.


What the plugin needs for SmartThings API calls

The plugin talks to Samsung's REST API (GET /v1/scenes to list scenes, POST /v1/scenes/{sceneId}/execute to run one). Everything required for authentication and for choosing which routines to run is set in the plugin config (Homebridge UI or config.json).

Fixed in code (not configurable)

| Item | Value | |------|--------| | API | https://api.smartthings.com/v1 (locations, scenes) | | OAuth token endpoint | https://api.smartthings.com/oauth/token (used for authorize + refresh) |

You do not need to enter URLs for those unless we add optional overrides in a future version.

Set in plugin config (typical copy-paste setup)

| Config key | Used for | |------------|----------| | clientId | OAuth client id — required to refresh the access token | | clientSecret | OAuth client secret — required for refresh | | accessToken | Bearer token on every SmartThings API request (Authorization: Bearer …) | | refreshToken | Refresh token grant with client id/secret when the access token expires | | tokenExpiresInSeconds | Recommended. Paste expires_in from the token response (e.g. 86399) so the plugin knows when to refresh. Stays valid across token refreshes (each new access token uses the same typical lifetime). | | routines | Required. Which scenes to expose; each entry is { "name": "…" } (scene name) or { "name": "…", "sceneId": "…" } to skip name lookup |

Together, client id + secret + access token + refresh token are what SmartThings expects for ongoing API access and token renewal. After a successful first start, tokens may be stored on disk (smartthings-tokens.json under your Homebridge storage path); you can keep accessToken / refreshToken in config or rely on the file—see below.

Optional (different setup path)

| Config key | Used for | |------------|----------| | redirectUri | Only if you do not paste tokens and instead use the plugin's browser OAuth flow (ngrok + port 38521). Not needed when you use the OAuth helper web form and paste tokens into Homebridge. |

Summary

For invoke scene via API after your one-time OAuth setup, put clientId, clientSecret, accessToken, refreshToken, tokenExpiresInSeconds (recommended), and routines in the plugin configuration. That is the full set of values the plugin reads to authenticate and call the Scenes API.


One-time setup: SmartThings OAuth app and tokens

Do this once on a machine where you can run Node, ngrok, and the CLI (your laptop is fine; it does not have to be the Homebridge host). Primary path: use the OAuth helper web form in your browser—do not rely on hand-built URLs or terminal curl unless you prefer to.

When you are done, copy the values into the plugin in the Homebridge UI.

  1. Run the local OAuth helper (see below), expose it with ngrok, and open http://127.0.0.1:38400/ (the web form).
  2. Fill in the form (ngrok URL, Client ID / Secret from the CLI) and use the SmartThings CLI to create the OAuth-In App with the Target URL and Redirect URI the form shows.
  3. In the browser: confirm the webhook (confirmation URL), then authorize the app using the form’s OAuth authorize URL (Open in new tab—see §5).
  4. In the web form, Exchange code (via this server) to turn the authorization code into access and refresh tokens (see §6). Alternative: curl if you want a manual copy-paste flow.
  5. In the Homebridge web UI, open Plugins → this plugin settings (or edit JSON) and paste Client ID, Client Secret, access token, and refresh token into the fields described below.

Which Samsung / SmartThings account to use in the browser

Whenever a step opens smartthings.com or asks you to sign in with Samsung (CLI flow, confirmation link, or OAuth redirect), use the same Samsung account you use for the SmartThings mobile app on your phone (iOS or Android). That login is your SmartThings identity: locations, devices, and manually-run routines all live under that account.

If you have more than one Samsung account, pick the one that actually has your SmartThings home and routines—not a work-only or unused Samsung ID.

Why a local server?

Samsung's Developer Workspace "Register app" flow targets Lambda or webhooks, which does not match what this plugin needs. Creating an OAuth-In App with the CLI is the approach that works. SmartThings will POST to your app's Target URL (/smartthings) during registration and redirect the browser to your Redirect URI (/callback) after you authorize.

1) Start the OAuth helper and open the web form

The helper is a small Express app in the oauth-tools folder. It is included in this repository and in the published npm package. This is where you collect Client ID, Secret, authorize Samsung, and exchange the code for access + refresh tokens—work in the browser UI, not only on the command line.

If you cloned this repository (or downloaded the source):

cd /path/to/homebridge-smartthings-routines
npm install
npm run oauth-server

If you installed the plugin globally and did not clone the repo:

cd "$(npm root -g)/homebridge-smartthings-scenes"
npm run oauth-server

The default port is 38400. Override with SMARTTHINGS_OAUTH_PORT if needed. When the server starts, it opens this URL in your default browser; set OPEN_OAUTH_BROWSER=0 to skip (e.g. SSH without display).

If the browser did not open, go to http://127.0.0.1:38400/ manually. The web form (wizard) walks you through: ngrok URL, Target URL / Redirect URI for the CLI, OAuth authorize URL (with Open in new tab), Exchange code (via this server) for tokens (no browser CORS), optional curl copy, and a Homebridge JSON snippet.

When the server starts, it also prints step-by-step hints in the terminal.

2) Start ngrok

In another terminal:

ngrok http 38400

Use the HTTPS URL ngrok shows (for example https://abc123.ngrok-free.app). You will use:

  • Target URL: https://YOUR-NGROK-HOST/smartthings
  • Redirect URI: https://YOUR-NGROK-HOST/callback

3) Create the OAuth app (SmartThings CLI)

From the same machine where you run npm run oauth-server (repository root is fine). Current CLI versions do not ship a separate smartthings login command—sign-in happens in the browser when you run a command that needs your Samsung account.

npx --yes @smartthings/cli apps:create

(From a clone of this repo you can instead run npm run smartthings:apps:create, which runs the same npx command.)

When prompted:

| Prompt | Value | |--------|--------| | App type | OAuth-In App | | Display name | e.g. Homebridge Routines | | Description | Short description | | Target URL | https://YOUR-NGROK-HOST/smartthings | | Redirect URIs | https://YOUR-NGROK-HOST/callback | | Scopes | r:locations:* x:locations:* r:scenes:* x:scenes:* (read + execute for scenes; no w: write scopes—same string as in plugin auth.ts) |

If you change scopes on an existing OAuth app, run authorize + token exchange again so the new scopes are granted.

Save the Client ID and Client Secret immediately; the secret may not be shown again.

4) Confirm registration (webhook only)

Watch the terminal running the OAuth helper.

  • You should see a POST /smartthings payload. If SmartThings sends a confirmation URL, open it in a browser signed in with the same Samsung account as your SmartThings app (see Which Samsung / SmartThings account above).
  • A JSON body like {"targetUrl":"https://…/smartthings"} means webhook registration succeeded. There is no OAuth consent screen on this step—that is normal.

5) Authorize the app (OAuth — this is where you "allow" access)

This is a separate step. Confirming the webhook does not show the OAuth permission screen. You must open SmartThings' authorize URL so Samsung can redirect to your /callback with a code.

Recommended: in the web form, open wizard step 3 — URLs for the app & OAuth, use the OAuth authorize URL box, and click Open in new tab—the URL is built with the correct client_id, redirect_uri, and scopes.

Manual URL (advanced): with oauth-server still running and ngrok still pointing at the same port, open a new browser tab and visit (replace placeholders):

https://api.smartthings.com/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI_URL_ENCODED&scope=r%3Alocations%3A*%20x%3Alocations%3A*%20r%3Ascenes%3A*%20x%3Ascenes%3A*&state=anyrandomstring
  • YOUR_CLIENT_ID — from the CLI when you created the app (same as in Homebridge config later).
  • YOUR_REDIRECT_URI_URL_ENCODED — must match the Redirect URI you registered exactly, URL-encoded.
    Example: https://yttriferous-unmovable-cristen.ngrok-free.dev/callback
    https%3A%2F%2Fyttriferous-unmovable-cristen.ngrok-free.dev%2Fcallback

You can build the query string in one line with Node (run from any directory):

node -e "const p=new URLSearchParams({response_type:'code',client_id:'YOUR_CLIENT_ID',redirect_uri:'https://YOUR-NGROK-HOST/callback',scope:'r:locations:* x:locations:* r:scenes:* x:scenes:*',state:'x'}); console.log('https://api.smartthings.com/oauth/authorize?'+p)"

Paste the printed URL into the browser. You should get Samsung / SmartThings sign-in (if needed) and a screen to approve the requested permissions. Then the browser is redirected to https://YOUR-NGROK-HOST/callback?code=... — your OAuth helper terminal logs that code.

6) Exchange the code for tokens

Use the web form: in the OAuth helper page, wizard step 5 — Exchange code for tokens, click Exchange code (via this server). The browser sends your credentials to the local Express server, which calls SmartThings (POST /oauth/token) and puts the JSON response in the text area (no browser CORS). On success, the form can apply tokens to the Homebridge JSON snippet; copy access_token, refresh_token, and expires_in into the plugin config.

Optional — curl: if you prefer the terminal, use curl from the same machine (the form shows the exact command):

Replace placeholders with your values. redirect_uri must match the Redirect URI exactly (URL-encoded).

curl -X POST "https://api.smartthings.com/oauth/token" \
  -u "CLIENT_ID:CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code=CODE_FROM_CALLBACK&redirect_uri=ENCODED_REDIRECT_URI"

The JSON response includes access_token, refresh_token, and expires_in. Copy those into Homebridge (or use the paste flow in the web form).


Configure Homebridge (web UI or JSON)

Recommended: use the Homebridge web interface (e.g. Homebridge UI / Config UI X). Install the plugin from the Plugins tab, then open this plugin's settings form. Each field matches the values from the one-time setup—paste Client ID, Client Secret, Access token, Refresh token, and optionally Token expiry (seconds) (expires_in from the OAuth helper token JSON or curl response, often 86399). Add Routines with names that match your SmartThings scene names (same strings as in the startup log).

You do not need to run the OAuth Express server on your Homebridge machine for day-to-day use.

Editing config.json directly

If you prefer raw JSON, add a platform block to ~/.homebridge/config.json (or the path your UI uses). Use the exact scene names from the SmartThings app (Automation → Scenes, or as listed at startup).

{
  "platforms": [
    {
      "name": "SmartThings Routines",
      "platform": "SmartThingsRoutines",
      "clientId": "YOUR_CLIENT_ID",
      "clientSecret": "YOUR_CLIENT_SECRET",
      "accessToken": "YOUR_ACCESS_TOKEN",
      "refreshToken": "YOUR_REFRESH_TOKEN",
      "tokenExpiresInSeconds": 86399,
      "routines": [
        { "name": "Good Morning" },
        { "name": "Good Night" }
      ]
    }
  ]
}
  • clientId / clientSecret — From the OAuth app; required so the plugin can refresh the access token.
  • accessToken / refreshToken — From the OAuth helper Exchange code response (or curl). On first successful start, the plugin may copy them to smartthings-tokens.json under your Homebridge storage path; you can remove them from the UI/config afterward if you prefer secrets only on disk.
  • tokenExpiresInSeconds — Recommended: expires_in from the token response (often 86399). Does not need updating when tokens refresh.

Optional: browser OAuth from Homebridge (no pasted tokens)

If you omit accessToken and refreshToken, you can set redirectUri to your HTTPS callback (for example https://YOUR-NGROK-HOST/callback) and start Homebridge on a machine where a browser can open. The plugin runs a small local callback server on port 38521 and can open SmartThings login—point ngrok at 38521 for that flow (different from the OAuth helper on 38400).

After linking, restart Homebridge when prompted. Most users will use the copy-paste flow above instead.


Configuration reference

Same fields appear in the Homebridge UI plugin form and in config.json. Paste values from the one-time OAuth setup.

| Field | Required | Description | |-------|----------|-------------| | name | Yes | Platform display name | | platform | Yes | Must be SmartThingsRoutines (set automatically in the UI) | | clientId | Yes | OAuth app client ID (CLI) | | clientSecret | Yes | OAuth app client secret | | routines | Yes | At least one routine to expose | | accessToken | No* | Paste with refreshToken from the OAuth helper token JSON or curl | | refreshToken | No* | Paste with accessToken | | tokenExpiresInSeconds | No | OAuth expires_in (seconds), e.g. 86399 — stable across refreshes | | redirectUri | For in-plugin OAuth only | HTTPS callback; omit if using pasted tokens |

*If both access and refresh are omitted, set redirectUri and use the in-plugin browser flow instead.

Each routine object:

  • name (required) — Must match a scene name from the startup log ([scene] …).
  • sceneId (optional) — If name matching fails, paste the UUID from logs or the SmartThings API to skip lookup.

Usage in the Home app

Each routine appears as a Switch. Example automation:

  • When: [Your routine] turns On
  • Then:

The switch returns to Off after a short delay so automations can trigger "turn on" again later.


Troubleshooting

apiOnly.targetUrl is malformed / PatternError (HTTP 422) when creating the OAuth-In app

SmartThings validates the Target URL with a strict pattern. The CLI shows this when you finish Create OAuth-In SmartApp.

Check the following:

  1. Scheme — Must be https:// (not http://). No spaces before or after the URL.
  2. Paste exactly what ngrok prints — e.g. https://abc123.ngrok-free.app (your subdomain will differ). Do not add quotes in the CLI prompt.
  3. Path — Use the callback path this plugin expects, with no trailing slash:
    https://YOUR-NGROK-HOST/smartthings
    If it still fails, try the same URL with a trailing slash (/smartthings/)—some validators are picky (use one style consistently everywhere: Target URL, Redirect URI, and later curl redirect_uri).
  4. ngrok domain — Free tunnels sometimes use *.ngrok-free.app or *.ngrok-free.dev. If one is rejected, start a new tunnel and try the other style, or use a reserved ngrok domain so the hostname stays stable and conventional.
  5. OAuth helper runningnpm run oauth-server must be up before registration so SmartThings can POST to /smartthings (validation may still fail with PatternError if the URL string alone is invalid—fix the URL first).

If the error persists, open the URL in a browser as https://YOUR-HOST/smartthings — you should not need a pretty page; you only need the tunnel to hit your local server. Then re-run npx --yes @smartthings/cli apps:create and enter the same Target URL again carefully.

redirect_uri could not be validated

The redirect URI in your OAuth app, in the curl -d string, and in config (if used) must match exactly (including trailing slashes, host, and HTTPS).

SmartThings CLI: invalid URL / undefined/apps

Some CLI versions need ~/.config/smartthings/config.yaml. See the CLI documentation or try:

default:
  clientIdProvider:
    baseURL: 'https://api.smartthings.com'
    baseOAuthInURL: 'https://oauthin-regional.api.smartthings.com/oauth'
    oauthAuthTokenRefreshURL: 'https://api.smartthings.com/oauth/token'
    clientId: 'd18cf96e-c626-4433-bf51-ddbb10c5d1ed'

Then run npx --yes @smartthings/cli apps:create again.

No scenes from the API (empty scene list on startup)

The plugin merges GET /v1/scenes (global) with per-location scene lists. If you see no scenes:

  • Create or use scenes in the SmartThings app (Automation → Scenes, or equivalent).
  • Use the same Samsung account in the app as the one used for OAuth.
  • Token scopes must include r:scenes:* and x:scenes:* for listing and execution; match auth.ts.

Routine not found

Use the exact scene name from the startup log ([scene] Name — uuid). The plugin logs available scene names when a match fails.

Port already in use

  • OAuth helper default: 38400 (override with SMARTTHINGS_OAUTH_PORT).
  • In-plugin OAuth callback: 38521 — use ngrok http 38521 only for that flow.

Development

git clone https://github.com/davidjgonzalez/homebridge-smartthings-routines.git
cd homebridge-smartthings-routines
npm install
npm run build
npm link
homebridge -D

With debug enabled (-D or "debug": true in Homebridge config), startup logs include raw JSON for each GET /v1/scenes page (global and per-location) under [SmartThings raw scenes].


License

See LICENSE.