Flexpa
Developer PortalFeedbackContact usSandbox

All docs

Overview

  • Why Use Flexpa?

How Health Links Work

  • Lifecycle
  • Security Model
  • Health Links vs Health Cards
  • Passcodes
  • Flags
  • Manifests
  • Status

Authenticated API

  • POSTCreate SHL
  • GETList SHLs
  • DELETERevoke SHL

Manifest and Direct Transfer

  • GETDirect Transfer
  • POSTManifest

SMART Health Links API

#Overview

SMART Health Links (SHLs) are secure URLs using the shlink: scheme that contain encrypted health information, including SMART Health Cards. Each link embeds a unique encryption key and manifest URL, enabling secure data sharing without confusing online portals or expensive network connection fees.

Flexpa's API fully implements the SMART Health Cards and Links STU1 specification while leveraging Flexpa's proven healthcare data infrastructure.

Perfect for healthcare applications needing to:

  • Kill the clipboard and participate in CMS Aligned Networks
  • Enable patient-controlled data portability and verifiable health records
  • Share comprehensive records such as lab results, digital insurance cards, and visit summaries directly with patients without requiring online portals

#Why Use Flexpa?

Our SMART Health Links implementation combines full specification compliance with enterprise-grade reliability:

  • Full Spec Compliance: Complete implementation of SMART Health Cards and Links STU1 specification with all required flags, status lifecycle, and support for both Manifest and Direct Transfer recipient access patterns
  • Enterprise-Grade Security: JSON Web Encryption (JWE) with A256GCM algorithm, unique 32-byte keys per link, reliable cloud object storage (S3), automatic expiry (TTL), passcodes with brute-force protection, and revocation
  • Production-Ready Infrastructure: Built on Flexpa's proven platform with automatic cleanup jobs, comprehensive error handling, rate limiting, and full audit logging
SHLs API

Sandbox Access

Get instant access to Flexpa's sandbox environment to start building and testing your healthcare integrations

Get Sandbox Access →

#How Health Links Work

When a patient receives a QR code containing their health records, that code is actually a SMART Health Link - a secure URL starting with shlink:/ that contains everything needed to decrypt and access their encrypted health data. Here's how the entire flow works from creation to access.

#Lifecycle

Creating the QR Code

1
Data Encryption

Your application sends health data to Flexpa's API, which encrypts it using AES-256-GCM encryption

2
Unique Key Generation

A unique 32-byte encryption key is generated specifically for this link - this key is not persisted by Flexpa

3
URL Creation

The encrypted data is stored securely in S3, and a shlink:/ URL is created containing both the manifest location and the encryption key

4
QR Generation

This URL can be rendered as a QR code that patients can share or print

Scanning the QR Code

5
URL Decoding

The QR scanner reads the shlink:/ URL and extracts the embedded JSON payload

6
Key Extraction

The recipient's app extracts both the manifest URL and the unique decryption key from the payload

7
Secure Retrieval

The app calls Flexpa's manifest endpoint (optionally with a passcode if required)

8
Local Decryption

Using the embedded key, the app decrypts the health data locally - Flexpa never sees the decryption key

#Security Model

Creation & Authentication

Your application authenticates with Flexpa using your Secret Key and calls the SHL creation endpoint with health data.

Input: SMART Health Cards, FHIR Bundles, Patient/$everything data

Encryption & Storage

Flexpa generates a unique 32-byte key, encrypts data with JWE/A256GCM, and stores files securely in AWS S3.

Process: Key generation → JWE encryption → S3 upload

Link Generation & Distribution

System returns a shlink: URL containing the manifest endpoint and encryption key. Share via your preferred channel.

Format:shlink:/[base64url-encoded-json]

Recipient Access

Recipients decode the base64url JSON payload, extract the manifest URL and decryption key, call the manifest endpoint, and decrypt the response locally.

Process: Decode JSON → Extract URL/key → API call → JWE decryption

