Partner Connect SDK

Promise-based JavaScript SDK for secure cross-origin communication between partner apps and LearnCard

circle-info

Last verified against @learncard/partner-connect v0.2.16. When in doubt, the runtime types in packages/learn-card-partner-connect-sdk/src/types.ts and the Zod validators in @learncard/types (packages/learn-card-types/src/lcn.ts) are the source of truth.

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.

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

Installation

npm install @learncard/partner-connect

Quick Start

import { createPartnerConnect } from '@learncard/partner-connect';

// Initialize the SDK
const learnCard = createPartnerConnect({
    hostOrigin: 'https://learncard.app',
});

// Request user identity (SSO)
try {
    const identity = await learnCard.requestIdentity();
    console.log('User DID:', identity.user.did);
    console.log('JWT Token:', identity.token);
} catch (error) {
    if (error.code === 'LC_UNAUTHENTICATED') {
        console.log('User is not logged in');
    }
}

API Reference

Factory Function

createPartnerConnect(options?)

Creates a new Partner Connect SDK instance.

Parameters:

  • options (PartnerConnectOptions, optional): Configuration options. Defaults to { hostOrigin: 'https://learncard.app' }.

Returns: PartnerConnect instance

Example:

circle-info

You can also import and instantiate the PartnerConnect class directly:

Configuration

PartnerConnectOptions

Core Methods

requestIdentity()

Request user identity from LearnCard for Single Sign-On authentication.

Returns: Promise<IdentityResponse>

Example:

Response Type:

sendCredential(input)

Send a credential to the user's LearnCard wallet. Supports two modes:

Mode 1: Template-Based Issuance (Recommended for App Store Apps)

Issue a credential using a pre-configured boost template attached to your App Store listing. LearnCard handles signing and delivery.

Parameters:

  • input (TemplateCredentialInput): Template alias and optional data

Returns: Promise<TemplateCredentialResponse>

Mode 2: Raw Credential

Send a pre-signed verifiable credential directly. Your backend must issue and sign the credential first.

Parameters:

  • input (unknown): A signed verifiable credential object

Returns: Promise<SendCredentialResponse>

circle-info

For App Store embedded apps, template-based issuance is strongly recommended. See Connect an Embedded App for a complete walkthrough.

launchFeature(featurePath, initialPrompt?)

Navigate the LearnCard host wallet to one of its built-in features. Use this when you want to send the user from your embedded app into a wallet route (e.g. AI Topics, Wallet Share, Profile).

circle-exclamation

Parameters:

  • featurePath (string): Wallet route to navigate to (e.g., /ai/topics, /wallet/share, /profile)

  • initialPrompt (string, optional): Initial prompt or data to pass to the feature

Returns: Promise<void>

Errors: LC_TIMEOUT, UNAUTHORIZED (if your app lacks the launch_feature permission)

Example:

launchFeature vs sendNotification actionPath

These two APIs both take a /path string and look interchangeable, but they navigate to different origins:

API
Scope
Use when

launchFeature(path)

LearnCard wallet

You want to send the user into a wallet feature (/ai/topics, /wallet/share, /profile). Path is interpreted by the LearnCard host.

sendNotification({ actionPath })

Your embedded app

You want a notification's tap action to deep-link the user to a route inside your own app's iframe. Path is appended to your app's URL.

Bridge pattern — deep-linking from a notification to a wallet feature:

If you want a notification to take the user to a wallet route (e.g. /ai/topics), you must route them through one of your own pages that calls launchFeature():

The wallet's iframe host enforces this: any actionPath is appended to your app's iframe URL and the host explicitly rejects values that would escape your origin.

askCredentialSearch(verifiablePresentationRequest)

Request credentials from the user's wallet using query criteria.

Parameters:

  • verifiablePresentationRequest (VerifiablePresentationRequest): Query specification

Returns: Promise<CredentialSearchResponse>

Example:

askCredentialSpecific(credentialId)

Request a specific credential by ID.

Parameters:

  • credentialId (string): The ID of the credential to request

