Overview
The LegUpRx API exposes the same data you see in the partner portal: leads, orders, payouts, sub-accounts, medical intake links, DNA testing links, Care Service links, and Care Services bulk coupon codes. It also publishes webhook events when those records change, and a separate public catalog API for product browsing on telehealthintakeforms.com.
Base URL: /
Format: JSON in, JSON out. All authenticated responses are wrapped in an envelope - typically { data: [...] } with an optional { page: { nextCursor, limit } } for paginated endpoints.
Authentication: authenticated endpoints require a per-user API token created in Settings - API Settings. Public catalog endpoints under https://www.telehealthintakeforms.com/api are unauthenticated and use a partner_id query parameter on the intake link itself for attribution.
Authentication
API tokens are created and managed in Settings - API Settings. Each token is tied to a single portal user. Tokens can be rotated or revoked from that page at any time; revoked tokens stop working immediately.
Send the token in the Authorization header on every request:
Authorization: Bearer <token>
Tokens are scoped to your Clerk user account and start with lrx_live_. The full token is shown only once when you create or rotate it, so save it somewhere secure.
Auth-related errors
| Status | Code | Description |
|---|---|---|
| 401 | missing_bearer | No Authorization: Bearer header was sent. |
| 401 | invalid_token | Token is malformed, revoked, expired, or not user-scoped. |
| 401 | unknown_user | Token verifies but no portal user matches its subject. |
| 503 | api_keys_unavailable | Reserved for environments where API token verification cannot run. |
Authenticated request
GET /api/v1/leads HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json
List leads
Returns leads collected for your partner account, ordered newest first. Paginated using a cursor; pass the nextCursor value from the previous response in the cursor query parameter to fetch the next page.
Query parameters
| Name | Type | Description |
|---|---|---|
limit | integer (1-200) | Page size. Defaults to 50. |
cursor | string | Opaque pagination cursor from the previous response. |
Response
Envelope: { data: LeadRow[], page: { nextCursor, limit } }. If a lead has not consented to email or SMS, the matching email or phone field is returned as No Consent.
{
"data": [
{
"id": "6f1a2c0e-4f0d-4c0a-9b41-7c9c2c0c0001",
"partnerId": "RFMLPVN1",
"subId": "12",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phone": "+15555550123",
"origin": "managed-website",
"location": "TX",
"questionId": "weight-loss-v2",
"createdAt": "2026-05-09T17:42:11.214Z",
"updatedAt": "2026-05-09T17:42:11.214Z"
}
],
"page": {
"nextCursor": "MjAyNi0wNS0wOVQxNzo0MjoxMS4yMTRafDZmMWEyYzBlLTRmMGQtNGMwYS05YjQxLTdjOWMyYzBjMDAwMQ==",
"limit": 50
}
}Errors
| Status | Code | Description |
|---|---|---|
| 400 | invalid_request | `limit` is not a positive integer. |
| 401 | missing_bearer | Authorization header missing. |
| 401 | invalid_token | Token is invalid, revoked, or expired. |
| 429 | rate_limited | Too many requests for this token. |
GET /api/v1/leads
GET /api/v1/leads?limit=50 HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json
List DNA testing links
Returns DNA test intake links available for your account. Requires DNA access; otherwise returns 403.
Response
Envelope: { data: DnaProductLink[] }.
{
"data": [
{
"recordId": "09a889e4-88cc-4b4f-8f37-7f93654d1ec1",
"email": "partner@example.com",
"partnerId": "RFMLPVN1",
"productName": "MTHFR Methylation Panel",
"description": "At-home DNA collection for methylation pathway insights.",
"intakeUrl": "https://medical.leguprecovery.com/start-online-visit/dna-mthfr?partner_id=RFMLPVN1",
"productImageUrl": "https://www.telehealthintakeforms.com/api/files/7c5271fd-b347-46d7-8e44-c0d3762ab000",
"minimumPrice": 199,
"recommendedPrice": 249,
"maximumPrice": 349,
"userSetPrice": 249,
"parentProduct": [
"MTHFR Methylation Panel"
],
"available": true
}
]
}Errors
| Status | Code | Description |
|---|---|---|
| 401 | missing_bearer | Authorization header missing. |
| 403 | forbidden | DNA access is disabled for this account. |
GET /api/v1/dna-links
GET /api/v1/dna-links HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json
List medical intake links
Returns medical intake product links assigned to your account. Pass sub to rewrite each link's partner_id to attribute orders to the given sub-account (1-250).
Query parameters
| Name | Type | Description |
|---|---|---|
sub | integer (1-250) | Sub-account number. The matching `subId` must already exist on your account. |
Response
Envelope: { data: PartnerProductLink[], sub: string | null }.
{
"data": [
{
"recordId": "7a56b350-5a59-4df1-806c-108b39439180",
"email": "partner@example.com",
"partnerId": "RFMLPVN1",
"productName": "Injectable Semaglutide",
"details": "Available Nationwide",
"url": "https://medical.leguprecovery.com/start-online-visit/sema-personalized-intake-vialsrx?partner_id=RFMLPVN1",
"imageUrl": "https://www.telehealthintakeforms.com/api/files/9c9585f5-4783-4c2b-8776-93e51f547409",
"category": [
"weight-loss"
],
"suggestedPrices": "$349 / 1 month",
"tiers": [
{
"key": "1-month",
"label": "1 month",
"minPrice": 299,
"maxPrice": 599,
"userPrice": 349,
"commission": 75
}
]
}
],
"sub": null
}Errors
| Status | Code | Description |
|---|---|---|
| 400 | invalid_request | `sub` is out of range or unknown for this account. |
| 401 | missing_bearer | Authorization header missing. |
GET /api/v1/medical-intake-links
GET /api/v1/medical-intake-links HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json
List Care Service links
Returns Care Service links available to your account. Results are filtered by active subscription/manual override, yearly-plan bundle access, individual service access, and category feature flags. URLs in the response are generated from the admin-configured Care Services base URLs; the examples below use placeholder domains.
Each result includes a default url (no duration pre-selected), a redeemUrl for Bulk Code Redemption, and a tiers array. Each tier contains a tier-specific url that already includes the matching m= query parameter, so you can hand the link directly to a patient without rebuilding it yourself.
The URLs are the same patient-facing checkout links rendered in the partner portal under Partner Links - Care Services. Patient-facing URL parameters appended to each link are documented in the "URL parameters" table below.
Query parameters
| Name | Type | Description |
|---|---|---|
service | string | Optional service key: primary-care, urgent-care, mental-health, dermatology, or veterinary-care. |
sub | integer (1-250) | Optional sub-account number. The matching `subId` must already exist on your account. When provided, every returned URL has `sub=<id>` appended for attribution. |
duration | integer (1, 3, 6, 12) | Optional duration. When provided, the top-level `url` includes `m=<duration>` and the `tiers` array is filtered to that duration only. |
Response
Envelope: { data: CareServiceLink[], sub, service, duration }. Admin-only catalog fields and pricing caps are not returned.
**Patient-facing URL parameters** (already appended to every url/redeemUrl we return - documented so you understand how to interpret or, if needed, regenerate them):
- partner_id (always present): your partner attribution code. Required for revenue and order attribution.
- m (optional, present on tier urls and when duration is requested): term in months. One of 1, 3, 6, 12. Pre-selects the matching tier on the checkout page.
- sub (optional, present when sub was passed): sub-account number 1-250 for downstream attribution.
- redeem=true (only on redeemUrl): switches the destination from the Stripe-checkout flow to the Bulk Code Redemption screen. Patients enter a 12-character coupon code (no card collected) and we provision the membership directly.
{
"data": [
{
"recordId": "2d2a6e76-41b5-4b64-a5fb-c1d9de8f0001",
"service": "primary-care",
"productName": "Primary Care Visit",
"description": "Virtual primary care access for eligible patients.",
"imageUrl": "https://example-care-services.com/assets/primary-care.png",
"url": "https://example-care-services.com/start?partner_id=RFMLPVN1",
"redeemUrl": "https://example-care-services.com/start?partner_id=RFMLPVN1&redeem=true",
"tiers": [
{
"key": "1-month",
"label": "1 month",
"userPrice": 99,
"commission": 30,
"url": "https://example-care-services.com/start?partner_id=RFMLPVN1&m=1"
}
]
}
],
"sub": null,
"service": null,
"duration": null
}Errors
| Status | Code | Description |
|---|---|---|
| 400 | invalid_request | `sub`, `service`, or `duration` is invalid. |
| 401 | missing_bearer | Authorization header missing. |
| 404 | not_found | Care Services API is disabled (CARE_SERVICES_API_ENABLED is off). |
| 429 | rate_limited | Too many requests for this token. |
GET /api/v1/care-service-links
GET /api/v1/care-service-links?service=primary-care&duration=1 HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json
List Care Services coupons
Download Care Services bulk coupon codes owned by the authenticated partner. Each coupon is single-use, locked to a productSlug + months combination, and either redeemed by a patient via your Bulk Code Redemption URL or marked void/expired. Admin tokens may filter by any partner_id; non-admin tokens are automatically scoped to their own partner.
Use this endpoint to programmatically pull every code you have purchased (including ones still in active status that have not yet been redeemed) so you can distribute them, store them in your own system, or reconcile redemptions.
Returns JSON by default. Pass format=csv to download a spreadsheet (the same columns as the "Download all CSV" button in the partner portal Bulk Orders view) instead.
Query parameters
| Name | Type | Description |
|---|---|---|
status | string (csv) | Optional comma-separated subset of `active,redeemed,void,expired`. |
partner_id | string | Admin only. Filter to a specific partner. |
product_slug | string | Optional product slug filter (e.g. `primary`, `urgent-care`). |
format | string | Response format: `json` (default) or `csv`. When `csv`, the response is a `text/csv` attachment named `care-services-coupons-<YYYY-MM-DD>.csv` and the total row count is returned in the `X-Total-Count` header. |
limit | integer (1-500) | Page size. Defaults to 100 for JSON, 500 for CSV. |
offset | integer (>=0) | Page offset. Defaults to 0. For full CSV exports of large coupon batches, paginate by incrementing `offset` and concatenating files. |
Response
JSON envelope: { data: CareServiceCoupon[], total, limit, offset }. Each coupon includes code (the raw 12-character A-Z 0-9 string), productSlug, months, status, expiresAt, redeemedAt, redeemedEmail, and redeemedLyricPrimaryExternalId so you can reconcile who used what.
CSV columns (with format=csv): code, product_slug, months, status, partner_id, sub_account_id, unit_price_cents, bulk_order_id, purchaser_email, purchaser_source, created_at, expires_at, redeemed_at, redeemed_email, redeemed_lyric_primary_external_id, notes. Values are quoted; embedded quotes are escaped by doubling.
{
"data": [
{
"id": "7e1cf7c0-bf56-4e90-b5be-9ec6e7d5a001",
"code": "A1B2C3D4E5F6",
"partnerId": "RFMLPVN1",
"productSlug": "primary",
"months": 1,
"status": "active",
"expiresAt": "2027-08-15T23:59:59Z",
"redeemedAt": null,
"redeemedEmail": null,
"redeemedLyricPrimaryExternalId": null,
"bulkOrderId": "8b27a12d-6a3f-4f33-9f6f-07ad04aa4e02",
"purchaserEmail": "partner@example.com",
"purchaserSource": "member_purchase",
"unitPriceCents": 9900,
"notes": null,
"createdAt": "2026-05-17T18:00:00Z"
}
],
"total": 1,
"limit": 100,
"offset": 0
}Errors
| Status | Code | Description |
|---|---|---|
| 400 | invalid_request | `product_slug`, `limit`, or `offset` is invalid. |
| 401 | missing_bearer | Authorization header missing. |
| 404 | not_found | Care Services API is disabled (CARE_SERVICES_API_ENABLED is off). |
| 429 | rate_limited | Too many requests for this token. |
GET /api/v1/care-services-coupons
# JSON (default) GET /api/v1/care-services-coupons?status=active HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json # CSV download GET /api/v1/care-services-coupons?format=csv&status=active,redeemed HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: text/csv
List orders
Returns orders attributed to your partner account, including commission and shipping status. Sensitive fields are filtered for non-admin tokens.
Response
Envelope: { data: Order[] }. The order object matches the Orders UI fields: orderId, createdDate, subAccount, product, amount, commission, and status.
{
"data": [
{
"orderId": "order_102938",
"createdDate": "2026-05-01T14:32:10.000Z",
"subAccount": "Austin clinic",
"product": "Injectable Semaglutide",
"amount": 349,
"commission": 75,
"status": "shipped"
}
]
}Errors
| Status | Code | Description |
|---|---|---|
| 401 | missing_bearer | Authorization header missing. |
| 429 | rate_limited | Too many requests for this token. |
GET /api/v1/orders
GET /api/v1/orders HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json
List payouts
Returns payout records for the authenticated partner.
Response
Envelope: { data: Payout[] }. Admin-only receipt and note fields are not included.
{
"data": [
{
"recordId": "5e9036aa-7772-40b6-9efa-38b5d782fb73",
"email": "partner@example.com",
"createdAt": "2026-05-01",
"payoutAmount": 1234.56,
"status": "paid"
}
]
}Errors
| Status | Code | Description |
|---|---|---|
| 401 | missing_bearer | Authorization header missing. |
GET /api/v1/payouts
GET /api/v1/payouts HTTP/1.1 Host: app.leguprx.com Authorization: Bearer $LEGUPRX_API_TOKEN Accept: application/json
Sub-accounts
List, create, and delete sub-accounts. Sub-accounts let you attribute orders, leads, and links to a specific staffer or affiliate using the subId field.
Response
GET envelope: { data: PortalSubAccount[] }. POST returns 201 with { data: PortalSubAccount }. DELETE returns { data: { ok: true } }.
{
"data": [
{
"id": "52c4a0eb-d109-4b44-90df-f0f0864c0195",
"email": "partner@example.com",
"subId": "12",
"nickname": "Austin clinic",
"createdAt": "2026-04-01T10:00:00.000Z",
"updatedAt": "2026-04-01T10:00:00.000Z"
}
]
}Errors
| Status | Code | Description |
|---|---|---|
| 400 | invalid_request | Missing or invalid `subId`/`nickname`/`recordId`. |
| 401 | missing_bearer | Authorization header missing. |
| 404 | not_found | Sub account not found (DELETE). |
| 409 | invalid_request | A sub-account with that `subId` already exists. |
GET /api/v1/sub-accounts
GET /api/v1/sub-accounts HTTP/1.1
Host: app.leguprx.com
Authorization: Bearer $LEGUPRX_API_TOKEN
POST /api/v1/sub-accounts HTTP/1.1
Host: app.leguprx.com
Authorization: Bearer $LEGUPRX_API_TOKEN
Content-Type: application/json
{"subId":"12","nickname":"Austin clinic"}
DELETE /api/v1/sub-accounts HTTP/1.1
Host: app.leguprx.com
Authorization: Bearer $LEGUPRX_API_TOKEN
Content-Type: application/json
{"recordId":"52c4a0eb-d109-4b44-90df-f0f0864c0195"}Webhooks
Webhooks let you react in real time to leads, orders, and payouts. Configure endpoints in Settings - API Settings - Webhooks. Each account can have up to 10 endpoints, and each endpoint receives the event types you select.
- HTTPS only. Plain
http://URLs are rejected at save time. - Deliveries retry up to 6 times with exponential backoff (a few seconds, then minutes, then hours) until your endpoint returns a 2xx status.
- Each delivery is signed with HMAC-SHA256. Verifying the signature is optional, but strongly recommended - see Signature verification.
- Webhook secrets are optional. If you do not set one, deliveries still work, but you should treat signature verification as disabled for that endpoint.
lead.createddeliveries can optionally be delayed by 1 minute, 5 minutes, or 1 hour to give the lead time to enter their phone number on the next intake step before you receive the webhook.- You can attach a single optional custom header (for example a shared bearer token) per endpoint, which we send on every delivery.
Signature verification
Signature verification is optional, but strongly recommended. Every delivery includes an X-LegUpRx-Signature header in the form:
X-LegUpRx-Signature: t=<unix_timestamp>,v1=<sha256_hex>
The signed string is t + '.' + body, where body is the exact raw HTTP request body (do not re-serialize the JSON). Compute HMAC-SHA256 with your endpoint secret as the key and compare in constant time. Reject deliveries whose t is more than 5 minutes old to prevent replays.
We also send X-LegUpRx-Event (the event name) and X-LegUpRx-Delivery (a unique delivery id, useful for idempotent processing).
Verify webhook signature
POST /your-webhook-endpoint HTTP/1.1
Host: yourdomain.com
Content-Type: application/json
X-LegUpRx-Signature: t=1715300000,v1=4f0b8f3bb12c2f70d4e3fb28c85dd438df9ad1186a2c9e5d13afd7b0ac54e8c9
X-LegUpRx-Event: lead.created
X-LegUpRx-Delivery: 5c570818-e918-489e-bebb-fbd9a5f6a47d
{"id":"5c570818-e918-489e-bebb-fbd9a5f6a47d","event":"lead.created","created_at":"2026-05-09T17:42:11.214Z","data":{"lead":{"id":"6f1a2c0e-4f0d-4c0a-9b41-7c9c2c0c0001"}}}lead.created
Fires when a new lead is captured for your partner account from any source (managed website, public links, sub-account collection forms).
Example payload
{
"id": "0d8a0fe2-b19c-4f61-bf65-7a16c0371176",
"event": "lead.created",
"created_at": "2026-05-09T17:42:11.214Z",
"data": {
"lead": {
"id": "6f1a2c0e-4f0d-4c0a-9b41-7c9c2c0c0001",
"partnerId": "RFMLPVN1",
"subId": "12",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phone": "+15555550123",
"origin": "managed-website",
"location": "TX",
"questionId": "weight-loss-v2",
"createdAt": "2026-05-09T17:42:11.214Z",
"updatedAt": "2026-05-09T17:42:11.214Z"
}
}
}lead.enriched
Fires when a previously captured lead has its phone number filled in or updated after the initial capture (typically a few minutes later, when the lead completes the next intake step).
Example payload
{
"id": "ff34b08c-58ef-4edc-81c9-b12f94e57a11",
"event": "lead.enriched",
"created_at": "2026-05-09T18:11:02.005Z",
"data": {
"lead": {
"id": "6f1a2c0e-4f0d-4c0a-9b41-7c9c2c0c0001",
"partnerId": "RFMLPVN1",
"subId": "12",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phone": "+15555550123",
"origin": "managed-website",
"location": "TX",
"questionId": "weight-loss-v2",
"createdAt": "2026-05-09T17:42:11.214Z",
"updatedAt": "2026-05-09T17:42:11.214Z"
},
"previousPhone": "",
"currentPhone": "+15555550123"
}
}order.created
Fires when a new order is attributed to your partner account, including its commission breakdown and shipping status.
Example payload
{
"id": "736b6ed2-1e5e-4c13-9faa-31a3d42f0909",
"event": "order.created",
"created_at": "2026-05-09T19:01:00.000Z",
"data": {
"source": "admin",
"order": {
"orderId": "order_102938",
"createdDate": "2026-05-01T14:32:10.000Z",
"subAccount": "Austin clinic",
"product": "Injectable Semaglutide",
"amount": 349,
"commission": 75,
"status": "shipped"
}
}
}payout.created
Fires when a payout record is created for your account.
Example payload
{
"id": "b52f2e65-34c8-4fae-874e-e9f6de2e592d",
"event": "payout.created",
"created_at": "2026-05-09T20:00:00.000Z",
"data": {
"payout": {
"recordId": "5e9036aa-7772-40b6-9efa-38b5d782fb73",
"email": "partner@example.com",
"createdAt": "2026-05-01",
"payoutAmount": 1234.56,
"status": "paid"
}
}
}Weight loss
Active weight-loss products available for distribution.
These endpoints are unauthenticated. To attribute traffic to your account, distribute intake links that already include your partner_id, for example:
https://www.telehealthintakeforms.com/api/weight-loss?partner_id=RFMLPVN1
Typical response headers include Content-Type: application/json; Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate with Cdn-Cache-Control: no-store; Access-Control-Allow-Methods: GET, OPTIONS; Access-Control-Allow-Headers: Content-Type.
Example response
{
"products": [
{
"id": "06c641ae-bebd-4e53-b267-f0e6b5b4e272",
"name": "Injectable Lipo-B",
"image": "https://www.telehealthintakeforms.com/api/files/a77ee64e-4a59-4d4d-81be-f042bae0b9b3",
"imageKind": "file",
"imageFileId": "a77ee64e-4a59-4d4d-81be-f042bae0b9b3",
"imageSourceUrl": "https://www.telehealthintakeforms.com/api/files/a77ee64e-4a59-4d4d-81be-f042bae0b9b3",
"intakeUrl": "https://medical.leguprecovery.com/start-online-visit/lipob-intake-vialsrx?partner_id=RFMLPVN1",
"price1Month": "$574.00",
"price3Month": "$449.00",
"price6Month": "$849.00",
"details": "Available Nationwide"
}
],
"count": 11
}https://www.telehealthintakeforms.com/api/weight-loss?partner_id=RFMLPVN1. Counts and product lists can change as catalog availability changes.GET /weight-loss
GET /api/weight-loss?partner_id=RFMLPVN1 HTTP/1.1 Host: www.telehealthintakeforms.com Accept: application/json
Men's health
Active men's health products.
These endpoints are unauthenticated. To attribute traffic to your account, distribute intake links that already include your partner_id, for example:
https://www.telehealthintakeforms.com/api/mens-health?partner_id=RFMLPVN1
Typical response headers include Content-Type: application/json; Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate with Cdn-Cache-Control: no-store; Access-Control-Allow-Methods: GET, OPTIONS; Access-Control-Allow-Headers: Content-Type.
Example response
{
"products": [
{
"id": "c6016e64-2ef3-4dad-b999-be0efe6289fb",
"name": "Cialis",
"image": "https://www.telehealthintakeforms.com/api/files/c23ad164-fc36-4a39-b26d-065ab2df21fb",
"imageKind": "file",
"imageFileId": "c23ad164-fc36-4a39-b26d-065ab2df21fb",
"imageSourceUrl": "https://www.telehealthintakeforms.com/api/files/c23ad164-fc36-4a39-b26d-065ab2df21fb",
"intakeUrl": "https://medical.leguprecovery.com/start-online-visit/ed?partner_id=RFMLPVN1",
"price1Month": "$549.00",
"price3Month": "$0.00",
"price6Month": "$0.00",
"details": "Not available in South Carolina"
}
],
"count": 4
}https://www.telehealthintakeforms.com/api/mens-health?partner_id=RFMLPVN1. Counts and product lists can change as catalog availability changes.GET /mens-health
GET /api/mens-health?partner_id=RFMLPVN1 HTTP/1.1 Host: www.telehealthintakeforms.com Accept: application/json
Women's health
Active women's health products.
These endpoints are unauthenticated. To attribute traffic to your account, distribute intake links that already include your partner_id, for example:
https://www.telehealthintakeforms.com/api/womens-health?partner_id=RFMLPVN1
Typical response headers include Content-Type: application/json; Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate with Cdn-Cache-Control: no-store; Access-Control-Allow-Methods: GET, OPTIONS; Access-Control-Allow-Headers: Content-Type.
Example response
{
"products": [
{
"id": "694759f6-2b17-4128-ba8c-2dfa274fb87e",
"name": "Enclomiphene",
"image": "https://www.telehealthintakeforms.com/api/files/7412c668-3b12-4595-b108-2a96a809f31f",
"imageKind": "file",
"imageFileId": "7412c668-3b12-4595-b108-2a96a809f31f",
"imageSourceUrl": "https://www.telehealthintakeforms.com/api/files/7412c668-3b12-4595-b108-2a96a809f31f",
"intakeUrl": "https://medical.leguprecovery.com/start-online-visit/enclomiphene-intake?partner_id=RFMLPVN1",
"price1Month": "$224.00",
"price3Month": "$0.00",
"price6Month": "$0.00",
"details": "COMING SOON 5/31/2026! Available Nationwide!"
}
],
"count": 4
}https://www.telehealthintakeforms.com/api/womens-health?partner_id=RFMLPVN1. Counts and product lists can change as catalog availability changes.GET /womens-health
GET /api/womens-health?partner_id=RFMLPVN1 HTTP/1.1 Host: www.telehealthintakeforms.com Accept: application/json
Hair loss
Active hair-loss products.
These endpoints are unauthenticated. To attribute traffic to your account, distribute intake links that already include your partner_id, for example:
https://www.telehealthintakeforms.com/api/hair-loss?partner_id=RFMLPVN1
Typical response headers include Content-Type: application/json; Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate with Cdn-Cache-Control: no-store; Access-Control-Allow-Methods: GET, OPTIONS; Access-Control-Allow-Headers: Content-Type.
Example response
{
"products": [
{
"id": "b2abf87a-b350-4864-9df5-08cc44c4bf28",
"name": "Finasteride Tablets",
"image": "https://www.telehealthintakeforms.com/api/files/073ba9d7-a446-4471-be65-41a3ca2a451e",
"imageKind": "file",
"imageFileId": "073ba9d7-a446-4471-be65-41a3ca2a451e",
"imageSourceUrl": "https://www.telehealthintakeforms.com/api/files/073ba9d7-a446-4471-be65-41a3ca2a451e",
"intakeUrl": "https://medical.leguprecovery.com/start-online-visit/hairloss?partner_id=RFMLPVN1",
"price1Month": "$124.00",
"price3Month": "$0.00",
"price6Month": "$0.00",
"details": "Available Nationwide"
}
],
"count": 3
}https://www.telehealthintakeforms.com/api/hair-loss?partner_id=RFMLPVN1. Counts and product lists can change as catalog availability changes.GET /hair-loss
GET /api/hair-loss?partner_id=RFMLPVN1 HTTP/1.1 Host: www.telehealthintakeforms.com Accept: application/json
Wellness
Active wellness and longevity products.
These endpoints are unauthenticated. To attribute traffic to your account, distribute intake links that already include your partner_id, for example:
https://www.telehealthintakeforms.com/api/wellness?partner_id=RFMLPVN1
Typical response headers include Content-Type: application/json; Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate with Cdn-Cache-Control: no-store; Access-Control-Allow-Methods: GET, OPTIONS; Access-Control-Allow-Headers: Content-Type.
Example response
{
"products": [
{
"id": "a9bef966-e60f-4875-893e-b18c9e6a2ae4",
"name": "Injectable B-12",
"image": "https://www.telehealthintakeforms.com/api/files/f420cbc3-ff2e-4644-92b8-a2f04f845c60",
"imageKind": "file",
"imageFileId": "f420cbc3-ff2e-4644-92b8-a2f04f845c60",
"imageSourceUrl": "https://www.telehealthintakeforms.com/api/files/f420cbc3-ff2e-4644-92b8-a2f04f845c60",
"intakeUrl": "https://medical.leguprecovery.com/start-online-visit/b12-intake?partner_id=RFMLPVN1",
"price1Month": "$249.00",
"price3Month": "$0.00",
"price6Month": "$0.00",
"details": "Not available in Louisiana, Mississippi, New Mexico"
}
],
"count": 6
}https://www.telehealthintakeforms.com/api/wellness?partner_id=RFMLPVN1. Counts and product lists can change as catalog availability changes.GET /wellness
GET /api/wellness?partner_id=RFMLPVN1 HTTP/1.1 Host: www.telehealthintakeforms.com Accept: application/json
All products
Combined active medication link product catalog across all medication categories.
These endpoints are unauthenticated. To attribute traffic to your account, distribute intake links that already include your partner_id, for example:
https://www.telehealthintakeforms.com/api/all-products?partner_id=RFMLPVN1
Typical response headers include Content-Type: application/json; Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate with Cdn-Cache-Control: no-store; Access-Control-Allow-Methods: GET, OPTIONS; Access-Control-Allow-Headers: Content-Type.
Example response
{
"products": [
{
"id": "c6016e64-2ef3-4dad-b999-be0efe6289fb",
"name": "Cialis",
"image": "https://www.telehealthintakeforms.com/api/files/c23ad164-fc36-4a39-b26d-065ab2df21fb",
"imageKind": "file",
"imageFileId": "c23ad164-fc36-4a39-b26d-065ab2df21fb",
"imageSourceUrl": "https://www.telehealthintakeforms.com/api/files/c23ad164-fc36-4a39-b26d-065ab2df21fb",
"intakeUrl": "https://medical.leguprecovery.com/start-online-visit/ed?partner_id=RFMLPVN1",
"price1Month": "$549.00",
"price3Month": "$0.00",
"price6Month": "$0.00",
"details": "Not available in South Carolina"
}
],
"count": 28
}https://www.telehealthintakeforms.com/api/all-products?partner_id=RFMLPVN1. Counts and product lists can change as catalog availability changes.GET /all-products
GET /api/all-products?partner_id=RFMLPVN1 HTTP/1.1 Host: www.telehealthintakeforms.com Accept: application/json
Embed Care Services
Partners can embed their Care Services catalog on their own site with the iframe URL shown in their Care Services section. Treat that URL like a shareable tracking link, not a secret. The embedded view only renders services the partner can currently access and respects category feature flags.
Replace the placeholder src below with the Care Services embed URL copied from the partner portal. Do not build this from the API docs domain. The payment-link domain accepts a few query parameters:
partner_id(required): your partner attribution code; auto-populated by the partner portal's "Copy URL" buttons.service: one ofprimary-care,urgent-care,mental-health,dermatology,veterinary-care. Filters the embedded catalog.m: term in months:1,3,6, or12. Pre-selects a duration on the intake.sub: optional sub-account number (1-250) to attribute the order to a downstream account.redeem=true: switches the page from the Stripe checkout flow to the Bulk Code Redemption screen. Patients enter a 12-character coupon code (no card collected) and we provision the care services membership directly. Use the "Copy Bulk Code Redemption URL" button on each Care Services row to generate this URL.
<iframe
id="leguprx-care-services"
src="PASTE_YOUR_CARE_SERVICES_EMBED_URL_HERE"
style="width:100%;border:0;min-height:700px;border-radius:16px;"
loading="lazy"
></iframe>
<script>
window.addEventListener('message', (event) => {
if (event.data?.type !== 'leguprx-api-docs-height') return;
document.getElementById('leguprx-care-services').style.height = event.data.height + 'px';
});
</script>{
"placeholderUrl": "PASTE_YOUR_CARE_SERVICES_EMBED_URL_HERE",
"whereToFindIt": "Partner Links > Care Services in the partner portal",
"notes": "Use the URL shown in the partner Care Services section. It already includes the correct partner attribution."
}Errors and rate limits
All errors use a consistent envelope:
{
"error": {
"code": "invalid_request",
"message": "limit must be a positive integer."
}
}Rate limits are enforced per API token, per endpoint group. When a request is rate-limited, the response includes X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, and Retry-After headers when applicable.
| Status | Code | Description |
|---|---|---|
| 401 | missing_bearer | Request did not include `Authorization: Bearer <token>`. |
| 401 | invalid_token | Token is malformed, revoked, expired, or not user-scoped. |
| 401 | unknown_user | The token verifies, but no portal user matches its subject. |
| 403 | forbidden | The account is inactive or the endpoint is disabled for this account (for example DNA links). |
| 404 | not_found | The referenced record does not exist or does not belong to this account. |
| 400 | invalid_request | A query/body parameter failed validation. |
| 429 | rate_limited | Per-token rate limit exceeded for this endpoint. |
| 500 | internal_error | Unexpected server error. Safe to retry with backoff. |
| 503 | api_keys_unavailable | Reserved for environments where API token verification cannot run. |