Lifecycle Management

Links track access attempts, enforce policies, transition through status states, and trigger cleanup jobs when expired.

Status flow: can-change → finalized → no-longer-valid

SHL URL Structure

Typically, but not necessarily, transported as a QR code.

shlink:/eyJ1cmwiOiJodHRwczovL3NoYy5mbGV4cGEuY29tL2V4YW1wbGVzL0k5MXJoYmEzVnN1R1hHY2hjbnI2VkhsUUZLeGZFMjhrdVowc3NiRXV4bm8vbWFuaWZlc3QuanNvbiIsImtleSI6Ik0yVkNjWGxHcDdvZ2EwejZOR1JJWDgxX1lVREJqWnBwMjN2QkNtODdUNVUiLCJ2IjoxLCJsYWJlbCI6IkV4YW1wbGUgSVBTIEJ1bmRsZSIsImZsYWciOiJMVSJ9

Base64url-encoded JSON payload
{ "url": "https://shc.flexpa.com/examples/I91rhba3VsuGXGchcnr6VHlQFKxfE28kuZ0ssbEuxno/manifest.json", "key": "M2VCcXlGp7oga0z6NGRIX81_YUDBjZpp23vBCm87T5U", "v": 1, "label": "Example IPS Bundle", "flag": "LU" }
Decoded JSON example
Property descriptions:
url - Manifest endpoint URL
key - 43-char base64url decryption key (32 bytes)
v - Version (currently 1)
label - Optional description (≤80 chars)
flag - Optional flags (L, P, U)
exp - Optional expiration (epoch seconds)

Recipient Access Pattern

1
Decode JSON payload
Base64url decode to get manifest URL and decryption key
2
Call manifest URL
POST to extracted URL with recipient info + optional passcode
3
Receive JWE payload
Encrypted health data response
4
Decrypt locally
Use extracted 32-byte key with A256GCM algorithm

#Health Links vs Health Cards

While SMART Health Cards are tamper-proof digital credentials containing signed health data (like vaccination records), SMART Health Links provide a secure way to share those credentials and other health data through encrypted, shareable URLs. Think of SHCs as the digital certificates themselves, while SHLs are the secure delivery mechanism.

SHCs are digitally signed JWS tokens containing health data that can be verified offline. SHLs are encrypted URLs (shlink:) that can contain one or more SHCs plus additional FHIR resources. Use them together by creating SHCs for tamper-proof credentials, then packaging them into SHLs for secure sharing.


#Passcodes

SMART Health Links support optional passcode protection to add an extra layer of security for sensitive health data. When a link is created with passcode protection, recipients must provide the correct passcode to access the encrypted content.

Passcodes provide several security benefits:

  • Access Control: Only recipients who know the passcode can decrypt and view the health data, even if the SHL is intercepted or shared unintentionally.
  • Brute-Force Protection: The system automatically locks access after 3 failed passcode attempts, preventing unauthorized access through repeated guessing.
  • Flexible Distribution: Passcodes can be shared through separate channels from the link itself (e.g., link via email, passcode via SMS), implementing a two-factor approach to data access.

Passcodes must be between 5-128 characters and cannot be used in combination with direct transfer mode (U flag), since direct file access bypasses the manifest endpoint where passcode validation occurs.

Passcode Processing Flow

1
Creation (5-128 chars)
Passcode hashed with SHA-256 before database storage
2
Validation Request
Database row locked to prevent race conditions
✓
Correct Passcode
Safe string comparison, access granted
!
Wrong Passcode
Attempt counter incremented, remaining attempts returned
✗
3rd Failed Attempt
Link automatically locked, access permanently denied
Security Features
  • • Serializable database isolation level
  • • Row-level locking prevents concurrent attacks
  • • Constant-time hash comparison
  • • Immediate lockout after 3 attempts

#Flags

