Partner Connect SDK
Promise-based JavaScript SDK for secure cross-origin communication between partner apps and LearnCard
The Partner Connect SDK transforms complex postMessage communication into clean, modern Promise-based functions. It handles the entire cross-origin message lifecycle, including request queuing, origin validation, and timeout management.
On this section
This page covers setup, configuration, and mock mode. For the rest of the SDK, see:
Methods — the full API reference: every method, its parameters, and examples
Errors, Types & Migration — error codes, advanced configuration, the migration guide, and TypeScript types
Features
🔒 Secure: Multi-layered origin validation prevents unauthorized access
🎯 Type-safe: Full TypeScript support with comprehensive type definitions
⚡ Promise-based: Modern async/await API eliminates callback complexity
🧹 Clean: Abstracts away all postMessage implementation details
📦 Lightweight: Zero runtime dependencies, ~8KB minified
🛡️ Robust: Built-in timeout handling and structured error management
🧪 Standalone-ready: Runs and demos on its own via automatic mock mode — no host required
Installation
Quick Start
Standalone / Mock Mode
The SDK only does real work when it's embedded inside LearnCard — that's what answers its requests. Run your app on its own (local dev, a preview deploy, tests) and there's nothing to answer. Standalone calls that aren't mocked reject immediately with LC_NOT_EMBEDDED (instead of hanging until the request timeout), plus a one-time console hint.
Mock mode fixes this automatically in local development. Whenever no LearnCard host is present and your app runs on a local dev host (localhost, 127.0.0.1, [::1], *.localhost, *.local), the SDK stands in for LearnCard so your app stays fully usable:
Every method shows a branded toast describing what would happen once embedded — e.g.
sendCredential→ "✅ In LearnCard, the user would receive [name] here",incrementCounter→ "Counter coins → 10",launchFeature→ "Would open /wallet". Strong, visible feedback for every call.requestConsent(...)grants automatically and shows a "mock consent" toast; counters (incrementCounter/getCounter/getCounters) save to the browser and survive reloads.Identical or polled calls coalesce into one toast with a ×N counter, so nothing spams the screen.
requestIdentity, notifications, learner context, and sync status return sensible placeholder data.Everything is also logged to the console with a
[LearnCard SDK · MOCK]prefix.
No flags, no separate build in local dev. Your app is demo-able locally and behaves exactly the same against the real host once embedded.
'auto' never mocks on production or remote preview origins. A real user opening your app's URL directly must never receive a fabricated identity or auto-granted consent. For remote deploy previews (Netlify, Lovable, Vercel, …) that should demo standalone anywhere but use the real host once embedded, opt in with mock: 'standalone'. For CI and tests that should always mock, use mock: true.
mock
Standalone, local dev
Standalone, remote origin
Embedded in LearnCard
'auto' (default)
mock
fail fast (LC_NOT_EMBEDDED)
real host
'standalone'
mock
mock
real host
true
mock
mock
mock
false
fail fast
fail fast
real host
If your app is embedded in something that isn't LearnCard (a cross-origin Storybook canvas, a preview shell), calls don't hang: the SDK mocks on local dev hosts and otherwise rejects fast with LC_NOT_EMBEDDED. When the parent can't be identified (Firefox, or a same-origin localhost wrapper), a one-time side-effect-free presence probe decides — the SDK only mocks if no host answers within hostProbeTimeout (default 1500 ms).
Every mocked call shows a labeled toast and a [LearnCard SDK · MOCK] console log, so it's clear the SDK is simulating rather than talking to a real host. For a production build meant to run only inside LearnCard, set mock: false — standalone calls then reject immediately with LC_NOT_EMBEDDED.
Overrides:
Use learnCard.isMocked() to check whether an instance is currently mocking.
The mock keeps a small session store, so reads reflect writes: after sendCredential(...), calls like checkUserHasCredential, getTemplateRecipients, requestLearnerContext, and askCredentialSearch return that credential — so happy-path UI actually lights up standalone. Use mockOptions.credentials / identity / counters to pre-populate state without performing an action first. Mock credentials are marked _mock: true and are never cryptographically valid.
Security Model
The Partner Connect SDK implements comprehensive security measures:
Origin Validation
Strict Enforcement:
Incoming messages must exactly match the configured host origin
No wildcard (
*) origins are ever usedQuery parameter overrides are validated against whitelist
Configuration Hierarchy:
Default:
https://learncard.app(security anchor)Query Parameter Override:
?lc_host_override=https://staging.learncard.appConfigured Origin: From
hostOriginoption
Example:
Message Security
Protocol Verification: Messages must match expected protocol version
Request ID Tracking: Only tracked requests are processed
Timeout Protection: Requests automatically timeout to prevent hanging
Cleanup on Destroy: Pending requests are properly rejected
Browser Support
Chrome/Edge: 90+
Firefox: 88+
Safari: 14+
Mobile: iOS Safari 14+, Android Chrome 90+
Required APIs:
postMessagePromiseURLSearchParamsaddEventListener
Related Documentation
Build an App Inside LearnCard - Step-by-step guide for App Store credential issuance
LearnCard Core SDK - Backend credential operations
LearnCard Network - Network integration
Connect a User's LearnCard to Your Platform - Integration guide
App Store Development - LearnCard app ecosystem
Last updated
Was this helpful?