Skip to main content

Referral Tier Integration Guide

📄 This guide is also available as a PDF download.

Version: 0.1 (Draft) Date: March 2, 2026 Base URL: https://api.stealth.health (production) | https://sandbox.stealth.health (development) Status: Proposal / Scoping

See also: Clinical Partner API Integration Guide — a deeper integration where patient data, intake responses, appointment details, and transaction history are shared with the partner under a full BAA.

1. Overview​

Stealth Health offers a white-label telemedicine integration that allows partner platforms to embed our enrollment, clinical review, and prescription fulfillment pipeline into their own product. The integration works as follows:

  1. Partner directs their customer to a co-branded Stealth Health enrollment page.
  2. Patient completes a medical intake questionnaire and (optionally) pays.
  3. Stealth Health doctors review the intake and approve or deny a prescription.
  4. Stealth Health pharmacy partners fulfill and ship approved prescriptions.
  5. Partner receives real-time status updates via webhooks and can query the API for current state.

The partner never handles, stores, or receives protected health information (PHI). All clinical data stays within the Stealth Health platform. Partners interact exclusively with de-identified references and lifecycle status events.


2. HIPAA Compliance & PHI Boundaries​

What Partners CAN Access​

Data PointExample
Partner-scoped reference IDref_abc123xyz
Enrollment statusenrolled, pending_review, approved, denied
Fulfillment statusawaiting_shipment, shipped, delivered
Timestamp of each status change2026-03-02T14:30:00Z
Product category enrolled fortrt-cream, peptides
Payment statuspayment_due, payment_complete
Tracking carrier (no tracking #)USPS, UPS, Canada Post

What Partners CANNOT Access​

Data PointReason
Patient name, DOB, genderPHI — identity
Address, phone, emailPHI — contact info
Medical conditions, symptoms, allergiesPHI — clinical
Prescription details (medication, dosage, quantity)PHI — treatment
Doctor notes, intake responsesPHI — clinical
Lab results, ID verification imagesPHI — clinical / PII
Tracking numbers, shipping labelsCould be used to correlate PHI

Note: If a partner needs to display fulfillment tracking to their end user, they should direct the user to their Stealth Health patient portal, or we can discuss a tokenized tracking link approach (see Section 6.6).

Business Associate Agreement (BAA)​

A signed BAA between Stealth Health and the partner is required before API credentials are issued. The BAA defines each party's obligations under HIPAA and limits the partner's role to a referral source — not a covered entity or business associate handling PHI.


3. Authentication & Security​

3.1 API Keys​

Each partner receives a pair of API credentials:

CredentialPurpose
X-Partner-IDIdentifies the partner (public, safe to log)
X-Api-KeyAuthenticates the request (secret, never log or expose client-side)

Both must be sent as HTTP headers on every request:

GET /partner/referrals HTTP/1.1
Host: api.stealth.health (or sandbox.stealth.health)
X-Partner-ID: ptr_acme_health
X-Api-Key: sk_live_7f3a...redacted
Content-Type: application/json

3.2 Key Rotation​

Partners can request key rotation at any time. When a new key is issued, the old key remains valid for 72 hours to allow migration. Both keys are accepted during the overlap window.

3.3 Webhook Signature Verification​

All webhook payloads include an X-Stealth-Signature header containing an HMAC-SHA256 signature of the request body, signed with the partner's webhook secret (provided at onboarding, separate from the API key).

X-Stealth-Signature: sha256=a1b2c3d4e5f6...

Partners must verify this signature before processing any webhook payload. See Section 7 for implementation details.

3.4 Transport Security​

  • All API traffic must use TLS 1.2+.
  • IP allowlisting is available on request.
  • All requests are logged with partner ID, endpoint, timestamp, and response code (no PHI is logged).

4. Partner Onboarding​

Step 1: BAA Execution​

Sign the Business Associate Agreement.

Step 2: Configuration​

Stealth Health provisions the following for each partner:

ItemDescription
partner_idUnique partner identifier (e.g. ptr_acme_health)
API key pairLive and sandbox credentials
Webhook secretFor verifying webhook signatures
Enrollment slug(s)Custom enrollment page URLs (e.g. enroll.stealth.health/acme/trt-cream)
Branding configLogo, colors, and copy for co-branded enrollment pages
Webhook URLPartner's HTTPS endpoint for receiving events

Step 3: Enrollment Page Setup​

Stealth Health creates partner-specific enrollment pages based on the product categories the partner wants to offer. These pages:

  • Use the partner's branding (logo, color scheme, custom copy).
  • Include the appropriate medical intake questionnaire.
  • Are accessible via partner-specific URLs or can be embedded via iframe.
  • Automatically tag all submissions with the partner's partner_id.

Step 4: Sandbox Testing​

Partners test the full lifecycle in sandbox before going live.

Step 5: Go Live​

Switch to production credentials and enrollment URLs.


5. Integration Flow​

5.1 Sequence Diagram​

Partner Integration Sequence Diagram

5.2 Step-by-Step​

Step 1 — Create Referral Partner calls POST /partner/referrals with a partner_reference (the partner's own customer ID) and the desired product_category. Stealth Health returns a referral_id and a unique enrollment URL.

Step 2 — Customer Enrollment Partner redirects or links their customer to the enrollment URL. The customer sees a co-branded page and completes the medical intake questionnaire.

Step 3 — Payment If payment is required for the product category, the customer pays during enrollment. Some categories are consult-only (payment after approval).

Step 4 — Clinical Review A licensed Stealth Health physician reviews the intake and either approves a prescription or denies the request (with a reason communicated to the patient, not the partner).

Step 5 — Fulfillment Approved prescriptions are sent to a licensed pharmacy partner for compounding and shipping. Partners receive status updates at each stage.


6. API Reference​

All endpoints are prefixed with /partner.

6.1 POST /partner/referrals​

Create a new patient referral. Call this before sending a customer to enrollment.

Request:

{
"partner_reference": "cust_12345",
"product_category": "trt-cream",
"metadata": {
"campaign": "spring-2026",
"source": "website"
}
}
FieldTypeRequiredDescription
partner_referencestringYesPartner's own identifier for this customer. Must be unique per partner. Max 128 chars.
product_categorystringYesOne of the available categories (see 6.5).
metadataobjectNoArbitrary key-value pairs for partner's own tracking (max 20 keys, 500 chars per value). Not used by Stealth Health.

Response (201 Created):

{
"referral_id": "ref_abc123xyz",
"partner_reference": "cust_12345",
"product_category": "trt-cream",
"enrollment_url": "https://enroll.stealth.health/acme/trt-cream?ref=ref_abc123xyz",
"status": "created",
"created_at": "2026-03-02T14:00:00Z",
"expires_at": "2026-03-09T14:00:00Z"
}

Note: Enrollment URLs expire after 7 days. A new referral must be created if the link expires.


6.2 GET /partner/referrals/:referral_id​

Retrieve the current status of a referral.

Response (200 OK):

{
"referral_id": "ref_abc123xyz",
"partner_reference": "cust_12345",
"product_category": "trt-cream",
"status": "approved",
"status_history": [
{ "status": "created", "at": "2026-03-02T14:00:00Z" },
{ "status": "enrolled", "at": "2026-03-02T14:15:00Z" },
{ "status": "pending_review", "at": "2026-03-02T14:15:00Z" },
{ "status": "approved", "at": "2026-03-03T09:30:00Z" }
],
"fulfillment": {
"status": "shipped",
"carrier": "USPS",
"estimated_delivery": "2026-03-07",
"updated_at": "2026-03-04T11:00:00Z"
},
"payment": {
"status": "paid",
"amount_cents": 14900,
"currency": "USD",
"paid_at": "2026-03-02T14:15:00Z"
},
"metadata": {
"campaign": "spring-2026",
"source": "website"
},
"created_at": "2026-03-02T14:00:00Z"
}

6.3 GET /partner/referrals​

List all referrals for the authenticated partner.

Query Parameters:

ParamTypeDefaultDescription
statusstring(all)Filter by status: created, enrolled, pending_review, approved, denied, expired
fulfillment_statusstring(all)Filter by fulfillment: awaiting_shipment, shipped, in_transit, delivered
partner_referencestring—Look up by partner's own reference
product_categorystring(all)Filter by category
created_afterISO 8601—Only referrals created after this timestamp
created_beforeISO 8601—Only referrals created before this timestamp
limitinteger50Max results per page (1–200)
cursorstring—Pagination cursor from previous response

Response (200 OK):

{
"referrals": [
{ "referral_id": "ref_abc123xyz", "partner_reference": "cust_12345", "product_category": "trt-cream", "status": "approved", "..." : "..." },
{ "referral_id": "ref_def456uvw", "partner_reference": "cust_67890", "product_category": "peptides", "status": "enrolled", "..." : "..." }
],
"pagination": {
"has_more": true,
"next_cursor": "eyJjcmVhdGVkX2F0Ijo..."
}
}

6.4 GET /partner/referrals/summary​

Aggregate counts for dashboard / reporting.

Query Parameters:

ParamTypeDescription
periodstringday, week, month, all_time (default: month)
product_categorystringFilter by category

Response (200 OK):

{
"period": "month",
"start": "2026-02-01T00:00:00Z",
"end": "2026-02-28T23:59:59Z",
"totals": {
"created": 150,
"enrolled": 120,
"pending_review": 15,
"approved": 90,
"denied": 12,
"expired": 3,
"shipped": 75,
"delivered": 60
},
"by_category": {
"trt-cream": { "created": 80, "approved": 50, "denied": 5 },
"peptides": { "created": 40, "approved": 30, "denied": 4 }
},
"revenue": {
"total_cents": 756000,
"currency": "USD"
}
}

6.5 GET /partner/products​

List product categories available to this partner.

Response (200 OK):

{
"products": [
{
"category": "trt-cream",
"display_name": "Testosterone Replacement Therapy (Cream)",
"description": "Compounded testosterone cream for hormone optimization",
"jurisdictions": ["US"],
"enrollment_url_template": "https://enroll.stealth.health/acme/trt-cream?ref={referral_id}",
"requires_payment_at_enrollment": true,
"price_range": {
"min_cents": 9900,
"max_cents": 19900,
"currency": "USD"
}
},
{
"category": "peptides",
"display_name": "BPC-157 Peptide Therapy",
"description": "BPC-157 peptide for tissue repair and recovery support",
"jurisdictions": ["US"],
"enrollment_url_template": "https://enroll.stealth.health/acme/peptides?ref={referral_id}",
"requires_payment_at_enrollment": true,
"price_range": {
"min_cents": 14900,
"max_cents": 24900,
"currency": "USD"
}
}
]
}

Generate a tokenized, time-limited tracking link that the partner can display to their end user. The link opens the Stealth Health patient portal's shipment tracking view without exposing the tracking number to the partner.

Response (200 OK):

{
"referral_id": "ref_abc123xyz",
"tracking_url": "https://portal.stealth.health/track/tkn_9f8e7d6c5b4a...",
"expires_at": "2026-03-05T14:00:00Z"
}

Returns 404 if no shipment exists for the referral yet.


6.7 POST /partner/referrals/:referral_id/cancel​

Request cancellation of a referral. Only possible if the referral has not yet reached approved status.

Request:

{
"reason": "Customer requested cancellation"
}

Response (200 OK):

{
"referral_id": "ref_abc123xyz",
"status": "cancelled",
"cancelled_at": "2026-03-02T16:00:00Z"
}

Returns 409 Conflict if the referral is already approved or further in the lifecycle.


7. Webhook Events​

7.1 Overview​

Stealth Health sends HTTPS POST requests to the partner's registered webhook URL whenever a referral's status changes. Events are delivered at least once — partners must handle idempotency.

7.2 Payload Format​

{
"event_id": "evt_1a2b3c4d",
"event_type": "referral.approved",
"referral_id": "ref_abc123xyz",
"partner_reference": "cust_12345",
"data": {
"status": "approved",
"product_category": "trt-cream",
"occurred_at": "2026-03-03T09:30:00Z"
},
"metadata": {
"campaign": "spring-2026"
},
"created_at": "2026-03-03T09:30:01Z"
}

7.3 Event Types​

EventTriggerdata includes
referral.enrolledPatient completes intake formproduct_category
referral.pending_reviewIntake submitted for doctor review—
referral.approvedDoctor approves prescription—
referral.deniedDoctor denies prescriptiondenial_category (e.g. medical_contraindication, incomplete_information, not_a_candidate)
referral.payment_duePayment required from patientamount_cents, currency
referral.payment_completePatient payment receivedamount_cents, currency
referral.awaiting_shipmentPrescription sent to pharmacy—
referral.shippedOrder shipped by pharmacycarrier, estimated_delivery
referral.in_transitShipment in transit (carrier scan)carrier
referral.out_for_deliveryShipment out for deliverycarrier
referral.deliveredShipment deliveredcarrier, delivered_at
referral.delivery_exceptionDelivery issue (failed attempt, etc.)carrier, exception_type
referral.cancelledReferral cancelledcancelled_by (partner or patient)
referral.expiredEnrollment URL expired without completion—

7.4 Signature Verification​

import hmac
import hashlib

def verify_signature(payload_body: bytes, signature_header: str, webhook_secret: str) -> bool:
expected = "sha256=" + hmac.new(
webhook_secret.encode(),
payload_body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)

7.5 Retry Policy​

AttemptDelay
1Immediate
230 seconds
35 minutes
430 minutes
52 hours
612 hours

After 6 failed attempts (non-2xx response or timeout), the event is placed in a dead letter queue. Partners can retrieve missed events via GET /partner/events (see 6.8).

Partners must respond with a 2xx status code within 10 seconds to acknowledge receipt.


8. Data Models​

8.1 Referral Object​

{
"referral_id": "string — Stealth Health's unique identifier",
"partner_reference": "string — Partner's customer identifier",
"product_category": "string — e.g. trt-cream, peptides",
"status": "string — See Appendix: Status Lifecycle",
"status_history": [
{ "status": "string", "at": "ISO 8601 timestamp" }
],
"fulfillment": {
"status": "string | null",
"carrier": "string | null",
"estimated_delivery": "string (YYYY-MM-DD) | null",
"updated_at": "ISO 8601 timestamp | null"
},
"payment": {
"status": "string — due | paid | refunded | not_applicable",
"amount_cents": "integer | null",
"currency": "string — USD | CAD",
"paid_at": "ISO 8601 timestamp | null"
},
"metadata": "object — Partner-provided key-value pairs",
"created_at": "ISO 8601 timestamp",
"expires_at": "ISO 8601 timestamp — Enrollment link expiry"
}

8.2 Event Object​

{
"event_id": "string — Unique event identifier (for idempotency)",
"event_type": "string — e.g. referral.approved",
"referral_id": "string",
"partner_reference": "string",
"data": "object — Event-specific payload (see Section 7.3)",
"metadata": "object — Mirror of referral metadata",
"created_at": "ISO 8601 timestamp"
}

9. Error Handling​

9.1 HTTP Status Codes​

CodeMeaning
200Success
201Created
400Bad request — invalid parameters
401Unauthorized — invalid or missing API key
403Forbidden — valid key but insufficient permissions
404Not found — referral doesn't exist or doesn't belong to this partner
409Conflict — action not allowed in current state
422Unprocessable — valid syntax but business rule violation
429Rate limited
500Internal server error

9.2 Error Response Format​

{
"error": {
"code": "REFERRAL_NOT_CANCELLABLE",
"message": "Referral ref_abc123xyz cannot be cancelled because it has already been approved.",
"details": {
"referral_id": "ref_abc123xyz",
"current_status": "approved"
}
}
}

9.3 Common Error Codes​

CodeDescription
INVALID_PARTNER_REFERENCEpartner_reference already used or invalid format
INVALID_PRODUCT_CATEGORYCategory not available to this partner
REFERRAL_NOT_FOUNDReferral doesn't exist or unauthorized
REFERRAL_NOT_CANCELLABLEReferral past the cancellable stage
REFERRAL_EXPIREDEnrollment link has expired
RATE_LIMITEDToo many requests

10. Rate Limits​

TierRequests / minuteBurst
Sandbox6010/sec
Production30050/sec
EnterpriseCustomCustom

Rate limit headers are included in every response:

X-RateLimit-Limit: 300
X-RateLimit-Remaining: 298
X-RateLimit-Reset: 1709395200

11. Environments​

EnvironmentBase URLPurpose
Sandboxhttps://sandbox.stealth.healthTesting with mock data, no real doctors or pharmacy
Productionhttps://api.stealth.healthLive environment

Sandbox behavior:

  • Referrals auto-advance through the lifecycle every 60 seconds.
  • Payment always succeeds with test card 4242 4242 4242 4242.
  • Webhooks are sent to the registered sandbox webhook URL.
  • No real clinical review occurs.

Appendix: Status Lifecycle​

Terminal states: delivered, denied, cancelled, expired


Questions for Partner Discussion​

  1. Revenue share model — How will partner compensation be structured? Per-referral fee, revenue share, or flat monthly?
  2. Branding depth — Does the partner want full white-label (custom domain, emails from their domain) or co-branded?
  3. Product categories — Which categories does the partner want to offer?
  4. Jurisdiction — US only, Canada only, or both?
  5. Patient support — Will the partner handle first-line patient support, or will Stealth Health?
  6. Reporting needs — Does the partner need additional reporting endpoints beyond the summary endpoint?
  7. Refund handling — How should refunds be coordinated between partner and Stealth Health?
  8. Re-enrollment — Should the same customer be able to enroll for additional product categories, and how should that be linked?

This document is a proposal for discussion purposes. Endpoint paths, field names, and behaviors are subject to change during implementation.