SMART Health Links use single-character flags to control access behavior and link properties. Flags are concatenated alphabetically in the flag property of the JSON payload and determine how recipients can interact with the link.

  • L (Long-term)

    Enables long-term use where the manifest can evolve over time, allowing content updates

  • P (Passcode)

    Requires a passcode for access (5-128 characters, up to 3 attempts allowed)

  • U (Direct Transfer)

    Enables direct file access via GET request, bypassing manifest endpoint (incompatible with P flag)


#Manifests

The manifest is the central coordination point for accessing encrypted health data through SMART Health Links. It provides recipients with metadata about available health files and URLs to download them.

When recipients decode a SMART Health Link, they extract a manifest URL that serves as the API endpoint for accessing the encrypted content. The manifest endpoint handles two primary access patterns:

  • Standard Manifest Flow (POST): Recipients POST to the manifest URL with their identifier and optional passcode. The server validates the request, enforces security policies, and returns a structured response containing encrypted file references, status information, and download locations.

  • Direct Transfer Flow (GET): For links with the U flag, recipients can bypass the manifest entirely and GET the encrypted files directly. This streamlined approach reduces round trips but sacrifices the ability to use passcode protection.

The manifest response includes critical metadata about each file's content type, encryption status, and availability. Files may be embedded directly in the response (for smaller content) or provided as temporary download URLs (for larger files), allowing efficient handling of varying data sizes while maintaining security.

Example Manifest Response

{
  "status": "finalized",
  "files": [
    {
      "contentType": "application/smart-health-card",
      "embedded": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...",
      "location": null,
      "lastUpdated": "2024-01-01T10:30:00.000Z"
    },
    {
      "contentType": "application/fhir+json",
      "embedded": null,
      "location": "https://api.flexpa.com/smart/health-links/files/abc123?token=xyz789",
      "lastUpdated": "2024-01-01T10:30:00.000Z"
    }
  ]
}

#Status

SMART Health Links contain a status value used to communicate the current state of the link and its contents to recipients. The status is returned in the manifest response and helps applications understand whether the data is stable, may change, or is no longer accessible.

Together with the L (Long-term) flag, the status can be used to enable workflows such as generating a SHL prior to data being available - such as the results of a diagnostic tests - or providing continuously updated data - such as a personal health history.

  • finalized

    Content is stable and will not change

  • can-change

    Content may be updated (used with long-term links)

  • no-longer-valid

    Link has expired or been revoked, no files available


#Authenticated API

These endpoints require authentication using your Flexpa Secret Key in the Authorization: Bearer header.


POSThttps://api.flexpa.com/smart/health-links

#Create SHL

Create a new SHL containing encrypted health data files. Returns a shareable shlink: URL with embedded encryption keys and manifest endpoint.

Integration Tip: Combine SHLs with other Flexpa APIs for powerful workflows. Use Patient/$health-cards-issue to generate SMART Health Cards from FHIR data, then package them into shareable links.

Request Headers

AuthorizationstringRequired

An Authorization: Bearer header value must presented with your Secret Key

Request Parameters

filesarrayRequired

Array of files to include in the SHL.

contentTypestringRequired

Content type: application/smart-health-card, application/fhir+json, or application/smart-api-access.

contentstring | objectRequired

File content - string for pre-built SHCs, object for FHIR resources or API access.

userobjectRequired

User information for tracking and association.

externalIdstringRequired

Your internal user identifier for tracking.

labelstring

Optional label for the link (max 80 characters). Note: This label is embedded directly in the SHL URL and is accessible without a passcode.

passcodestring

Optional passcode protection (5-128 characters). Cannot be used with directTransfer: true.

ttlnumber

Time-to-live in seconds (minimum 1).

longTermboolean

Whether this is a long-term link. Adds L flag.

directTransferboolean

Enable direct file transfer. Adds U flag. Cannot be used with passcode.

Response Fields

idstring

