LiveCard Exchange (LCX) Standard
Version: 1.0
Status: Draft
Date: 2026-04-06
Authors: Componera (PTY) LTD
Document Identifier: LCX-1.0
MIME Type: application/vnd.lcx.card+json
Abstract
The LiveCard Exchange (LCX) Standard defines an interoperable protocol for creating, sharing, and live-updating digital business cards across platforms and applications. It specifies a JSON-based data model for business card content, a layout system for visual rendering, an lcx:// deep-link QR encoding format so operating systems can route scans to LCX-compatible apps, and a REST-based server protocol that enables cards to update in real time after they have been exchanged.
LCX is designed for two audiences: developers building Card Provider platforms (services that host and manage business cards) and developers building Card Consumer applications (apps that store, display, and synchronize received cards). By adhering to this standard, any Card Provider can issue cards that any Card Consumer can display and keep up to date — regardless of who built either system.
Table of Contents
- Introduction
- Terminology and Conventions
- Card Data Model
- QR Code Encoding
- Media Assets
- Card Layout and Positioning
- Update Server Protocol
- Authentication
- Caching and Offline Behavior
- Security Considerations
- Extensibility and Versioning
- Appendix A: JSON Schema
- Appendix B: Example Card Payload
- Appendix C: Example QR Code Payload
- Appendix D: Example HTTP Exchange
- Appendix E: MIME Type Registration
1. Introduction
1.1 Problem Statement
Physical business cards become outdated the moment they are printed. A change in phone number, job title, or company branding renders every previously distributed card inaccurate. Digital alternatives exist, but they are fragmented: each platform uses its own proprietary format, making it impossible for a card created on one service to be reliably consumed by another.
There is no open, interoperable standard that simultaneously addresses:
- Structured card data (contact details, social links, addresses)
- Visual presentation (layout, images, branding)
- Live updates (fetching the latest card data from a server after the initial exchange)
- Offline resilience (caching card data for use when connectivity is unavailable)
- Secure sharing (exchanging cards via QR codes with optional access control)
1.2 Goals
LCX aims to:
- Define a universal data model for digital business cards that is rich enough to represent real-world card designs.
- Specify an absolute-positioning layout system that gives card designers full creative control while remaining resolution-independent.
- Establish a QR code encoding format that enables instant card sharing between devices.
- Define a REST-based update protocol that allows cards to be refreshed from a server, ensuring recipients always see the latest information.
- Provide caching and offline requirements so that cards remain accessible even when the hosting server is unreachable.
- Support optional authentication for private or restricted cards.
- Be extensible so that future versions can add capabilities without breaking existing implementations.
1.3 Audience
This specification is intended for:
- Card Provider developers — those building platforms where users create, manage, and host their digital business cards.
- Card Consumer developers — those building applications (mobile apps, desktop clients, web viewers) that scan, store, display, and synchronize received business cards.
1.4 Scope
LCX 1.0 covers the data model, layout system, QR encoding, server protocol, caching behavior, and security considerations for digital business cards. It does not cover:
- User account management or registration flows on Card Provider platforms.
- The process of designing or editing a card (this is Provider-specific UI).
- Token issuance or OAuth flows (authentication token provisioning is left to Card Providers).
- Push notifications or WebSocket-based real-time subscriptions (polling via TTL is the v1.0 mechanism).
2. Terminology and Conventions
2.1 Key Terms
| Term | Definition |
|---|---|
| Card | A digital business card conforming to the LCX data model. |
| Card Payload | The complete JSON document representing a Card, including data, media references, and layout. |
| Card Provider | A server or platform that hosts, manages, and serves Card Payloads. Providers expose an Update Endpoint from which Consumers fetch card data. |
| Card Consumer | An application that scans, stores, displays, and synchronizes Cards received from Providers. |
| Card URI | The full URL of a Card's Update Endpoint, uniquely identifying where a Card's live data can be fetched. |
| Update Endpoint | The HTTP(S) API endpoint on a Card Provider from which a Card Consumer retrieves the latest Card Payload. |
| Card ID | A globally unique identifier (UUID v4) assigned to each Card by its Provider. |
| QR Payload | The JSON object carried inside an LCX QR URI (after base64url decoding the p query parameter) that enables a Consumer to locate and fetch a Card. |
| LCX QR URI | The UTF-8 string encoded in a share QR code: an lcx:// deep link whose query parameter p holds a base64url-encoded QR Payload. |
| Canvas | The virtual coordinate space in which Card layout elements are positioned. |
| TTL (Time To Live) | A value in seconds indicating how frequently a Consumer should re-fetch a Card from the Update Endpoint. |
2.2 Notational Conventions
The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
2.3 Data Format Conventions
- All JSON field names use camelCase.
- All timestamps use ISO 8601 format in UTC (e.g.,
"2026-04-06T12:00:00Z"). - All UUIDs follow UUID v4 format (e.g.,
"550e8400-e29b-41d4-a716-446655440000"). - All colors are expressed as CSS-compatible strings: hex (
"#FF5733"), rgba ("rgba(255, 87, 51, 0.8)"), or named colors ("white"). - All URLs MUST be absolute and use the
httpsscheme unless explicitly stated otherwise.
3. Card Data Model
The Card Payload is a JSON object that contains all information needed to display and update a business card. This section defines the structure of that object.
3.1 Top-Level Structure
{
"lcxVersion": "1.0",
"cardId": "<uuid>",
"createdAt": "<iso8601>",
"updatedAt": "<iso8601>",
"ttl": 3600,
"identity": { ... },
"professional": { ... },
"contacts": [ ... ],
"addresses": [ ... ],
"socials": [ ... ],
"customFields": [ ... ],
"bio": "<string>",
"media": { ... },
"layout": { ... }
}
3.2 Metadata Fields
| Field | Type | Required | Description |
|---|---|---|---|
lcxVersion | string | REQUIRED | The LCX specification version this payload conforms to. For this specification: "1.0". |
cardId | string (UUID v4) | REQUIRED | Globally unique identifier for this card, assigned by the Card Provider. |
createdAt | string (ISO 8601) | REQUIRED | Timestamp of when the card was first created. |
updatedAt | string (ISO 8601) | REQUIRED | Timestamp of the most recent modification to the card. |
ttl | integer | RECOMMENDED | Suggested re-fetch interval in seconds. Consumers SHOULD NOT poll the Update Endpoint more frequently than this value. Default assumption if omitted: 3600 (1 hour). |
3.3 Identity Fields
The identity object contains personal identification information.
| Field | Type | Required | Description |
|---|---|---|---|
fullName | string | REQUIRED | The person's full display name as it should appear on the card. |
preferredName | string | OPTIONAL | A shorter or informal name (e.g., "Jack" instead of "Jackson"). |
prefix | string | OPTIONAL | Name prefix or honorific (e.g., "Dr.", "Prof.", "Mr."). |
suffix | string | OPTIONAL | Name suffix (e.g., "Jr.", "III", "PhD"). |
pronouns | string | OPTIONAL | Preferred pronouns (e.g., "he/him", "she/her", "they/them"). |
3.4 Professional Fields
The professional object contains work-related information.
| Field | Type | Required | Description |
|---|---|---|---|
jobTitle | string | OPTIONAL | The person's job title or role. |
department | string | OPTIONAL | Department or division within the organization. |
organization | string | OPTIONAL | The name of the company or organization. |
organizationUrl | string (URL) | OPTIONAL | The organization's website URL. |
3.5 Contacts Array
The contacts array contains communication channels. Each entry is an object:
| Field | Type | Required | Description |
|---|---|---|---|
type | string | REQUIRED | The contact method. MUST be one of: "phone", "email", "fax", "pager", "sms", "whatsapp", "telegram", "signal", "other". |
value | string | REQUIRED | The contact value (phone number, email address, etc.). Phone numbers SHOULD use E.164 format (e.g., "+27821234567"). |
label | string | OPTIONAL | A human-readable label (e.g., "Work", "Personal", "Mobile"). |
preferred | boolean | OPTIONAL | If true, indicates this is the preferred contact method of this type. Defaults to false. |
A Card Payload SHOULD contain at least one entry in the contacts array.
3.6 Addresses Array
The addresses array contains physical or mailing addresses. Each entry is an object:
| Field | Type | Required | Description |
|---|---|---|---|
label | string | OPTIONAL | A human-readable label (e.g., "Office", "Home", "Warehouse"). |
street | string | OPTIONAL | Street address, including building/suite numbers. |
city | string | OPTIONAL | City or locality. |
state | string | OPTIONAL | State, province, or region. |
postalCode | string | OPTIONAL | Postal or ZIP code. |
country | string | OPTIONAL | Country name or ISO 3166-1 alpha-2 code (e.g., "ZA", "US"). |
coordinates | object | OPTIONAL | Geographic coordinates: { "lat": <number>, "lng": <number> }. |
3.7 Socials Array
The socials array contains social media and professional network links. Each entry is an object:
| Field | Type | Required | Description |
|---|---|---|---|
platform | string | REQUIRED | The platform identifier. RECOMMENDED values: "linkedin", "twitter", "x", "facebook", "instagram", "github", "youtube", "tiktok", "mastodon", "bluesky", "threads", "snapchat", "pinterest", "dribbble", "behance", "medium", "other". Custom platform identifiers MAY be used. |
url | string (URL) | REQUIRED | The full URL to the person's profile on this platform. |
handle | string | OPTIONAL | The person's username or handle on this platform (e.g., "@componera"). |
3.8 Custom Fields Array
The customFields array allows Card Providers to include arbitrary key-value data not covered by the standard fields. Each entry is an object:
| Field | Type | Required | Description |
|---|---|---|---|
label | string | REQUIRED | A human-readable label for this field (e.g., "License Number", "Languages Spoken"). |
value | string | REQUIRED | The field value. |
icon | string (URL) | OPTIONAL | URL to an icon image representing this field. |
3.9 Bio
| Field | Type | Required | Description |
|---|---|---|---|
bio | string | OPTIONAL | A free-text biography or description. Plain text only in v1.0. Consumers SHOULD display this with line breaks preserved. |
4. QR Code Encoding
This section defines how a Card is shared between devices using QR codes.
4.1 LCX QR URI (Deep Link)
The QR code MUST encode an LCX QR URI: a URI whose scheme is lcx, whose authority (host) identifies the QR transport revision, and whose query carries the card locator data. The scanned string therefore begins with lcx:// (or LCX://, etc.; see below), which allows mobile and desktop operating systems to offer Open in actions for apps that register the lcx URL scheme.
The QR code MUST NOT contain raw JSON as its entire payload. The JSON QR Payload (Sections 4.2–4.4) is embedded only after decoding.
Normative form:
lcx://v1?p=<base64url>
| Component | Requirement |
|---|---|
| Scheme | lcx. Per RFC 3986, scheme matching is case-insensitive. Producers MUST serialize the scheme as lowercase lcx. Consumers MUST accept lcx in any case (e.g., LCX://v1?... from a camera overlay). |
| Authority | v1 — LCX QR transport version aligned with the API path /lcx/v1/. Future standards MAY define lcx://v2?... without changing HTTP Card URIs until a future API version exists. |
| Path | Empty (no path segment after lcx://v1). Producers MUST NOT include a path; Consumers MAY ignore an empty path if present. |
| Query | Exactly one REQUIRED parameter: p. The value is the base64url encoding (RFC 4648, Section 5; without padding characters =) of the UTF-8 octets of the QR Payload JSON document (Sections 4.2–4.4). Producers MUST use a compact JSON serialization (minimal whitespace). Additional query parameters are reserved for future LCX versions; Consumers MUST ignore unknown parameters. |
Encoding steps (Card Provider):
- Build the QR Payload JSON object (Sections 4.2–4.4).
- Serialize to UTF-8 bytes with no insignificant whitespace (same logical JSON as a pretty-printed document).
- Encode those bytes with base64url and omit padding.
- Form the URI
lcx://v1?p=followed by that string. The full URI is the QR symbol contents.
Decoding steps (Card Consumer):
- Obtain the scanned string (trim leading/trailing whitespace).
- Parse or pattern-match as a URI with scheme
lcx(case-insensitive) and authorityv1. - Read the
pquery parameter. If missing or empty, fail the decode. - Base64url-decode
pto bytes. Implementations MUST accept omitted padding and MUST NOT require=padding. - Interpret the bytes as UTF-8 and parse as JSON to obtain the QR Payload.
- Validate and use the QR Payload (Sections 4.3–4.4); fetch the Card from the HTTPS Card URI in the
urifield using the same HTTP behavior as before (Section 7, Section 8).
The Card URI inside the JSON remains an https:// Update Endpoint URL (for example https://cards.example.com/lcx/v1/cards/{cardId}). Only the QR transport wrapping uses the lcx:// scheme; live fetch and caching are unchanged HTTP(S).
4.2 QR Payload Format (JSON)
After decoding the p parameter, the Consumer parses the following JSON structure:
{
"lcx": "1",
"uri": "https://cards.example.com/lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000",
"cid": "550e8400-e29b-41d4-a716-446655440000",
"auth": "none",
"token": null,
"snapshot": {
"fn": "Jane Smith",
"title": "Chief Technology Officer",
"org": "Componera (PTY) LTD"
}
}
4.3 QR Payload Fields
| Field | Type | Required | Description |
|---|---|---|---|
lcx | string | REQUIRED | The LCX major version number as a string. For this specification: "1". Consumers MUST check this field to determine compatibility. |
uri | string (URL) | REQUIRED | The full Update Endpoint URL from which the complete Card Payload can be fetched. |
cid | string (UUID) | REQUIRED | The Card ID. MUST match the cardId in the Card Payload returned by the Update Endpoint. |
auth | string | OPTIONAL | Authentication method required to access the card. MUST be one of: "none" (default), "bearer", "query". If omitted, Consumers MUST assume "none". |
token | string | OPTIONAL | The authentication token. REQUIRED if auth is "bearer" or "query". MUST be null or omitted if auth is "none". |
snapshot | object | OPTIONAL | A minimal preview of the card for instant display before the full payload is fetched from the server. See Section 4.4. |
4.4 Snapshot Object
The snapshot provides enough data to render a basic preview immediately upon scanning, before any network request completes.
| Field | Type | Required | Description |
|---|---|---|---|
fn | string | REQUIRED | Full name (abbreviated key to save space). |
title | string | OPTIONAL | Job title. |
org | string | OPTIONAL | Organization name. |
email | string | OPTIONAL | Primary email address. |
phone | string | OPTIONAL | Primary phone number. |
Providers SHOULD include the snapshot object. The snapshot exists purely for UX optimization and MUST NOT be treated as authoritative data. Consumers MUST replace snapshot data with the full Card Payload once it is fetched from the Update Endpoint.
4.5 Registering the lcx Protocol (Consumers)
LCX-compatible Card Consumers SHOULD register a handler for the lcx URL scheme on every platform they support, so that when the user scans a share QR code, the OS can open the Consumer directly with the full LCX QR URI.
The following notes are informative; they rest on platform documentation that may evolve. Implementers MUST consult current vendor guides.
4.5.1 iOS and iPadOS
- Declare the URL scheme
lcxunderCFBundleURLTypes/CFBundleURLSchemesinInfo.plist. - Implement the appropriate open-URL callback (
application(_:open:options:)onUIApplicationDelegate, orscene(_:openURLContexts:)onUISceneDelegatefor multi-window apps). - Parse the incoming
URLas an LCX QR URI (Section 4.1), then run the decoding pipeline (Section 4.1) before fetching the Card over HTTPS.
Universal Links (https://...) are separate from custom schemes; LCX 1.0 does not require Universal Links. A Consumer MAY additionally associate an https host with the app for non-QR entry points, but the normative share QR format remains lcx://.
4.5.2 Android
- Declare an
Activity(orNavDeepLink) with an<intent-filter>:actionandroid.intent.action.VIEW, categoriesDEFAULTandBROWSABLE, and<data android:scheme="lcx" android:host="v1" />. - Read the intent URI in
onCreate/onNewIntent; parse and decode per Section 4.1. - App Links verify
httpshosts; they do not replace custom-scheme handling forlcx://.
4.5.3 macOS and Windows desktop
- macOS: Same URL-type registration as iOS in the app bundle; handle incoming URLs via
NSApplication/AppDelegateopen-URL APIs. - Windows: Register a custom URL protocol for
lcxsoShellExecute/ the default browser handoff passes the string to the registered LCX Consumer.
4.5.4 Web browsers and generic scanners
- Many in-browser QR scanners produce a string and navigate to it. For
lcx://, the browser or OS typically resolves the scheme to a registered native app. Pure web apps cannot reliably “claim” arbitrary custom schemes the way native apps do; hybrid or native Consumers should handlelcx://in the native shell and pass the decoded payload to embedded WebViews if needed. - Camera / scanner apps pass the scanned string to the platform URL dispatcher; registering
lcxis what enables Open with LCX app behavior.
4.6 QR Code Requirements
- Encoding mode: The QR code MUST encode the LCX QR URI (Section 4.1) as a UTF-8 byte string.
- Error correction: The QR code MUST use error correction level M (15% recovery) or higher. Level Q (25%) is RECOMMENDED for printed materials.
- Maximum QR Payload size: The decoded QR Payload JSON (UTF-8 bytes after base64url decode) SHOULD NOT exceed 2,048 bytes (2 KB) when serialized without insignificant whitespace. The full LCX QR URI is longer than the JSON alone (prefix + base64url overhead); Providers SHOULD still target compact payloads so the QR symbol stays scannable at reasonable print sizes.
- Minimum module size: When rendered for display or print, each QR module (dot) SHOULD be at least 0.75mm wide to ensure reliable scanning.
4.7 Legacy encodings (informative)
Earlier drafts described raw JSON or an LCX:-prefixed compressed blob as the full QR contents. Those forms are not LCX 1.0–conformant. New Providers MUST emit the lcx://v1?p=... form only. Consumers are not required to support legacy encodings.
5. Media Assets
This section defines how visual assets (photographs, logos, background images) are referenced and delivered within a Card Payload.
5.1 Media Object Structure
The media object in the Card Payload contains named asset slots:
{
"media": {
"profilePhoto": { ... },
"backgroundImage": { ... },
"organizationLogo": { ... },
"customAssets": [ ... ]
}
}
5.2 Asset Object
Each asset (whether in a named slot or in the customAssets array) is an object with the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
url | string (URL) | REQUIRED | Absolute HTTPS URL from which the asset can be fetched. |
mimeType | string | REQUIRED | The MIME type of the asset. See Section 5.3 for supported types. |
width | integer | RECOMMENDED | The intrinsic width of the asset in pixels. |
height | integer | RECOMMENDED | The intrinsic height of the asset in pixels. |
blurhash | string | OPTIONAL | A BlurHash string for rendering a placeholder while the asset loads. |
alt | string | OPTIONAL | Accessibility text describing the asset. |
data | string | OPTIONAL | Base64-encoded inline data URI (e.g., "data:image/png;base64,...") for offline or snapshot use. See Section 5.5. |
5.3 Supported Formats
Card Providers MUST serve assets in at least one of the following formats:
| MIME Type | Extension | Usage |
|---|---|---|
image/jpeg | .jpg, .jpeg | Photographs, background images |
image/png | .png | Logos, graphics with transparency |
image/webp | .webp | Optimized photographs and graphics |
image/svg+xml | .svg | Vector logos and icons |
Card Consumers MUST support image/jpeg and image/png. Support for image/webp and image/svg+xml is RECOMMENDED.
5.4 Resolution Guidance
| Asset | Minimum Size | Recommended Size | Maximum Size |
|---|---|---|---|
profilePhoto | 256 x 256 px | 512 x 512 px | 2048 x 2048 px |
backgroundImage | 800 x 480 px | 1600 x 960 px | 3200 x 1920 px |
organizationLogo | 128 x 128 px | 256 x 256 px | 1024 x 1024 px |
Providers SHOULD serve assets at or above the recommended size. Consumers SHOULD downscale assets to fit the display rather than upscaling below-minimum assets.
Asset file sizes SHOULD NOT exceed 2 MB per individual asset and 5 MB total across all assets in a single Card Payload.
5.5 Inline Data
Assets MAY include a data field containing a base64-encoded data URI. This is intended for:
- Providing a low-resolution preview that can be rendered immediately without a network request.
- Enabling basic offline rendering when the Consumer has never fetched the full-resolution asset.
When a data field is present alongside a url field, Consumers MUST treat the url as the authoritative source and use data only as a fallback or placeholder. Inline data SHOULD be kept small (under 50 KB per asset) to avoid inflating the Card Payload.
5.6 Custom Assets
The customAssets array allows Providers to attach additional images to a card (e.g., product photos, QR codes for other services, award badges). Each entry follows the Asset Object structure (Section 5.2) with an additional field:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | REQUIRED | A unique identifier for this custom asset within the card. |
label | string | OPTIONAL | A human-readable label describing the asset. |
Custom assets can be referenced by layout elements using their id (see Section 6).
6. Card Layout and Positioning
This section defines the absolute-positioning layout system that controls how card elements are visually arranged.
6.1 Canvas
All layout positions are defined within a virtual canvas — an abstract coordinate space that is independent of physical screen resolution.
| Property | Default | Description |
|---|---|---|
width | 1000 | The canvas width in abstract units. |
height | 600 | The canvas height in abstract units. |
The default canvas represents a standard landscape business card with a 5:3 aspect ratio. Providers MAY override the canvas dimensions to support portrait or custom aspect ratios.
{
"layout": {
"canvas": {
"width": 1000,
"height": 600
},
"backgroundColor": "#FFFFFF",
"elements": [ ... ]
}
}
Rendering rule: Card Consumers MUST scale the canvas uniformly to fit the available display area while preserving the aspect ratio. The origin (0, 0) is the top-left corner of the canvas. The x-axis increases to the right; the y-axis increases downward.
6.2 Layout Object
The layout object within the Card Payload has the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
canvas | object | OPTIONAL | Canvas dimensions: { "width": <int>, "height": <int> }. Defaults to { "width": 1000, "height": 600 } if omitted. |
backgroundColor | string (color) | OPTIONAL | The card's background color. Defaults to "#FFFFFF". |
elements | array | REQUIRED (if layout is present) | An ordered array of layout elements to render on the canvas. |
6.3 Layout Elements
Each entry in the elements array is a layout element object that describes a single visual component on the card.
6.3.1 Common Element Fields
These fields apply to all element types:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | REQUIRED | A unique identifier for this element within the card. |
type | string | REQUIRED | The element type. MUST be one of: "text", "image", "shape", "divider", "qrCode", "icon". |
dataBinding | string | OPTIONAL | A dot-notation path to the data field this element displays (e.g., "identity.fullName", "media.profilePhoto", "contacts.0.value"). If present, the element renders the bound data. If absent, the element uses its inline content or src field. |
x | number | REQUIRED | Horizontal position of the element's top-left corner in canvas units. |
y | number | REQUIRED | Vertical position of the element's top-left corner in canvas units. |
width | number | REQUIRED | Element width in canvas units. |
height | number | REQUIRED | Element height in canvas units. |
zIndex | integer | OPTIONAL | Stacking order. Higher values render on top. Defaults to 0. Elements with equal zIndex are rendered in array order. |
rotation | number | OPTIONAL | Clockwise rotation in degrees (0–360) around the element's center point. Defaults to 0. |
opacity | number | OPTIONAL | Opacity from 0.0 (fully transparent) to 1.0 (fully opaque). Defaults to 1.0. |
visible | boolean | OPTIONAL | Whether the element is rendered. Defaults to true. Allows Providers to include hidden elements that may be toggled by future features. |
6.3.2 Text Elements
For elements with "type": "text":
| Field | Type | Required | Description |
|---|---|---|---|
content | string | OPTIONAL | Static text content. Ignored if dataBinding is set. |
style | object | OPTIONAL | Text styling properties (see below). |
Text style properties:
| Field | Type | Default | Description |
|---|---|---|---|
fontFamily | string | "sans-serif" | The font family name. Consumers SHOULD support common web-safe fonts and MAY support custom fonts via URL. |
fontSize | number | 24 | Font size in canvas units. |
fontWeight | string or integer | "normal" | CSS-compatible font weight (e.g., "bold", "normal", 100–900). |
fontStyle | string | "normal" | "normal" or "italic". |
color | string (color) | "#000000" | Text color. |
textAlign | string | "left" | "left", "center", "right", or "justify". |
verticalAlign | string | "top" | "top", "middle", or "bottom". |
lineHeight | number | 1.2 | Line height as a multiplier of fontSize. |
letterSpacing | number | 0 | Additional spacing between characters in canvas units. |
textDecoration | string | "none" | "none", "underline", "line-through", or "overline". |
textTransform | string | "none" | "none", "uppercase", "lowercase", or "capitalize". |
overflow | string | "wrap" | Behavior when text exceeds the element bounds: "wrap" (default), "ellipsis", or "clip". |
6.3.3 Image Elements
For elements with "type": "image":
| Field | Type | Required | Description |
|---|---|---|---|
src | string (URL) | OPTIONAL | Direct URL to the image. Ignored if dataBinding is set (the bound media asset's url is used instead). |
style | object | OPTIONAL | Image styling properties (see below). |
Image style properties:
| Field | Type | Default | Description |
|---|---|---|---|
objectFit | string | "cover" | How the image fits within the element bounds: "cover", "contain", or "fill". |
borderRadius | number | 0 | Corner radius in canvas units. Use a value equal to half the smaller dimension for a circle. |
border | object | none | Border specification: { "width": <number>, "color": "<color>", "style": "solid" }. |
6.3.4 Shape Elements
For elements with "type": "shape":
| Field | Type | Required | Description |
|---|---|---|---|
shape | string | REQUIRED | The shape to render: "rectangle", "ellipse", "triangle", or "line". |
style | object | OPTIONAL | Shape styling properties (see below). |
Shape style properties:
| Field | Type | Default | Description |
|---|---|---|---|
fillColor | string (color) | "transparent" | Fill color. |
strokeColor | string (color) | "#000000" | Stroke (border) color. |
strokeWidth | number | 1 | Stroke width in canvas units. |
borderRadius | number | 0 | Corner radius for rectangles, in canvas units. |
6.3.5 Divider Elements
For elements with "type": "divider":
| Field | Type | Default | Description |
|---|---|---|---|
style.color | string (color) | "#CCCCCC" | Line color. |
style.thickness | number | 2 | Line thickness in canvas units. |
style.pattern | string | "solid" | "solid", "dashed", or "dotted". |
The divider renders as a horizontal line spanning the element's width at the vertical center of its height.
6.3.6 QR Code Elements
For elements with "type": "qrCode":
| Field | Type | Required | Description |
|---|---|---|---|
qrData | string | OPTIONAL | The data to encode in the on-card QR element. If omitted, Consumers SHOULD encode the LCX QR URI for the card (Section 4.1) so scanning opens an LCX Consumer; alternatively, Consumers MAY encode the Card URI alone if the design intent is a generic HTTPS link without opening a registered lcx app. |
style | object | OPTIONAL | QR styling properties. |
QR Code style properties:
| Field | Type | Default | Description |
|---|---|---|---|
foregroundColor | string (color) | "#000000" | Module (dot) color. |
backgroundColor | string (color) | "#FFFFFF" | Background color. |
errorCorrection | string | "M" | Error correction level: "L", "M", "Q", or "H". |
6.3.7 Icon Elements
For elements with "type": "icon":
| Field | Type | Required | Description |
|---|---|---|---|
icon | string | REQUIRED | Icon identifier. Providers SHOULD use identifiers from a well-known icon set (e.g., Material Icons names like "phone", "email", "location_on"). Alternatively, a URL to an SVG icon. |
style | object | OPTIONAL | Icon styling properties. |
Icon style properties:
| Field | Type | Default | Description |
|---|---|---|---|
color | string (color) | "#000000" | Icon tint color. |
6.4 Default Layout Fallback
If the layout field is absent from the Card Payload, or if the elements array is empty, Card Consumers MUST render a default card layout using the available data fields. The specific design of the default layout is left to the Consumer, but it MUST display at minimum:
- The
identity.fullNamefield. - The
professional.jobTitleandprofessional.organizationfields, if present. - The first
contactsentry of type"email"and"phone", if present. - The
media.profilePhoto, if present.
7. Update Server Protocol
This section defines the REST API that Card Providers MUST implement to serve Card Payloads to Card Consumers.
7.1 Base URL
Card Providers choose their own base URL. The LCX protocol path is appended to it:
{baseUrl}/lcx/v1/cards/{cardId}
For example:
https://cards.example.com/lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000
The full URL is the Card URI and is the value stored in the QR Payload's uri field.
7.2 Fetch Card
Request:
GET /lcx/v1/cards/{cardId} HTTP/1.1
Host: cards.example.com
Accept: application/vnd.lcx.card+json, application/json
Successful Response (200 OK):
HTTP/1.1 200 OK
Content-Type: application/vnd.lcx.card+json
ETag: "a1b2c3d4e5"
Last-Modified: Sun, 05 Apr 2026 18:30:00 GMT
Cache-Control: public, max-age=3600
The response body is the full Card Payload JSON as defined in Sections 3–6.
Content-Type: Card Providers SHOULD use application/vnd.lcx.card+json as the response content type. Providers MAY fall back to application/json if the custom media type is not practical for their infrastructure. Consumers MUST accept both.
7.3 Conditional Requests
Providers SHOULD support conditional requests to minimize bandwidth:
If-None-Match (ETag-based):
GET /lcx/v1/cards/{cardId} HTTP/1.1
Host: cards.example.com
Accept: application/vnd.lcx.card+json, application/json
If-None-Match: "a1b2c3d4e5"
If the card has not changed, the Provider responds:
HTTP/1.1 304 Not Modified
ETag: "a1b2c3d4e5"
Cache-Control: public, max-age=3600
If-Modified-Since (Date-based):
GET /lcx/v1/cards/{cardId} HTTP/1.1
Host: cards.example.com
Accept: application/vnd.lcx.card+json, application/json
If-Modified-Since: Sun, 05 Apr 2026 18:30:00 GMT
Providers SHOULD support at least ETag/If-None-Match. Support for If-Modified-Since is RECOMMENDED.
7.4 Error Responses
All error responses MUST use standard HTTP status codes and SHOULD include a JSON body:
{
"error": {
"code": "<error_code>",
"message": "<human_readable_message>"
}
}
| Status Code | Error Code | Description |
|---|---|---|
400 | bad_request | Malformed request. |
401 | unauthorized | Authentication is required but was not provided or is invalid. |
403 | forbidden | The provided credentials do not have access to this card. |
404 | not_found | The card does not exist or the Card ID is invalid. |
410 | gone | The card has been permanently deleted. Consumers SHOULD remove this card from their local storage and inform the user. |
429 | rate_limited | Too many requests. The response MUST include a Retry-After header (in seconds). |
500 | internal_error | Server-side error. |
7.5 CORS
Card Providers that intend to support browser-based Card Consumers SHOULD include appropriate CORS headers:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Authorization, Accept, If-None-Match, If-Modified-Since
Access-Control-Expose-Headers: ETag, Last-Modified, Retry-After
7.6 Rate Limiting
Card Providers SHOULD implement rate limiting to protect against abuse. When a Consumer is rate limited:
- The Provider MUST respond with
429 Too Many Requests. - The response MUST include a
Retry-Afterheader indicating the number of seconds before the Consumer may retry. - Consumers MUST respect the
Retry-Aftervalue and MUST NOT retry before it expires.
Providers SHOULD allow at least 60 requests per minute per Card ID per client IP for public cards.
8. Authentication
LCX supports optional authentication for cards that should not be publicly accessible.
8.1 Authentication Methods
| Method | auth Value | Description |
|---|---|---|
| None (Public) | "none" | No authentication required. This is the default. |
| Bearer Token | "bearer" | Consumer includes a token in the Authorization header. |
| Query Parameter | "query" | Consumer includes a token as a URL query parameter. |
8.2 Public Cards
When auth is "none" (or omitted), the Card is publicly accessible. Consumers send a standard GET request with no authentication headers.
8.3 Bearer Token Authentication
When auth is "bearer":
- The QR Payload MUST include a
tokenfield containing the bearer token. - The Consumer MUST include the token in the HTTP
Authorizationheader when fetching the card:
GET /lcx/v1/cards/{cardId} HTTP/1.1
Host: cards.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Accept: application/vnd.lcx.card+json, application/json
- If the token is missing, expired, or invalid, the Provider MUST respond with
401 Unauthorized.
8.4 Query Parameter Authentication
When auth is "query":
- The QR Payload MUST include a
tokenfield containing the token value. - The Consumer MUST append the token as a query parameter when fetching the card:
GET /lcx/v1/cards/{cardId}?token=abc123def456 HTTP/1.1
Host: cards.example.com
Accept: application/vnd.lcx.card+json, application/json
- This method is provided for simpler integrations where modifying HTTP headers is impractical. Bearer token authentication (Section 8.3) is RECOMMENDED over query parameter authentication when possible.
8.5 Token Provisioning
How tokens are generated, rotated, and revoked is outside the scope of LCX 1.0. Card Providers are free to use any mechanism (JWTs, opaque tokens, API keys, etc.). The standard only defines how tokens are carried in QR Payloads and HTTP requests.
8.6 Token Storage
Card Consumers that receive authenticated cards MUST store the associated token alongside the cached Card Payload. Consumers SHOULD store tokens using platform-appropriate secure storage mechanisms (e.g., Keychain on iOS, EncryptedSharedPreferences on Android).
9. Caching and Offline Behavior
A core benefit of LCX is that cards update live. However, Consumers must also function when the Card Provider is unreachable.
9.1 Client-Side Caching Requirements
- Card Payload caching: Consumers MUST cache the most recently fetched Card Payload for each card in persistent local storage. The cached payload MUST survive app restarts.
- Media asset caching: Consumers SHOULD cache fetched media assets (images) separately from the Card Payload, keyed by their URL. Asset caches SHOULD persist across app restarts.
- Token caching: Consumers MUST persist authentication tokens for authenticated cards (see Section 8.6).
9.2 Refresh Behavior
- Consumers SHOULD attempt to refresh a card from the Update Endpoint when:
- The card is opened or viewed by the user.
- The time since the last successful fetch exceeds the card's
ttlvalue. - The user manually triggers a refresh.
- Consumers SHOULD NOT fetch more frequently than the card's
ttlvalue unless the user explicitly requests a refresh. - Consumers SHOULD use conditional requests (Section 7.3) to minimize bandwidth.
9.3 Offline Fallback
When the Update Endpoint is unreachable (network error, timeout, DNS failure):
- Consumers MUST display the cached Card Payload.
- Consumers MUST provide a visual indicator that the displayed data may be stale (e.g., a "Last updated" timestamp, a subtle banner, or an icon).
- Consumers SHOULD retry the fetch according to an exponential backoff strategy, respecting the card's
ttlas the minimum interval.
9.4 Card Deletion
When a Provider returns 410 Gone:
- Consumers SHOULD mark the card as deleted in local storage.
- Consumers SHOULD inform the user that the card has been permanently removed by its owner.
- Consumers MAY retain the cached data for a grace period (e.g., 30 days) to allow the user to note down any information they need before the card is purged.
10. Security Considerations
10.1 Transport Security
All Update Endpoint URLs MUST use HTTPS with TLS 1.2 or higher. Card Consumers MUST reject Update Endpoint URLs that use plain HTTP. Card Consumers MUST validate the server's TLS certificate against the platform's trusted certificate store.
10.2 QR Code Integrity
QR codes are inherently susceptible to tampering (e.g., a malicious QR code sticker placed over a legitimate one). LCX 1.0 does not define a cryptographic signature mechanism for QR Payloads. Consumers SHOULD:
- Display the Update Endpoint domain prominently when a card is first scanned, so the user can verify it comes from an expected source.
- Warn the user if the domain is an IP address or uses an unusual TLD.
Future versions of LCX MAY introduce payload signing to mitigate this risk.
10.3 Token Security
- Tokens MUST be transmitted only over HTTPS.
- Consumers MUST NOT log tokens in plaintext.
- Consumers MUST store tokens in platform-secure storage (see Section 8.6).
- Providers SHOULD issue tokens with limited scope (per-card access only) and SHOULD support token revocation.
10.4 Rate Limiting and Abuse Prevention
Card Providers SHOULD implement rate limiting (see Section 7.6) to prevent:
- Enumeration attacks (sequentially guessing Card IDs).
- Denial-of-service attacks against the Update Endpoint.
Card IDs are UUID v4 (122 bits of randomness), making enumeration impractical, but rate limiting provides defense in depth.
10.5 Data Privacy
- Card Providers MUST support card deletion and MUST return
410 Gonefor deleted cards, enabling Consumers to remove personal data. - Card Providers SHOULD provide card owners with the ability to see which data is published in their card.
- Card Consumers SHOULD allow users to delete any stored card and its associated data from local storage at any time.
- Implementers in jurisdictions subject to GDPR, POPIA, CCPA, or similar regulations MUST ensure their implementations comply with applicable data protection requirements.
11. Extensibility and Versioning
11.1 Version Identification
Every Card Payload includes an lcxVersion field (Section 3.2) and every QR Payload includes an lcx field (Section 4.3). These fields allow Consumers to determine which version of the standard the data conforms to.
11.2 Forward Compatibility
To ensure forward compatibility:
- Consumers MUST ignore unknown fields. If a Card Payload or QR Payload contains fields not defined in the version of the standard that the Consumer implements, those fields MUST be silently ignored. Consumers MUST NOT treat unknown fields as an error.
- Consumers MUST ignore unknown element types. If a layout element has a
typenot recognized by the Consumer, the element MUST be skipped during rendering. - Consumers MUST preserve unknown fields when caching. If a Consumer caches a Card Payload containing fields it does not recognize, those fields MUST be retained in the cache so they are available if the Consumer is later updated to a version that supports them.
11.3 Versioning Policy
- Patch versions (e.g., 1.0.1): Clarifications and errata only. No new fields, no behavioral changes.
- Minor versions (e.g., 1.1): New OPTIONAL fields, new element types, new authentication methods. Fully backward-compatible with the same major version. A Consumer implementing LCX 1.0 can read a 1.1 payload (ignoring new fields).
- Major versions (e.g., 2.0): Breaking changes to required fields, payload structure, or protocol behavior. Consumers MUST check the
lcxVersion/lcxfield and inform the user if they encounter a major version they do not support.
11.4 Extension Namespace
Providers MAY include custom extension fields in the Card Payload by prefixing them with x-. For example:
{
"lcxVersion": "1.0",
"cardId": "...",
"x-myplatform-theme": "dark",
"x-myplatform-animationEnabled": true,
...
}
Extension fields MUST NOT override or conflict with standard fields. Consumers MUST ignore extension fields they do not recognize (per Section 11.2).
Appendix A: JSON Schema
The following JSON Schema (draft 2020-12) defines the structure of an LCX 1.0 Card Payload. The canonical machine-readable schema is available at schemas/card-payload.schema.json.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://lcx.componera.com/schemas/card-payload/1.0",
"title": "LCX Card Payload",
"description": "A LiveCard Exchange (LCX) 1.0 business card payload.",
"type": "object",
"required": ["lcxVersion", "cardId", "createdAt", "updatedAt", "identity"],
"properties": {
"lcxVersion": {
"type": "string",
"const": "1.0",
"description": "LCX specification version."
},
"cardId": {
"type": "string",
"format": "uuid",
"description": "Globally unique card identifier (UUID v4)."
},
"createdAt": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 creation timestamp."
},
"updatedAt": {
"type": "string",
"format": "date-time",
"description": "ISO 8601 last-modified timestamp."
},
"ttl": {
"type": "integer",
"minimum": 0,
"description": "Suggested re-fetch interval in seconds."
},
"identity": {
"type": "object",
"required": ["fullName"],
"properties": {
"fullName": { "type": "string" },
"preferredName": { "type": "string" },
"prefix": { "type": "string" },
"suffix": { "type": "string" },
"pronouns": { "type": "string" }
},
"additionalProperties": false
},
"professional": {
"type": "object",
"properties": {
"jobTitle": { "type": "string" },
"department": { "type": "string" },
"organization": { "type": "string" },
"organizationUrl": { "type": "string", "format": "uri" }
},
"additionalProperties": false
},
"contacts": {
"type": "array",
"items": {
"type": "object",
"required": ["type", "value"],
"properties": {
"type": {
"type": "string",
"enum": ["phone", "email", "fax", "pager", "sms", "whatsapp", "telegram", "signal", "other"]
},
"value": { "type": "string" },
"label": { "type": "string" },
"preferred": { "type": "boolean", "default": false }
},
"additionalProperties": false
}
},
"addresses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"label": { "type": "string" },
"street": { "type": "string" },
"city": { "type": "string" },
"state": { "type": "string" },
"postalCode": { "type": "string" },
"country": { "type": "string" },
"coordinates": {
"type": "object",
"properties": {
"lat": { "type": "number" },
"lng": { "type": "number" }
},
"required": ["lat", "lng"],
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"socials": {
"type": "array",
"items": {
"type": "object",
"required": ["platform", "url"],
"properties": {
"platform": { "type": "string" },
"url": { "type": "string", "format": "uri" },
"handle": { "type": "string" }
},
"additionalProperties": false
}
},
"customFields": {
"type": "array",
"items": {
"type": "object",
"required": ["label", "value"],
"properties": {
"label": { "type": "string" },
"value": { "type": "string" },
"icon": { "type": "string", "format": "uri" }
},
"additionalProperties": false
}
},
"bio": {
"type": "string"
},
"media": {
"type": "object",
"properties": {
"profilePhoto": { "$ref": "#/$defs/asset" },
"backgroundImage": { "$ref": "#/$defs/asset" },
"organizationLogo": { "$ref": "#/$defs/asset" },
"customAssets": {
"type": "array",
"items": {
"allOf": [
{ "$ref": "#/$defs/asset" },
{
"type": "object",
"required": ["id"],
"properties": {
"id": { "type": "string" },
"label": { "type": "string" }
}
}
]
}
}
},
"additionalProperties": false
},
"layout": {
"type": "object",
"properties": {
"canvas": {
"type": "object",
"properties": {
"width": { "type": "integer", "default": 1000 },
"height": { "type": "integer", "default": 600 }
},
"additionalProperties": false
},
"backgroundColor": { "type": "string" },
"elements": {
"type": "array",
"items": { "$ref": "#/$defs/layoutElement" }
}
},
"additionalProperties": false
}
},
"additionalProperties": true,
"$defs": {
"asset": {
"type": "object",
"required": ["url", "mimeType"],
"properties": {
"url": { "type": "string", "format": "uri" },
"mimeType": { "type": "string" },
"width": { "type": "integer" },
"height": { "type": "integer" },
"blurhash": { "type": "string" },
"alt": { "type": "string" },
"data": { "type": "string" }
},
"additionalProperties": false
},
"layoutElement": {
"type": "object",
"required": ["id", "type", "x", "y", "width", "height"],
"properties": {
"id": { "type": "string" },
"type": {
"type": "string",
"enum": ["text", "image", "shape", "divider", "qrCode", "icon"]
},
"dataBinding": { "type": "string" },
"x": { "type": "number" },
"y": { "type": "number" },
"width": { "type": "number" },
"height": { "type": "number" },
"zIndex": { "type": "integer", "default": 0 },
"rotation": { "type": "number", "default": 0 },
"opacity": { "type": "number", "minimum": 0, "maximum": 1, "default": 1.0 },
"visible": { "type": "boolean", "default": true },
"content": { "type": "string" },
"src": { "type": "string", "format": "uri" },
"shape": {
"type": "string",
"enum": ["rectangle", "ellipse", "triangle", "line"]
},
"qrData": { "type": "string" },
"icon": { "type": "string" },
"style": { "type": "object" }
},
"additionalProperties": true
}
}
}
Appendix B: Example Card Payload
The following is a complete example of an LCX 1.0 Card Payload:
{
"lcxVersion": "1.0",
"cardId": "550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2026-03-15T09:00:00Z",
"updatedAt": "2026-04-05T18:30:00Z",
"ttl": 3600,
"identity": {
"fullName": "Jane Smith",
"preferredName": "Jane",
"prefix": "Ms.",
"pronouns": "she/her"
},
"professional": {
"jobTitle": "Chief Technology Officer",
"department": "Engineering",
"organization": "Componera (PTY) LTD",
"organizationUrl": "https://componera.com"
},
"contacts": [
{
"type": "email",
"value": "[email protected]",
"label": "Work",
"preferred": true
},
{
"type": "phone",
"value": "+27821234567",
"label": "Mobile",
"preferred": true
},
{
"type": "phone",
"value": "+27111234567",
"label": "Office"
}
],
"addresses": [
{
"label": "Head Office",
"street": "42 Innovation Drive, Tech Park",
"city": "Johannesburg",
"state": "Gauteng",
"postalCode": "2000",
"country": "ZA",
"coordinates": {
"lat": -26.2041,
"lng": 28.0473
}
}
],
"socials": [
{
"platform": "linkedin",
"url": "https://linkedin.com/in/janesmith",
"handle": "janesmith"
},
{
"platform": "github",
"url": "https://github.com/janesmith",
"handle": "janesmith"
},
{
"platform": "x",
"url": "https://x.com/janesmith",
"handle": "@janesmith"
}
],
"customFields": [
{
"label": "Languages",
"value": "English, Afrikaans, Zulu"
}
],
"bio": "Passionate technologist with 15 years of experience building scalable systems. Leading the engineering team at Componera to redefine how professionals connect.",
"media": {
"profilePhoto": {
"url": "https://cards.componera.com/assets/550e8400/profile.jpg",
"mimeType": "image/jpeg",
"width": 512,
"height": 512,
"blurhash": "LEHV6nWB2yk8pyo0adR*.7kCMdnj",
"alt": "Jane Smith headshot"
},
"backgroundImage": {
"url": "https://cards.componera.com/assets/550e8400/background.jpg",
"mimeType": "image/jpeg",
"width": 1600,
"height": 960,
"blurhash": "LGF5]+Yk^6#M@-5c,1J5@[or[Q6.",
"alt": "Abstract blue gradient background"
},
"organizationLogo": {
"url": "https://cards.componera.com/assets/550e8400/logo.svg",
"mimeType": "image/svg+xml",
"width": 256,
"height": 256,
"alt": "Componera logo"
}
},
"layout": {
"canvas": {
"width": 1000,
"height": 600
},
"backgroundColor": "#1A1A2E",
"elements": [
{
"id": "bg",
"type": "image",
"dataBinding": "media.backgroundImage",
"x": 0,
"y": 0,
"width": 1000,
"height": 600,
"zIndex": 0,
"style": {
"objectFit": "cover",
"opacity": 0.3
}
},
{
"id": "photo",
"type": "image",
"dataBinding": "media.profilePhoto",
"x": 60,
"y": 120,
"width": 200,
"height": 200,
"zIndex": 2,
"style": {
"objectFit": "cover",
"borderRadius": 100,
"border": {
"width": 3,
"color": "#FFFFFF",
"style": "solid"
}
}
},
{
"id": "name",
"type": "text",
"dataBinding": "identity.fullName",
"x": 300,
"y": 130,
"width": 450,
"height": 60,
"zIndex": 2,
"style": {
"fontFamily": "sans-serif",
"fontSize": 42,
"fontWeight": "bold",
"color": "#FFFFFF",
"textAlign": "left"
}
},
{
"id": "title",
"type": "text",
"dataBinding": "professional.jobTitle",
"x": 300,
"y": 195,
"width": 450,
"height": 35,
"zIndex": 2,
"style": {
"fontFamily": "sans-serif",
"fontSize": 22,
"fontWeight": "normal",
"color": "#E0E0E0",
"textAlign": "left"
}
},
{
"id": "org",
"type": "text",
"dataBinding": "professional.organization",
"x": 300,
"y": 235,
"width": 450,
"height": 30,
"zIndex": 2,
"style": {
"fontFamily": "sans-serif",
"fontSize": 18,
"fontWeight": "normal",
"color": "#B0B0B0",
"textAlign": "left"
}
},
{
"id": "divider1",
"type": "divider",
"x": 300,
"y": 280,
"width": 450,
"height": 10,
"zIndex": 2,
"style": {
"color": "rgba(255, 255, 255, 0.3)",
"thickness": 1,
"pattern": "solid"
}
},
{
"id": "emailIcon",
"type": "icon",
"icon": "email",
"x": 300,
"y": 305,
"width": 24,
"height": 24,
"zIndex": 2,
"style": {
"color": "#FFFFFF"
}
},
{
"id": "emailText",
"type": "text",
"dataBinding": "contacts.0.value",
"x": 335,
"y": 303,
"width": 400,
"height": 28,
"zIndex": 2,
"style": {
"fontFamily": "sans-serif",
"fontSize": 16,
"color": "#FFFFFF",
"textAlign": "left"
}
},
{
"id": "phoneIcon",
"type": "icon",
"icon": "phone",
"x": 300,
"y": 345,
"width": 24,
"height": 24,
"zIndex": 2,
"style": {
"color": "#FFFFFF"
}
},
{
"id": "phoneText",
"type": "text",
"dataBinding": "contacts.1.value",
"x": 335,
"y": 343,
"width": 400,
"height": 28,
"zIndex": 2,
"style": {
"fontFamily": "sans-serif",
"fontSize": 16,
"color": "#FFFFFF",
"textAlign": "left"
}
},
{
"id": "logo",
"type": "image",
"dataBinding": "media.organizationLogo",
"x": 850,
"y": 30,
"width": 100,
"height": 100,
"zIndex": 2,
"style": {
"objectFit": "contain"
}
},
{
"id": "qr",
"type": "qrCode",
"x": 830,
"y": 420,
"width": 140,
"height": 140,
"zIndex": 2,
"style": {
"foregroundColor": "#FFFFFF",
"backgroundColor": "transparent",
"errorCorrection": "M"
}
}
]
}
}
Appendix C: Example QR Code Payload
The strings below are decoded QR Payloads (JSON). A conformant share QR encodes lcx://v1?p=<base64url(JSON)>, as in Section 4.1.
C.1 Minimal QR Payload (Public Card)
Decoded QR Payload:
{"lcx":"1","uri":"https://cards.componera.com/lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000","cid":"550e8400-e29b-41d4-a716-446655440000"}
Example LCX QR URI (full QR contents):
lcx://v1?p=eyJsY3giOiIxIiwidXJpIjoiaHR0cHM6Ly9jYXJkcy5jb21wb25lcmEuY29tL2xjeC92MS9jYXJkcy81NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJjaWQiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAifQ
C.2 QR Payload with Snapshot
Decoded QR Payload:
{
"lcx": "1",
"uri": "https://cards.componera.com/lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000",
"cid": "550e8400-e29b-41d4-a716-446655440000",
"auth": "none",
"snapshot": {
"fn": "Jane Smith",
"title": "Chief Technology Officer",
"org": "Componera (PTY) LTD",
"email": "[email protected]",
"phone": "+27821234567"
}
}
Example LCX QR URI (full QR contents):
lcx://v1?p=eyJsY3giOiIxIiwidXJpIjoiaHR0cHM6Ly9jYXJkcy5jb21wb25lcmEuY29tL2xjeC92MS9jYXJkcy81NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJjaWQiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJhdXRoIjoibm9uZSIsInNuYXBzaG90Ijp7ImZuIjoiSmFuZSBTbWl0aCIsInRpdGxlIjoiQ2hpZWYgVGVjaG5vbG9neSBPZmZpY2VyIiwib3JnIjoiQ29tcG9uZXJhIChQVFkpIExURCIsImVtYWlsIjoiamFuZUBjb21wb25lcmEuY29tIiwicGhvbmUiOiIrMjc4MjEyMzQ1NjcifX0
C.3 QR Payload with Bearer Authentication
Decoded QR Payload:
{
"lcx": "1",
"uri": "https://cards.componera.com/lcx/v1/cards/7a3b9c12-d4e5-6f78-90ab-cdef12345678",
"cid": "7a3b9c12-d4e5-6f78-90ab-cdef12345678",
"auth": "bearer",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjYXJkSWQiOiI3YTNiOWMxMi1kNGU1LTZmNzgtOTBhYi1jZGVmMTIzNDU2NzgiLCJleHAiOjE3NTYwMDAwMDB9.signature",
"snapshot": {
"fn": "John Doe",
"title": "Managing Director",
"org": "Acme Corp"
}
}
Example LCX QR URI (full QR contents):
lcx://v1?p=eyJsY3giOiIxIiwidXJpIjoiaHR0cHM6Ly9jYXJkcy5jb21wb25lcmEuY29tL2xjeC92MS9jYXJkcy83YTNiOWMxMi1kNGU1LTZmNzgtOTBhYi1jZGVmMTIzNDU2NzgiLCJjaWQiOiI3YTNiOWMxMi1kNGU1LTZmNzgtOTBhYi1jZGVmMTIzNDU2NzgiLCJhdXRoIjoiYmVhcmVyIiwidG9rZW4iOiJleUpoYkdjaU9pSklVekkxTmlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKallYSmtTV1FpT2lJM1lUTmlPV014TWkxa05HVTFMVFptTnpndE9UQmhZaTFqWkdWbU1USXpORFUyTnpnaUxDSmxlSEFpT2pFM05UWXdNREF3TURCOS5zaWduYXR1cmUiLCJzbmFwc2hvdCI6eyJmbiI6IkpvaG4gRG9lIiwidGl0bGUiOiJNYW5hZ2luZyBEaXJlY3RvciIsIm9yZyI6IkFjbWUgQ29ycCJ9fQ
Appendix D: Example HTTP Exchange
D.1 Initial Fetch
Request:
GET /lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: cards.componera.com
Accept: application/vnd.lcx.card+json, application/json
User-Agent: LiveRolodex/1.0 (LCX-Consumer)
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.lcx.card+json
ETag: "v42-2026040518"
Last-Modified: Sun, 05 Apr 2026 18:30:00 GMT
Cache-Control: public, max-age=3600
{
"lcxVersion": "1.0",
"cardId": "550e8400-e29b-41d4-a716-446655440000",
"createdAt": "2026-03-15T09:00:00Z",
"updatedAt": "2026-04-05T18:30:00Z",
"ttl": 3600,
"identity": {
"fullName": "Jane Smith"
},
...
}
D.2 Conditional Fetch (Not Modified)
Request:
GET /lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: cards.componera.com
Accept: application/vnd.lcx.card+json, application/json
If-None-Match: "v42-2026040518"
User-Agent: LiveRolodex/1.0 (LCX-Consumer)
Response:
HTTP/1.1 304 Not Modified
ETag: "v42-2026040518"
Cache-Control: public, max-age=3600
D.3 Conditional Fetch (Modified)
Request:
GET /lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: cards.componera.com
Accept: application/vnd.lcx.card+json, application/json
If-None-Match: "v42-2026040518"
User-Agent: LiveRolodex/1.0 (LCX-Consumer)
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.lcx.card+json
ETag: "v43-2026040612"
Last-Modified: Mon, 06 Apr 2026 12:00:00 GMT
Cache-Control: public, max-age=3600
{
"lcxVersion": "1.0",
"cardId": "550e8400-e29b-41d4-a716-446655440000",
"updatedAt": "2026-04-06T12:00:00Z",
"ttl": 3600,
"identity": {
"fullName": "Jane Smith-Williams"
},
"professional": {
"jobTitle": "Co-CEO",
"organization": "Componera (PTY) LTD"
},
...
}
D.4 Authenticated Fetch
Request:
GET /lcx/v1/cards/7a3b9c12-d4e5-6f78-90ab-cdef12345678 HTTP/1.1
Host: cards.componera.com
Accept: application/vnd.lcx.card+json, application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
User-Agent: LiveRolodex/1.0 (LCX-Consumer)
Response:
HTTP/1.1 200 OK
Content-Type: application/vnd.lcx.card+json
ETag: "v1-2026040100"
Cache-Control: private, max-age=1800
{
"lcxVersion": "1.0",
"cardId": "7a3b9c12-d4e5-6f78-90ab-cdef12345678",
...
}
D.5 Card Deleted
Request:
GET /lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: cards.componera.com
Accept: application/vnd.lcx.card+json, application/json
Response:
HTTP/1.1 410 Gone
Content-Type: application/json
{
"error": {
"code": "gone",
"message": "This card has been permanently deleted by its owner."
}
}
D.6 Rate Limited
Request:
GET /lcx/v1/cards/550e8400-e29b-41d4-a716-446655440000 HTTP/1.1
Host: cards.componera.com
Accept: application/vnd.lcx.card+json, application/json
Response:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Please retry after 60 seconds."
}
}
Appendix E: MIME Type Registration
E.1 Media Type
LCX defines a vendor-specific media type for Card Payloads:
- Type name: application
- Subtype name: vnd.lcx.card+json
- Required parameters: None
- Optional parameters:
version(e.g.,application/vnd.lcx.card+json; version=1.0) - Encoding considerations: UTF-8
- Published specification: This document (LCX 1.0)
- Contact: Componera (PTY) LTD
E.2 File Extension
The RECOMMENDED file extension for LCX Card Payload files is .lcx.json.
E.3 Registration Status
As of LCX 1.0, this media type has not been formally registered with IANA. Card Providers and Consumers SHOULD use this media type in anticipation of future registration. Implementations MUST also accept application/json as a fallback.
LCX (LiveCard Exchange) Standard v1.0 -- Copyright 2026 Componera (PTY) LTD. All rights reserved.