@vyer-eco/ecoflow-embed-sdk
v0.1.0
Published
Browser SDK for embedding EcoFlow in a partner application
Downloads
104
Readme
EcoFlow Embed SDK
Browser SDK for embedding EcoFlow in a partner application.
Start here: PARTNER-GUIDE.md, which ships in this package, describes the whole integration — how your backend mints a session, every destination you can embed, and every error you can receive. This README covers the browser half only.
This is a
0.xrelease. The surface may still change in a breaking way; one such change is planned. Pin a version and read the release notes before upgrading.
What it does, and what it deliberately does not
The SDK navigates an iframe to the embed URL the platform returned — origin and path exactly as given, with the bootstrap token added to the query — and posts that token to the URL's origin once the frame has loaded. That is all of it.
Why the token is in the URL as well as in the message. It is a known leak (a URL reaches history,
Refererand server logs) and its removal is tracked separately. It cannot simply be deleted:postMessagefires on the iframe'sloadevent, while the embedded application registers its listener from a React effect after hydration — so the message can arrive before anything is listening, and apostMessagewith no listener is dropped, not queued. The query token is what makes the message a fallback rather than the only path. Removing it needs the embedded side to announce readiness first.
It holds no EcoFlow routes. You choose a destination by naming a target when your backend
generates the token; the platform resolves that name to a URL and returns it. An earlier version of
this SDK rebuilt the path itself from an internal table, which meant every integration held
EcoFlow's route strings and any internal rename would have broken all of them at once. That is gone
and has no replacement — a test fails the build if a route literal reappears here.
So: do not edit embedUrl. Pass it through unchanged. Its shape is internal and may change.
Two halves of the integration
| Half | Where it runs | How it is contracted | |---|---|---| | Minting a token | your backend, with the embedding key | PARTNER-GUIDE.md §3 | | Opening the session | the browser | this package |
Token minting stays server-to-server on purpose and is documented rather than wrapped, so the embedding key cannot end up in a browser bundle.
Usage
Your backend calls the token endpoint with a target:
POST /api/v1/partners/{partnerId}/embed-tokens
x-embedding-key: <your embedding key>
{
"customerId": "acme",
"userId": "user-1",
"email": "[email protected]",
"role": "editor",
"target": "workflow-editor",
"targetParameters": { "workflowId": "wf-123" }
}Targets: workflow-editor (parameters workflowId, showBackButton), workflow-list,
connection-list, run-list. An unsupported target is refused with 400 unsupported_target and no token is
issued — the error names what it refused and lists what it would accept.
Then, in the browser:
import { EcoFlowEmbedClient } from '@vyer-eco/ecoflow-embed-sdk';
const client = new EcoFlowEmbedClient({
iframe: document.getElementById('ecoflow-iframe'),
});
await client.startSession({
embedUrl: response.embedUrl, // pass through unchanged
externalToken: response.token,
});destroy() tears the session down and clears the frame.
Development
The bundle is built, never edited, and is not in version control — a hand-maintained dist/
with no source is how this package drifted a month behind the code it talks to.
npm install
npm run build # -> dist/ (ESM + .d.ts)
npm test # vitest
npm run type-checksrc/generated/ is also generated and gitignored. build, test and type-check each regenerate
it first, so it cannot be stale; a fresh checkout has no src/generated/ until you run one of them.
The bootstrap contract has one source
contract/embed-bootstrap-contract.json defines the message type, its version and its fields. The
SDK generates a module from it; the embedded application mirrors the same file under a test that
fails, naming both files and both values, if the two ever disagree. Edit the JSON, never one
side. They were once two separate literals that agreed only by coincidence.