Unique identifier for the SHL (UUID format).

shlstring

The complete SHL URL starting with shlink:/.

viewerUrlstring

Direct URL to view the health data in Flexpa's viewer interface.

manifestUrlstring

API endpoint URL for programmatic access to the encrypted manifest.

expiresAtstring | null

ISO 8601 timestamp when the link expires, or null for long-term links.

Request

POST
/smart/health-links
SECRET_KEY=sk_test_your-secret-key
# First generate a SMART Health Card using Patient/$health-cards-issue
curl -X POST https://api.flexpa.com/smart/health-links \
  -H "Authorization: Bearer $SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "files": [
      {
        "contentType": "application/smart-health-card",
        "content": "eyJhbGciOiJFUzI1NiI..."
      }
    ],
    "user": {
      "externalId": "patient-123"
    },
    "label": "Vaccination Record",
    "ttl": 86400
  }'

Response Examples

{
  "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "shl": "shlink:/eyJhbGciOiJFUzI1NiI...",
  "viewerUrl": "https://shc.flexpa.com/#shlink:/eyJhbGciOiJFUzI1NiI...",
  "manifestUrl": "https://api.flexpa.com/smart/health-links/manifests/7d4c9a5e3b2f1a8c6d9e4f7a8b5c2e1d",
  "expiresAt": "2024-02-01T00:00:00.000Z"
}

GEThttps://api.flexpa.com/smart/health-links

#List SHLs

Retrieve a paginated list of all SHLs created by your application.

Request Headers

AuthorizationstringRequired

An Authorization: Bearer header value must presented with your Secret Key

Request Parameters

limitnumber

Number of results per page (1-1000, default: 20).

cursorstring

Pagination cursor for next page.

Response Fields

dataarray

Array of SHL objects.

idstring

Unique identifier for the SHL.

manifestIdstring

Unique identifier for the encrypted manifest.

userobject

User information associated with the link.

externalIdstring

Your internal user identifier.

labelstring | null

Optional label for the link.

flagsstring

SHL flags (L, P, U combinations).

expiresAtstring | null

ISO 8601 expiration timestamp, or null for long-term links.

revokedAtstring | null

ISO 8601 timestamp when revoked, or null if active.

createdAtstring

ISO 8601 timestamp when the link was created.

updatedAtstring

ISO 8601 timestamp when the link was last updated.

fileCountnumber

Number of files contained in the link.

totalSizenumber

Total size of all files in bytes.

metaobject

Pagination metadata.

hasMoreboolean

Whether more results are available.

nextCursorstring | null

Cursor for the next page, or null if no more pages.

Request

GET
/smart/health-links
SECRET_KEY=sk_test_your-secret-key
curl https://api.flexpa.com/smart/health-links?limit=10 \
  -H "Authorization: Bearer $SECRET_KEY"

Response Example

{
  "data": [{
    "id": "a1b2c3d4-e5f6-4789-abc1-23def4567890",
    "manifestId": "9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d",
    "user": {"externalId": "patient-123"},
    "label": "Lab Results",
    "flags": "LP",
    "expiresAt": "2024-02-01T00:00:00.000Z",
    "revokedAt": null,
    "createdAt": "2024-01-01T10:30:00.000Z",
    "updatedAt": "2024-01-01T10:30:00.000Z",
    "fileCount": 1,
    "totalSize": 2048
  }],
  "meta": {
    "hasMore": true,
    "nextCursor": "eyJjcmVhdGVkQXQi..."
  }
}

DELETEhttps://api.flexpa.com/smart/health-links/{id}

#Revoke SHL

Permanently revoke a SHL, making it inaccessible and scheduling file deletion.

Permanent Action: Revocation cannot be undone. All associated files will be deleted from storage.

Request Headers

AuthorizationstringRequired

An Authorization: Bearer header value must presented with your Secret Key

Request Parameters

idstringRequired

