Integration steps

Your app needs to let users link both their vehicle and charger through LinkUI. Your backend requests separate link sessions for each device type.

Linking a charger works the same as linking a vehicle. The only difference is the scopes you request when generating the token. See Scopes referenceAPI for the full list.

Recommended flow:

  1. Link the vehicle. Request a linkToken with vehicle scopes (vehicle:read:data, vehicle:read:location, vehicle:control:charging). Open LinkUI with this token. See the LinkUI Developer Guide for details.
  2. Prompt for the charger. After the vehicle links successfully, prompt the user to link their charger. Explain the benefits: smart charging for otherwise incapable vehicles, or improved reliability. See UX Recommendations.
  3. Link the charger. Request a new linkToken with charger scopes (charger:read:data, charger:control:charging). Open a second LinkUI session.

Copy linkStep 2: Set the charging location for chargers

Associate the charger with a Location to know where the vehicle is charging. This is useful when the vehicle lacks GPS or when you need to verify charging happens at the user's home.

  1. Create a Location. POST to /locationsAPI with the user's coordinates. This returns a locationId.
  2. Assign it to the charger. PUT to /chargers/{chargerId}API with the locationId.

Copy linkStep 3: Use the Vehicle API for data and controls

Once both devices are linked to the same user, we establish the pair automatically. Data and controls surface through the Vehicle API.

Copy linkBasics

  • pluggedInChargerId appears when the vehicle is plugged into a linked charger. It's null otherwise.
  • The vehicle can charge elsewhere (public charging, unlinked chargers). We still return live vehicle data; pluggedInChargerId is just null.
  • The Charger API shows the inverse via pluggedInVehicleId.

Copy linkUnlocked capabilities

The paired charger enables capabilities on the vehicle:

  • chargeRate falls back to the charger's value if the vehicle doesn't report it
  • startCharging, stopCharging, and location become isCapable: true. Associated interventions are suppressed.
  • For vehicles without GPS, location is inferred from the charger

These capabilities persist once both devices are linked. We clear them when the pair is no longer valid (for example, after repeated failed commands while unplugged). When plugged back in, the pair re-establishes automatically.

Copy linkSending commands

Use the Vehicle API for charging commands:

Commands work the same whether the vehicle is plugged into the paired charger, a different charger, or unplugged. We route them to the right device.

Copy linkFailure reasons

When a charging action fails (FAILED or CANCELLED), the response includes a failureReason:

  • failureReason.type: Machine-readable error category
  • failureReason.detail: Human-readable explanation of what went wrong

Example Vehicle API response

GET /vehicles/{vehicleId}

{
  "id": "05ee9df5-d072-4ee8-b773-399dec8f5693",
  "userId": "bb28471e-cde6-4eff-ace4-9a7f4f50882a",
  "vendor": "TESLA",
  "lastSeen": "2024-01-07T17:04:26.000Z",
  "isReachable": true,
  "information": {
    "vin": "2HGFB2F5XEH542858",
    "model": "Model S P85",
    "year": 2020
  },
  "chargeState": {
    "batteryLevel": 66,
    "range": 228,
    "batteryCapacity": 48.1,
    // EV Pair: When available, the chargeRate from the charger
    // is returned if it is not provided by the vehicle
    "chargeRate": 2.3,
    "chargeTimeRemaining": 285,
    "lastUpdated": "2020-04-07T17:04:26Z",
    "maxCurrent": 16,
    "powerDeliveryState": "PLUGGED_IN:CHARGING",
    // EV Pair: Will be "null" when not currently
    // plugged into a charger
    "pluggedInChargerId": "07f8368d-be7e-4dbd-8cf0-94d00dd67ad3"
  },
  "capabilities": {
    "information": {
      "isCapable": true,
      "interventionIds": []
    },
    "chargeState": {
      "isCapable": true,
      "interventionIds": []
    },
    "odometer": {
      "isCapable": false,
      "interventionIds": ["4eaeb363-296d-4ccc-a973-7805e6f400bd"]
    },
    "setMaxCurrent": {
      "isCapable": false,
      "interventionIds": []
    },
    // EV Pair: These capabilities are unlocked by the paired charger
    // and persist across charging sessions
    "startCharging": {
      "isCapable": true,
      "interventionIds": []
    },
    "stopCharging": {
      "isCapable": true,
      "interventionIds": []
    },
    "location": {
      "isCapable": true,
      "interventionIds": []
    }
  }
}

Example Charger API response

GET /chargers/{chargerId}

{
  ...
  "chargeState": {
    "isPluggedIn": true,
    "isCharging": true,
    "chargeRate": 2.3,
    "lastUpdated": "2020-04-07T17:04:26Z",
    "maxCurrent": 16,
    "powerDeliveryState": "PLUGGED_IN:CHARGING",
    // EV Pair: Will be "null" when not currently
    // plugged into a vehicle
    "pluggedInVehicleId": "05ee9df5-d072-4ee8-b773-399dec8f5693"
  }
  ...
}

Knowing when the vehicle is plugged in at the correct charging location

Subscribe to webhooks for the user:vehicle:updated event to receive notifications when vehicle state changes. When pluggedInChargerId and the expected location.id are returned, the vehicle is plugged in at the correct charging location.

Copy linkStep 4: Handle unified interventions

Interventions are user actions that unlock device capabilities. With EV Charger Pairing, the Vehicle API returns interventions from both the vehicle and charger. You don't need to query the Charger API separately.

Copy linkHow interventions appear

The Vehicle API response includes interventions from the vehicle and all linked chargers:

  • Charger interventions that unlock control or location capabilities appear first
  • If the charger can provide a capability, we suppress the vehicle's intervention for that capability
  • Interventions affecting chargeState from either device are always returned

Copy linkOptional interventions

Sometimes a vehicle can control charging on its own, but the linked charger cannot. In this case:

  • isCapable remains true on the vehicle
  • We return the charger's interventions anyway, marked as optional

Show optional interventions as recommended but not blocking.

Copy linkPresenting interventions to users

  1. Fetch interventions from capabilities.*.interventionIds
  2. Show them in the order returned
  3. Subscribe to user:vehicle:updated webhooks for changes
Read next: Testing your integration

Use Sandbox to test common EV Charger Pairing scenarios and understand known production edge cases

Was this article helpful?