Returns: Promise<CredentialSpecificResponse>

Example:

requestConsent(contractUri?, options?)

Request user consent for data access permissions.

circle-info

App Store Apps: If your app is installed from the LearnCard App Store and has a consent contract configured in its integration settings, you can omit the contractUri parameter. The SDK will automatically resolve the configured contract from your listing.

Parameters:

  • contractUri (string, optional): URI of the consent contract. Can be omitted for App Store apps with configured contracts.

  • options (RequestConsentOptions, optional): Additional options for the consent flow

Option
Type
Default
Description

redirect

boolean

false

If true, redirects to the contract's configured URL after consent granted

Returns: Promise<ConsentResponse>

Examples:

initiateTemplateIssue(templateId, draftRecipients?)

Initiate a template-based credential issuance flow.

Parameters:

  • templateId (string): ID of the template/boost to issue

  • draftRecipients (string[], optional): Array of recipient DIDs

Returns: Promise<TemplateIssueResponse>

Example:


requestLearnerContext(options?)

Request comprehensive learner context for AI tutoring and personalization systems.

This method retrieves the user's credentials and personal data (with their consent), then formats them into either an LLM-ready prompt or structured data that can be used to personalize AI experiences.

Use Cases:

  • AI tutors that adapt to learner's existing skills and credentials

  • Personalized learning pathway recommendations

  • Smart content that adjusts based on learner history

  • Intelligent assessment systems

Parameters:

  • options (RequestLearnerContextOptions, optional): Configuration for what data to include and how to format it

Option
Type
Default
Description

includeCredentials

boolean

true

Whether to include user's credentials in the context

includePersonalData

boolean

false

Whether to include personal data (name, bio, etc.)

format

'prompt' | 'structured'

'prompt'

Format of the response

instructions

string

-

Optional instructions to guide LLM prompt generation

detailLevel

'compact' | 'expanded'

'compact'

Level of detail in generated content

Returns: Promise<LearnerContextResponse>

Example - AI Tutor Integration:

Example - Structured Data Access:

Error Handling:

circle-info

Prerequisites for Learner Context:

  1. Your app must be installed from the LearnCard App Store

  2. The user must have consented to a contract that grants access to their credentials

  3. The consent contract must be configured in your app's listing integration

Use requestConsent() before calling requestLearnerContext() if the user hasn't consented yet.

sendAiSessionCredential(input)

Send an AI Session credential to record a learning interaction. AI Sessions are organized under AI Topics, creating a structured history of AI tutoring sessions that appears in the user's AI Topics page.

Use Cases:

  • AI Tutoring Apps - Record what was learned during a tutoring session

  • Learning Assistants - Track learning progress and outcomes

  • Skill Assessment - Document demonstrated competencies

  • Learning Pathways - Build a history of learning interactions

Parameters:

  • input (SendAiSessionCredentialInput): Session details

Property
Type
Required
Description

sessionTitle

string

Yes

Title of this specific AI session

summaryData

SummaryCredentialData

Yes

Structured data about what was learned

metadata

Record<string, unknown>

No

Optional metadata for the session

Summary Data Structure:

circle-exclamation

Returns: Promise<SendAiSessionCredentialResponse>

Example - Recording a Learning Session:

How It Works:

  1. Topic Creation/Reuse: The first session from your app creates an AI Topic. Subsequent sessions reuse this topic.

  2. Session Credential: Each call creates a new AI Session credential under the topic.

  3. Automatic Storage: Credentials are immediately stored in the user's LearnCloud wallet.

  4. AI Topics Page: Sessions appear in the user's AI Topics section for review.

Session Hierarchy:

circle-info

Prerequisites for AI Sessions:

  1. Your app must be installed from the LearnCard App Store

  2. The user must have consented to share their learning data

  3. Call requestConsent() before sending AI sessions if not already consented

The AI Topic is automatically created on the first session and reused for all subsequent sessions from your app.

Errors: LC_UNAUTHENTICATED, UNAUTHORIZED, USER_REJECTED, LC_TIMEOUT, BAD_REQUEST (when summaryData fails server-side validation — see the Source-of-Truth note below).