The UUID of the SHL to revoke (path parameter).

Request

DELETE
/smart/health-links/{id}
SECRET_KEY=sk_test_your-secret-key
curl -X DELETE https://api.flexpa.com/smart/health-links/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
  -H "Authorization: Bearer $SECRET_KEY"

Response Examples

{}

#Manifest and Direct Transfer

These endpoints are accessible to end recipients of SHLs and do not require a Secret Key. Access is controlled through the encryption keys and optional passcodes embedded in the SHL URL.


GEThttps://api.flexpa.com/smart/health-links/manifests/{manifestId}

#Direct Transfer

Direct download of encrypted health data files. Only available for links with the U flag enabled.

Flag Restriction: This endpoint only works with links that have the U (Direct Transfer) flag. Links with both U and P flags are invalid.

Parameters

manifestIdstringRequired

The manifest ID from the SHL (path parameter).

recipientstring

Optional recipient identifier (query parameter).

Response Fields

Content-Typeheader

Set to application/jose for JWE-encrypted content.

Response Bodystring

JWE (JSON Web Encryption) string using A256GCM algorithm. Decrypt using the 32-byte key embedded in the original SHL URL payload.

Request

GET
/smart/health-links/manifests/{manifestId}
curl https://api.flexpa.com/smart/health-links/manifests/7d4c9a5e3b2f1a8c6d9e4f7a8b5c2e1d

Response Examples

HTTP/1.1 200 OK
Content-Type: application/jose

eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0..iv8E9W3flKTiZhYeAW3Se.4hU4gz
mSH5K6E5WCekMtV8u9-g_bCh5lUhcmAJI9EqTvJZLKqttqHpLJiyqk0jRl-BqRDjNiU2r
IeqZVb0k2JPj7IuR8qVzN8kpmw0K8fvPhKMmjmC41ydPG1sqVvgPYN0nz8sT5x5Z2MpYV
8N6iNwAjhSNnqYk3jJGmCLNMOKpEhHz7kN-d4fWqR3X9iG7Lh2xuEOLed7_27dxcpvnS2
ScbvhzPqhYqiVF7KQ3mTbWcKdxNM5KkrCw.Bx8xiafv0c-uVEXy_6q-jg

POSThttps://api.flexpa.com/smart/health-links/manifests/{manifestId}

#Manifest

Recipients use this endpoint to retrieve the encrypted health data from a SHL.

Request Parameters

recipientstringRequired

Identifier for the requesting party.

passcodestring

Required if the link has passcode protection (max 128 characters).

embeddedLengthMaxnumber

Maximum length for embedded content (minimum 0, default: 0).

Response Fields

statusstring

Indicates file changeability: finalized (stable), can-change (may evolve), or no-longer-valid (expired/revoked).

filesarray

Array of encrypted health data files following the SHLs manifest structure.

contentTypestring

MIME type: application/smart-health-card, application/fhir+json, or application/smart-api-access.

embeddedstring | null

JWE-encrypted file content (base64url encoded) if within size limits, otherwise null.

locationstring | null

Short-lived URL for downloading large encrypted files, or null if embedded.

remainingAttemptsnumber | null

Number of passcode attempts remaining (only included for incorrect passcode errors).

Request

POST
/smart/health-links/manifests/{manifestId}
curl -X POST https://api.flexpa.com/smart/health-links/manifests/7d4c9a5e3b2f1a8c6d9e4f7a8b5c2e1d \
  -H "Content-Type: application/json" \
  -d '{
    "recipient": "healthcare-provider-id",
    "passcode": "12345"
  }'

Response Examples

{
  "status": "finalized",
  "files": [{
    "contentType": "application/smart-health-card",
    "embedded": "eyJhbGciOiJFUzI1NiI...",
    "lastUpdated": "2024-01-01T10:30:00.000Z"
  }]
}
Status TwitterGitHub

© 2025 Flexpa. All rights reserved.