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.

These APIs, webhooks, examples, and documentation are provided as is and without warranty. LegUpRx does not guarantee uninterrupted availability, exact delivery timing, or that examples cover every integration case. You are responsible for validating your implementation, handling retries and failures, and confirming that your use complies with your own business, privacy, and compliance requirements.

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

StatusCodeDescription
401missing_bearerNo Authorization: Bearer header was sent.
401invalid_tokenToken is malformed, revoked, expired, or not user-scoped.
401unknown_userToken verifies but no portal user matches its subject.
503api_keys_unavailableReserved 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

GET/api/v1/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

NameTypeDescription
limitinteger (1-200)Page size. Defaults to 50.
cursorstringOpaque 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

StatusCodeDescription
400invalid_request`limit` is not a positive integer.
401missing_bearerAuthorization header missing.
401invalid_tokenToken is invalid, revoked, or expired.
429rate_limitedToo 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 Care Services coupons

GET/api/v1/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

NameTypeDescription
statusstring (csv)Optional comma-separated subset of `active,redeemed,void,expired`.
partner_idstringAdmin only. Filter to a specific partner.
product_slugstringOptional product slug filter (e.g. `primary`, `urgent-care`).
formatstringResponse 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.
limitinteger (1-500)Page size. Defaults to 100 for JSON, 500 for CSV.
offsetinteger (>=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

StatusCodeDescription
400invalid_request`product_slug`, `limit`, or `offset` is invalid.
401missing_bearerAuthorization header missing.
404not_foundCare Services API is disabled (CARE_SERVICES_API_ENABLED is off).
429rate_limitedToo 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

GET/api/v1/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

StatusCodeDescription
401missing_bearerAuthorization header missing.
429rate_limitedToo 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

GET/api/v1/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

StatusCodeDescription
401missing_bearerAuthorization 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

GET/api/v1/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

StatusCodeDescription
400invalid_requestMissing or invalid `subId`/`nickname`/`recordId`.
401missing_bearerAuthorization header missing.
404not_foundSub account not found (DELETE).
409invalid_requestA 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.created deliveries 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

EVENTlead.created

Fires when a new lead is captured for your partner account from any source (managed website, public links, sub-account collection forms).

Optional 1 minute, 5 minute, or 1 hour delivery delay can be configured per endpoint. The delay gives the lead time to enter their phone number on the next intake step before you receive the webhook, so the payload is more useful for follow-up.

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

EVENTlead.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

EVENTorder.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

EVENTpayout.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

GEThttps://www.telehealthintakeforms.com/api/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
}
Example response for 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

GEThttps://www.telehealthintakeforms.com/api/mens-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
}
Example response for 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

GEThttps://www.telehealthintakeforms.com/api/womens-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
}
Example response for 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

GEThttps://www.telehealthintakeforms.com/api/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
}
Example response for 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

GEThttps://www.telehealthintakeforms.com/api/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
}
Example response for 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

GEThttps://www.telehealthintakeforms.com/api/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
}
Example response for 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 of primary-care, urgent-care, mental-health, dermatology, veterinary-care. Filters the embedded catalog.
  • m: term in months: 1, 3, 6, or 12. 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.

StatusCodeDescription
401missing_bearerRequest did not include `Authorization: Bearer <token>`.
401invalid_tokenToken is malformed, revoked, expired, or not user-scoped.
401unknown_userThe token verifies, but no portal user matches its subject.
403forbiddenThe account is inactive or the endpoint is disabled for this account (for example DNA links).
404not_foundThe referenced record does not exist or does not belong to this account.
400invalid_requestA query/body parameter failed validation.
429rate_limitedPer-token rate limit exceeded for this endpoint.
500internal_errorUnexpected server error. Safe to retry with backoff.
503api_keys_unavailableReserved for environments where API token verification cannot run.