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

node-chargepoint

v0.9.0

Published

A Node.js/TypeScript wrapper for the ChargePoint EV charging network API. Based on python-chargepoint by Marc Billow.

Readme

node-chargepoint

Pre-release Not production ready

Warning: This library is in pre-release and is not ready for production use. The API is unstable and may change without notice between versions.

A simple, async Node.js/TypeScript wrapper around the ChargePoint EV Charging Network API.

Based on python-chargepoint by Marc Billow (MIT).

Disclaimer

This project is not affiliated with or endorsed by ChargePoint in any way. Use at your own risk. ChargePoint is a registered trademark of ChargePoint, Inc.


Installation

pnpm add node-chargepoint

Requires Node.js ≥ 24.


Library Usage

All client methods are async and return Promises.

Authentication

Three authentication methods are supported. The client is created via the async factory ChargePoint.create().

Password:

import { ChargePoint } from 'node-chargepoint';

const client = await ChargePoint.create('[email protected]');
await client.loginWithPassword('password');
// ...
await client.logout();

Long-lived session token (recommended for automation):

const client = await ChargePoint.create('[email protected]', {
  coulombToken: '<coulomb_sess cookie value>',
});

SSO JWT:

const client = await ChargePoint.create('[email protected]');
await client.loginWithSsoSession('<sso jwt>');

Obtaining Tokens Manually

Password-based login may be blocked by bot-protection (Datadome). When that happens, you can capture a token directly from your browser and pass it to the client.

  1. Open https://driver.chargepoint.com in your browser and log in normally.
  2. Open Developer Tools and navigate to Application > Cookies > https://driver.chargepoint.com.
  3. Copy the value of one of the following cookies:

| Cookie | Use as | |---|---| | coulomb_sess | coulombToken: option (recommended — long-lived) | | auth-session | loginWithSsoSession() (shorter-lived JWT) |

Note: The coulomb_sess value contains # and ? characters. When setting it as a shell environment variable, always wrap the value in double quotes to prevent the shell from interpreting # as a comment:

export CP_TOKEN="Ab3dEf...token...#D???????#RNA-US"

Account

const account = await client.getAccount();
console.log(account.user.fullName);          // "Jane Smith"
console.log(account.accountBalance.amount);  // 12.34

const vehicles = await client.getVehicles();
for (const ev of vehicles) {
  console.log(`${ev.year} ${ev.make} ${ev.model}`);     // "2023 Polestar 2"
  console.log(`  AC: ${ev.chargingSpeed} kW  DC: ${ev.dcChargingSpeed} kW`);
}

Home Charger

const chargerIds = await client.getHomeChargers();
// [12345678]

const chargerId = chargerIds[0];

const status = await client.getHomeChargerStatus(chargerId);
// {
//   chargerId: 12345678,
//   brand: 'CP',
//   model: 'HOME FLEX',
//   chargingStatus: 'AVAILABLE',
//   isPluggedIn: true,
//   isConnected: true,
//   amperageLimit: 28,
//   possibleAmperageLimits: [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]
// }

const tech = await client.getHomeChargerTechnicalInfo(chargerId);
// {
//   modelNumber: 'CPH50-NEMA6-50-L23',
//   serialNumber: '...',
//   softwareVersion: '1.2.3.4',
//   lastConnectedAt: '2024-06-01T08:30:00Z'
// }

const config = await client.getHomeChargerConfig(chargerId);
// {
//   stationNickname: 'Home Flex',
//   ledBrightness: { level: 5, supportedLevels: [0,1,2,3,4,5] },
//   utility: { name: 'Austin Energy', ... }
// }

Amperage limit

// Print valid amperage values
console.log(status.possibleAmperageLimits);
// [20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]

await client.setAmperageLimit(chargerId, 24);

LED brightness

Levels map to: 0=off, 1=20%, 2=40%, 3=60%, 4=80%, 5=100%. Available levels are returned by getHomeChargerConfig().

await client.setLedBrightness(chargerId, 3);  // 60%

Restart

await client.restartHomeCharger(chargerId);

Charging schedule

const schedule = await client.getHomeChargerSchedule(chargerId);
console.log(schedule.scheduleEnabled);                      // false
console.log(schedule.defaultSchedule.weekdays.startTime);   // "23:00"
console.log(schedule.defaultSchedule.weekdays.endTime);     // "07:00"
console.log(schedule.defaultSchedule.weekends.startTime);   // "19:00"
console.log(schedule.defaultSchedule.weekends.endTime);     // "15:00"

// Enable a schedule
const updated = await client.setHomeChargerSchedule(
  chargerId,
  '23:00', '07:00',  // weekday start, weekday end
  '19:00', '15:00',  // weekend start, weekend end
);
console.log(updated.scheduleEnabled);  // true

// Disable the schedule
await client.disableHomeChargerSchedule(chargerId);

Schedule window utilities

Two pure helper functions are exported for evaluating schedule windows without an extra API call.

getActiveScheduleWindow(schedule, date?)

Resolves the window that is currently active from a HomeChargerSchedule. Returns null when scheduleEnabled is false — the signal that the ChargePoint schedule should be ignored and your own logic applied.

Priority when multiple schedules exist: userScheduleutilityScheduledefaultSchedule. Automatically selects the weekday or weekend window based on date (defaults to now).

isWithinChargeScheduleWindow(window, date?)

Returns true if the time component of date (defaults to now) falls within the given ChargeScheduleWindow. Handles midnight-crossing windows (e.g. 22:0006:00). Start is inclusive, end is exclusive.

TOU / off-peak charging — check the ChargePoint schedule:

import { getActiveScheduleWindow, isWithinChargeScheduleWindow } from 'node-chargepoint';

const schedule = await client.getHomeChargerSchedule(chargerId);
const window = getActiveScheduleWindow(schedule);