Schema Source of Truth

The summaryData shape is defined by SummaryCredentialDataValidator in @learncard/types (packages/learn-card-types/src/lcn.ts). The brain service deep-validates every sendAiSessionCredential call against this discriminated union, so a malformed summaryData will fail fast with a clear zod error rather than producing a broken credential.

sendNotification(input)

Send a notification to the current user from this app. The notification appears in the user's LearnCard notification inbox.

Parameters: AppNotificationInput

Property
Type
Required
Description

title

string

No

Notification title.

body

string

No

Notification body text.

actionPath

string

No

App-local path. When the user taps the notification, this path is appended to your app's iframe URL. See below.

category

string

No

Optional category tag for grouping notifications.

priority

'normal' | 'high'

No

Visual priority. 'high' notifications are styled more prominently in the inbox.

Returns: Promise<AppNotificationResponse>

Errors: LC_UNAUTHENTICATED, UNAUTHORIZED, LC_TIMEOUT

circle-exclamation

Example — notify within your own app:

Example — bridge to a wallet feature:

Counters: incrementCounter, getCounter, getCounters

Lightweight per-user-app counters for tracking app-defined integer state (e.g. "sessions completed", "streak days"). Counters are scoped to (user, listing) — every user has an independent set of counters per app.

Limits (load-bearing — design around these):

  • Maximum 50 distinct keys per (user, app) pair

  • Maximum 100 writes per minute per (user, app) pair

  • Integer values only (use Math.floor or pre-aggregate if you need fractional state)

  • Key format: ^[a-zA-Z0-9_-]+$, 1–64 characters

If you need to track more than 50 things, consolidate (e.g. one lessons_completed counter rather than one counter per lesson).

Signatures:

Examples:

Errors: LC_UNAUTHENTICATED, UNAUTHORIZED, BAD_REQUEST (invalid key format, > 50 keys, or rate-limit exceeded), LC_TIMEOUT

destroy()

Clean up the SDK and remove event listeners.

Returns: void

Example:

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 used

  • Query parameter overrides are validated against whitelist

Configuration Hierarchy:

  1. Default: https://learncard.app (security anchor)

  2. Query Parameter Override: ?lc_host_override=https://staging.learncard.app

  3. Configured Origin: From hostOrigin option

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

Error Handling

All SDK methods reject with a PartnerConnectError (a real Error subclass) carrying both code and message. The legacy LearnCardError shape is preserved — error.code keeps working — so existing call sites continue to function unchanged:

The LearnCardError interface remains exported for backwards compatibility:

Error Codes

Code
Description

LC_TIMEOUT

Request timed out

LC_UNAUTHENTICATED

User not logged in

USER_REJECTED

User declined the request

CREDENTIAL_NOT_FOUND

Requested credential doesn't exist

UNAUTHORIZED

User lacks permission

TEMPLATE_NOT_FOUND

Template doesn't exist

SDK_NOT_INITIALIZED

SDK not properly initialized

SDK_DESTROYED

SDK was destroyed before completion

Error Handling Patterns

Advanced Configuration

Multiple Origins (Staging Support)

Native App Support

For Capacitor/Ionic apps:

Custom Timeouts

Browser Support

  • Chrome/Edge: 90+

  • Firefox: 88+

  • Safari: 14+

  • Mobile: iOS Safari 14+, Android Chrome 90+

Required APIs:

  • postMessage

  • Promise

  • URLSearchParams

  • addEventListener

Migration Guide

From Manual postMessage

Before (80+ lines of boilerplate):

After (3 lines):

Benefits:

  • 85% code reduction in typical integrations

  • Type safety with full TypeScript support

  • Better error handling with structured error codes

  • Security improvements with origin validation

  • No manual cleanup required

Examples

SSO Authentication Flow

Credential Gating (Premium Content)

Credential Issuance (Certificate Award)

TypeScript Types

All types are exported from the package for full type safety:

Key Type Definitions

Last updated

Was this helpful?