if (window && isWithinChargeScheduleWindow(window)) {
  // within the configured off-peak window — ok to charge
}

Solar / custom scheduling — ChargePoint schedule is off, apply your own window:

const schedule = await client.getHomeChargerSchedule(chargerId);
const window = getActiveScheduleWindow(schedule);

if (!window) {
  // ChargePoint schedule is disabled — use your own time window
  const solarWindow = { startTime: '7:00', endTime: '19:00' };
  if (isWithinChargeScheduleWindow(solarWindow)) {
    // sun is up — ok to charge from solar
  }
}

Note: HomeChargerStatus.isDuringScheduledTime is the ChargePoint API's own evaluation of the configured off-peak schedule. Use getActiveScheduleWindow + isWithinChargeScheduleWindow instead when you need to check a custom window (solar hours, time-of-day rules, etc.) independently of TOU pricing.


Charging Status and Sessions

Home charger sessions (recommended)

getHomeChargerSession(chargerId) resolves the active session for a home charger regardless of how it was started — including sessions started manually in the ChargePoint app, auto-started on plug-in, or started via this library.

const [chargerId] = await client.getHomeChargers();

const session = await client.getHomeChargerSession(chargerId);
if (session) {
  console.log(session.chargingState);  // "CHARGING"
  console.log(session.energyKwh);     // 6.42
  console.log(session.powerKw);       // 7.2
  await session.stop();
}

Returns null when the charger is not actively charging or no session can be resolved.

Resolution order:

  1. Device plane — reads the session id from getHomeChargerStatus when the device API surfaces it (app-started, auto-started, and RFID sessions).
  2. Driver plane fallback — calls getUserChargingStatus for driver-authenticated sessions (started via this library's startChargingSession).

getHomeChargerStatus also surfaces optional live telemetry fields when the device API includes them: sessionId, energyKwh, powerKw, and sessionStartTime.

Driver-plane vs device-plane identity: getUserChargingStatus() is the driver plane and is only populated for sessions bound to the current authenticated context (API-started or driver-authenticated sessions). The device plane (getHomeChargerStatus) reflects the physical charger state and surfaces sessions regardless of how they were started. Use getHomeChargerSession as the primary path for home charger session management.

Driver-plane status

const status = await client.getUserChargingStatus();
if (status) {
  console.log(status.state);      // "CHARGING"
  console.log(status.sessionId);  // 1234567890

  const session = await client.getChargingSession(status.sessionId);
  console.log(session.chargingState);  // "CHARGING"
  console.log(session.energyKwh);     // 6.42
  console.log(session.milesAdded);    // 22.3
}

Starting and stopping a session

// Start a new session on any device
const newSession = await client.startChargingSession(deviceId);
console.log(newSession.sessionId);

// Stop by device ID — no session object needed
await client.stopChargingSession(deviceId);

// Or stop via a session object
const session = await client.getChargingSession(status.sessionId);
await session.stop();

stopChargingSession(deviceId) is the device-level stop symmetric with startChargingSession. It stops the active session on the device without requiring you to fetch a session first. If the charger is currently busy (e.g. mid-handshake), a ChargerBusyError is thrown — see Error Handling.


Station Info

Fetch detailed information about any station by device ID — ports, pricing, connector types, and real-time status.

const info = await client.getStation(13055991);
console.log(info.name.join(' / '));    // "DOMAIN TOWER 2 / LVL 2_STATION 2"
console.log(info.address.address1);   // "10025 Alterra Pkwy"
console.log(info.stationStatusV2);    // "available"
console.log(info.portsInfo.totalCount);  // 2

for (const port of info.portsInfo.ports) {
  console.log(`Port ${port.outletNumber}: ${port.statusV2} (Level ${port.level})`);
  for (const c of port.connectorList) {
    console.log(`  ${c.displayPlugType}: ${c.statusV2}`);
  }
}

if (info.stationPrice) {
  for (const tou of info.stationPrice.touFees) {
    console.log(`Rate: ${tou.price} ${info.stationPrice.currencyCode}`);
  }
}

Nearby Stations

Fetch all charging stations visible within a geographic bounding box.

import type { MapFilter, ZoomBounds } from 'node-chargepoint';

const bounds: ZoomBounds = {
  swLat: 30.37, swLon: -97.66,
  neLat: 30.40, neLon: -97.64,
};

// No filter — return all stations
const stations = await client.getNearbyStations(bounds);

// Optional: filter by connector type or status
const filter: MapFilter = {
  connectorL2: true,
  connectorCombo: true,
  statusAvailable: true,
};
const filtered = await client.getNearbyStations(bounds, filter);

for (const s of filtered) {
  console.log(`${s.name1} — ${s.stationStatusV2}`);
  if (s.isHome && s.chargingInfo) {
    console.log(`  Charging: ${s.chargingStatus}`);
  }
}

MapFilter fields (all boolean, all optional):

| Field | Description | |---|---| | connectorL2 | Level 2 AC | | connectorCombo | CCS combo (DC) | | connectorChademo | CHAdeMO (DC) | | connectorTesla | Tesla proprietary | | connectorL1 | Level 1 AC | | connectorL2Tesla | Tesla Level 2 | | connectorL2Nema1450 | NEMA 14-50 | | dcFastCharging | Any DC fast charger | | statusAvailable | Only available stations | | priceFree | Only free stations | | vanAccessible | Van-accessible spaces | | disabledParking | Disability-accessible parking | | networkChargepoint | ChargePoint network | | networkEvgo | EVgo network |


CLI

See docs/cli.md for usage, commands, and global options.


Error Handling

See docs/error-handling.md for the error class hierarchy and handling examples.


Development

See docs/development.md for setup, tests, E2E tests, and build instructions.