GLP-1 Coverage Criteria API
One request resolves a payer × drug × indication to its structured prior-authorization criteria: step therapy, BMI and A1C thresholds, qualification pathways, required documentation, quantity limits, approval durations, and provenance. You get one coverage entry per plan type, or just the plan type you ask for.
Every record is human-reviewed against the source policy document, dated, and re-verified on a
rolling cycle. Criteria detail is only returned for reviewed records
(provenance.source_type: reviewed_policy),
and the API never converts policy silence into a coverage answer. Gaps come back as an explicit
no_data verdict.
Two endpoints
POST /coverage — the criteria lookup. POST /resolve — map a card's plan name to the right payer first.
Payer resolution built in
Send the payer name as printed on the card; the API resolves it and reports match_type and confidence.
Seven explicit verdicts
Including no_data and off_label — honest gaps, never silent denials.
No PHI, structurally
Selectors travel in the JSON body, never the URL; unexpected fields are rejected, not ignored.
Base URL
https://api.myglp1coverage.com/api/v1All requests are HTTPS POSTs with a JSON body. Responses are JSON, UTF-8 encoded.
Authentication
Every request requires an API key, sent as a bearer token
(Authorization: Bearer <key>)
or in the X-Api-Key header.
Keys are issued per organization —
request access to get one.
curl https://api.myglp1coverage.com/api/v1/coverage \
-H "Authorization: Bearer $GLP1_COVERAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ ... }'
Requests without a valid key receive 401. Usage is metered per request;
exceeding your daily limit returns 429.
Keep keys server-side; never embed them in client-side code.
No PHI, by design
The API accepts plan selectors only — never patient or clinical data — and the transport is built so that holds even by accident:
-
01
Selectors travel in the JSON request body, never the URL. Any query-string
parameter is rejected with
400— edge infrastructure logs raw URLs before application-level filtering can run, so the API refuses to let anything ride in one. -
02
The request body is deny-by-default: any field outside the
documented selector allowlist is rejected with
400, not silently ignored. A straymember_dobnever makes it past the front door.
Payer resolution
You don't need to learn our payer keys. Send the payer name as it appears on the member's card —
the API resolves it and reports match_type
and confidence so your integration
decides when to trust the match. Resolution handles the cases that actually break card-to-criteria mapping:
- Product-name aliases that pin a line of business. "Cigna HealthSpring" resolves to Cigna and pins
medicare_advantage, the line its criteria are actually filed under. - Medicaid managed-care fallback. An MCO plan name resolves to the state Medicaid program whose criteria govern it, flagged with
mco_fallback. - Fail-loud, never fuzzy. Matching is exact (canonical names + curated aliases). A name that can't be matched to a specific payer returns
no_match. For a PA gate, a wrong criteria set is worse than no answer.
Use POST /resolve to map a card
name before a lookup, or just pass the name straight to
/coverage — both resolve the same way.
Responses include stable payer_id /
drug_id values you can send on
later requests to skip resolution entirely.
curl https://api.myglp1coverage.com/api/v1/resolve \
-H "Authorization: Bearer $GLP1_COVERAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Cigna HealthSpring"}'{
"query": { "name": "Cigna HealthSpring" },
"match": {
"payer_id": 12,
"name": "Cigna",
"payer_type": "national",
"match_type": "exact_alias_pinned",
"confidence": 0.98,
"resolved_plan_type": "medicare_advantage",
"mco_fallback": false
}
}Coverage lookup
/coverage
Resolves the payer and drug, then returns one coverage entry per plan type the payer has criteria
for — or only the requested plan_type.
When a payer maintains more than one formulary and they disagree, the entry answers for the payer's
default formulary and sets formulary_varies: true.
If the payer resolved via an alias that pins a line of business, a contradictory
plan_type fails loud with
409 rather than silently
answering for the wrong line. Medicare Part D and Medicare Advantage share PA criteria and are
treated as one line.
Request body
JSON body fields for POST /coverage. Identify the payer by payer or payer_id, and the drug by drug or drug_id.
| Field | Type | Description |
|---|---|---|
payer
required*
|
string | Payer name or alias as printed on the card, e.g. "Kaiser Permanente Colorado", "Cigna HealthSpring". (*or payer_id) |
payer_id
optional
|
integer | Stable payer id from a previous response or /resolve — skips name resolution. |
drug
required*
|
string | Drug brand or generic name, e.g. "Wegovy", "Ozempic". (*or drug_id) |
drug_id
optional
|
integer | Stable drug id from a previous response — skips name resolution. |
indication
required
|
string | One of: diabetes, weight_loss, cv_risk_reduction, mash, osa, ckd. |
plan_type
optional
|
string | One of: commercial, medicare_part_d, medicare_advantage, marketplace, medicaid, essential_plan, fep. Omit to receive one coverage entry per plan type. |
formulary_id
optional
|
integer | For payers that maintain more than one formulary. Defaults to the payer's default formulary when coverage varies. |
Any other body field — and any query-string parameter — is rejected with
400. The fields bin,
pcn, rx_group, and
formulary are accepted without error but are reserved —
they do not influence resolution today.
Example request
Wegovy for weight loss under Kaiser Permanente Colorado's commercial plans:
curl https://api.myglp1coverage.com/api/v1/coverage \
-H "Authorization: Bearer $GLP1_COVERAGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"payer": "Kaiser Permanente Colorado",
"drug": "Wegovy",
"indication": "weight_loss",
"plan_type": "commercial"
}'Example responses
Three verbatim production responses. Together they show the resolution block, the per-plan-type
coverage array, and the three
most common verdict shapes: coverage conditional on benefit design, a preferred agent with standard
requirements, and Medicaid criteria with condition-specific requirements.
Wegovy · weight loss · Kaiser Permanente Colorado (Commercial)
Covered, but conditional on the member's benefit including weight-loss medications (coverage_scope: rider_required).
{
"query": {
"payer": "Kaiser Permanente Colorado",
"drug": "Wegovy",
"indication": "weight_loss",
"plan_type": "commercial"
},
"resolved": {
"payer": {
"payer_id": 44,
"name": "Kaiser Permanente Colorado",
"payer_type": "regional",
"match_type": "exact_name",
"confidence": 1.0,
"mco_fallback": false
},
"drug": {
"id": 2,
"brand_name": "Wegovy",
"generic_name": "semaglutide"
}
},
"coverage": [
{
"plan_type": "commercial",
"formulary": "HMO (all plans)",
"formulary_varies": false,
"coverage_state": "conditional_on_benefit",
"is_covered": true,
"is_preferred": false,
"coverage_scope": "rider_required",
"coverage_scope_note": "Patient must have benefit plan with coverage for weight loss medications",
"basis": null,
"requirements": {
"age": {
"min": 12,
"max": null
},
"bmi": {
"min": 30.0,
"min_with_comorbidity": 27.0,
"min_asian": null,
"percentile_min": null
},
"a1c": {
"min": null,
"max": null,
"for_combination_therapy": null
},
"step_therapy": {
"requires_metformin_trial": false,
"metformin_trial_duration_days": null,
"metformin_exception_conditions": [],
"requires_prior_glp1_trial": true,
"prior_glp1_drugs": [
"generic liraglutide (Victoza)"
],
"prior_glp1_count_required": 1,
"prior_weight_loss_drugs": [
"phentermine",
"diethylpropion",
"Qsymia",
"Contrave"
],
"prior_weight_loss_trial_months": 3
},
"cardiovascular": {
"requires_cv_disease": false,
"cv_qualifying_events": [],
"requires_gdmt": false,
"gdmt_medications": []
},
"osa": {
"requires_osa_diagnosis": false,
"ahi_min": null,
"requires_pap_trial": false
},
"mash": {
"requires_mash_diagnosis": false,
"fibrosis_stage_min": null,
"fibrosis_stage_max": null,
"confirmation_methods": []
},
"renal": {
"egfr_min": null,
"egfr_max": null,
"uacr_min": null
},
"lifestyle": {
"requires_program": false,
"duration_months": null
},
"diagnosis": {
"requires_diagnosis_code": false,
"codes": [],
"confirmation_methods": [
"clinical_diagnosis"
],
"requires_lab_verification": false,
"excludes_diabetes": false
},
"comorbidities_accepted": [
"HTN",
"dyslipidemia",
"T2DM"
],
"exclusions": {
"other": [
"Concurrent use with another GLP-1 or GLP/GIP (e.g., tirzepatide) product",
"Concurrent use of DPP-4 inhibitor (alogliptin, linagliptin, saxagliptin, sitagliptin)",
"Step therapy failure exceptions do not apply for convenience or needle phobia",
"Wegovy (semaglutide) tablets excluded per P&T",
"Patient must have benefit plan with coverage for weight loss medications"
],
"pregnancy": false,
"type_1_diabetes": false,
"bariatric_surgery": false
}
},
"qualification_pathways": [
{
"all_of": [
"Patient is 12 years of age or older",
"Patient has benefit plan with coverage for weight loss medications",
"Not currently using a DPP-4 inhibitor (alogliptin, linagliptin, saxagliptin, or sitagliptin)",
"Patient will NOT use Wegovy with another GLP-1 or GLP/GIP (e.g., tirzepatide) product",
"Current weight on file within the past 4 weeks (objectively measured in-office)",
"BMI >= 30 kg/m2 OR (BMI >= 27 kg/m2 AND at least one weight-related comorbidity: hypertension, dyslipidemia, or type 2 diabetes)",
"Provider attests patient is on a reduced calorie diet and has increased physical activity",
"Documented intolerance, contraindication, or failure to lose and maintain at least 5% body weight after trial of all required step therapy agents, OR provider submits justification per criteria"
],
"any_of": [
"Step therapy completed in order: (a) phentermine 37.5 mg/day OR diethylpropion 75 mg/day for >= 3 months, then (b) Qsymia (phentermine 15 mg/topiramate 92 mg/day) for >= 3 months, then (c) Contrave (naltrexone 32 mg/bupropion 360 mg/day) for >= 3 months, then (d) generic liraglutide (Victoza) 3 mg/day for >= 3 months",
"Provider justification: required drug(s) contraindicated or will likely cause adverse reaction/harm",
"Provider justification: required drug(s) ineffective based on known clinical characteristics",
"Provider justification: patient tried and failed required drug(s) or same-class agent, discontinued due to lack of efficacy, diminished effect, or adverse event",
"Patient is stable on requested drug after completing step therapy or receiving a step therapy exception"
],
"pathway_name": "Initial approval for weight loss (age 12+)"
}
],
"required_documentation": [
"Current (within past 4 weeks) BMI (kg/m2) — objectively measured in-office weight check",
"Documentation of weight-related comorbidities if BMI is 27-<30 kg/m2 (hypertension, dyslipidemia, or type 2 diabetes)",
"Documentation of failed trials of step therapy agents (medication, strength, dates of treatment, reason for discontinuation) OR provider justification why alternatives are not suitable with supporting clinical documentation",
"Provider attestation that patient is on a reduced calorie diet and has increased physical activity",
"Confirmation that patient is not currently on a DPP-4 inhibitor",
"Confirmation that patient will not use Wegovy concurrently with another GLP-1 or GLP/GIP product"
],
"quantity_limits": [
{
"strengths": [
"all strengths"
],
"supply_28_day": "1 box / 4 pens / 3 mL (max daily dose 0.11 mL); renewal: 1 box / 1 pen / 3 mL per 28 days",
"supply_84_day": null
}
],
"approval": {
"initial_months": 6,
"continuation_months": 12,
"continuation_clinical_benefit": "Patient must have achieved and maintained at least 5% weight loss from baseline (objectively measured with in-office weight checks). BMI check within past 4 weeks required. Initial step therapy requirements (phentermine, Qsymia, Contrave, generic liraglutide trials) are NOT re-verified at renewal.",
"continuation_weight_loss_percent": 5.0,
"minimum_maintenance_dose_mg": null,
"minimum_therapy_weeks": null
},
"provenance": {
"source_type": "reviewed_policy",
"documented": true,
"effective_date": "2026-02-01",
"expiration_date": null,
"last_verified_at": "2026-06-05T14:01:33.189Z"
}
}
]
}Coverage states
coverage_state is the verdict —
the first thing to key integration logic off. The four stored states carry the full criteria payload;
the three derived states are verdict-only entries.
| State | Payload | Meaning |
|---|---|---|
covered |
full | Covered with no documented clinical gating. |
covered_with_requirements |
full | Covered once the documented criteria are met — thresholds, step therapy, pathways. |
conditional_on_benefit |
full | Covered only if the member's pharmacy-benefit design includes it (see coverage_scope / coverage_scope_note) — often an optional employer benefit. |
not_covered |
full | Excluded under this plan type and indication. |
covered_under_diabetes_criteria |
verdict only | Derived: an on-label, diabetes-restricted use is covered via the plan's diabetes criteria. Policy silence on the specific indication is never treated as a denial. |
off_label |
verdict only | The drug is not FDA-labeled for this indication; no policy basis exists. |
no_data |
verdict only | We haven't captured this combination yet — an honest gap, not a denial. |
Field reference
Every field in the POST /coverage response.
Paths under Coverage entries and below are relative to each element of the
coverage[] array.
A null threshold means the
policy sets no such requirement.
Response envelope
| Field | Type | Description |
|---|---|---|
query |
object | Echo of the selectors you sent (omitted keys are absent). |
resolved.payer.payer_id |
integer | Stable payer id — reusable as payer_id in later requests. |
resolved.payer.name |
string | Canonical payer name your input resolved to. |
resolved.payer.payer_type |
string | Payer category (e.g. national, regional, bcbs_independent). |
resolved.payer.match_type |
string | How the match was made: exact_name, exact_alias, exact_alias_pinned (alias that also pins a line of business), or id. |
resolved.payer.confidence |
number | Match confidence, 0.0–1.0 (1.0 exact name, 0.98 curated alias). |
resolved.payer.resolved_plan_type |
string | Present only when the matched alias pins a line of business — the line the criteria are filed under. |
resolved.payer.mco_fallback |
boolean | True when a Medicaid managed-care plan name resolved to the state Medicaid program that governs it. |
resolved.payer.resolves_to_state_medicaid |
string | Present only when mco_fallback is true — the state Medicaid payer the plan resolved to. |
resolved.drug.id |
integer | Stable drug id — reusable as drug_id in later requests. |
resolved.drug.brand_name |
string | Brand name (e.g. Wegovy). |
resolved.drug.generic_name |
string | Generic name (e.g. semaglutide). |
coverage |
object[] | One entry per plan type (or only the requested one). All paths below are relative to one entry. |
Coverage entries (coverage[])
| Field | Type | Description |
|---|---|---|
plan_type |
string | Plan type this entry answers for. |
formulary |
string | null | Formulary the answer is based on (the payer's default when coverage varies). |
formulary_varies |
boolean | True when the payer's formularies disagree for this combination — verify the member's specific formulary. |
coverage_state |
string | The verdict — one of the seven states above. |
is_covered |
boolean | Authoritative coverage flag for this drug × indication × plan type. |
is_preferred |
boolean | null | Whether the drug is a preferred agent on this formulary; null when the policy doesn't state a tier. |
coverage_scope |
string | standard, rider_required, or rider_excluded — whether coverage depends on the member's pharmacy-benefit design. |
coverage_scope_note |
string | null | Policy-sourced explanation of the benefit-design condition, when one applies. |
basis |
string | null | Stated policy basis for the determination, when the source provides one. |
Requirements — demographics & labs
| Field | Type | Description |
|---|---|---|
requirements.age.min |
integer | null | Minimum patient age in years. |
requirements.age.max |
integer | null | Maximum patient age in years. |
requirements.bmi.min |
number | null | Minimum BMI (kg/m²) without a qualifying comorbidity. |
requirements.bmi.min_with_comorbidity |
number | null | Lower BMI threshold (kg/m²) that applies with at least one accepted comorbidity. |
requirements.bmi.min_asian |
number | null | Alternate minimum BMI (kg/m²) for patients of Asian descent, when defined. |
requirements.bmi.percentile_min |
integer | null | Minimum BMI percentile for pediatric patients, when defined. |
requirements.a1c.min |
number | null | Minimum hemoglobin A1C in percent (e.g. 6.5 confirms a T2DM diagnosis). |
requirements.a1c.max |
number | null | Maximum hemoglobin A1C in percent, when the policy caps eligibility. |
requirements.a1c.for_combination_therapy |
number | null | A1C threshold that applies specifically when the drug is added to existing therapy. |
Requirements — step therapy
| Field | Type | Description |
|---|---|---|
requirements.step_therapy.requires_metformin_trial |
boolean | Whether a prior metformin trial is required before approval. |
requirements.step_therapy.metformin_trial_duration_days |
integer | null | Required length of the metformin trial in days. |
requirements.step_therapy.metformin_exception_conditions |
string[] | Conditions that waive the metformin requirement (e.g. intolerance, contraindication, ASCVD, CKD). |
requirements.step_therapy.requires_prior_glp1_trial |
boolean | Whether a trial of another GLP-1 agent is required first. |
requirements.step_therapy.prior_glp1_drugs |
string[] | GLP-1 agents that satisfy the prior-trial requirement. |
requirements.step_therapy.prior_glp1_count_required |
integer | null | Number of distinct prior GLP-1 trials required. |
requirements.step_therapy.prior_weight_loss_drugs |
string[] | Non-GLP-1 weight-loss agents that must be tried first (e.g. phentermine, Qsymia, Contrave). |
requirements.step_therapy.prior_weight_loss_trial_months |
integer | null | Required duration of each prior weight-loss-agent trial in months. |
Requirements — condition-specific
| Field | Type | Description |
|---|---|---|
requirements.cardiovascular.requires_cv_disease |
boolean | Whether established cardiovascular disease is required to qualify. |
requirements.cardiovascular.cv_qualifying_events |
string[] | CV events or diagnoses the payer accepts as qualifying (e.g. MI, stroke, PAD). |
requirements.cardiovascular.requires_gdmt |
boolean | Whether concurrent guideline-directed medical therapy is required. |
requirements.cardiovascular.gdmt_medications |
string[] | GDMT therapies the patient must be taking concurrently. |
requirements.osa.requires_osa_diagnosis |
boolean | Whether an obstructive sleep apnea diagnosis is required. |
requirements.osa.ahi_min |
integer | null | Minimum apnea-hypopnea index (events/hour) to qualify. |
requirements.osa.requires_pap_trial |
boolean | Whether a positive-airway-pressure (CPAP/BiPAP) trial is required first. |
requirements.mash.requires_mash_diagnosis |
boolean | Whether a MASH diagnosis is required. |
requirements.mash.fibrosis_stage_min |
string | null | Minimum liver fibrosis stage (e.g. F2) to qualify. |
requirements.mash.fibrosis_stage_max |
string | null | Maximum liver fibrosis stage (e.g. F3) covered for MASH. |
requirements.mash.confirmation_methods |
string[] | Accepted methods of confirming the MASH diagnosis (e.g. biopsy, imaging). |
requirements.renal.egfr_min |
integer | null | Minimum estimated glomerular filtration rate (mL/min/1.73m²). |
requirements.renal.egfr_max |
integer | null | Maximum eGFR (mL/min/1.73m²), used to define CKD eligibility windows. |
requirements.renal.uacr_min |
integer | null | Minimum urine albumin-to-creatinine ratio (mg/g). |
requirements.lifestyle.requires_program |
boolean | Whether a documented diet-and-exercise / lifestyle program is required. |
requirements.lifestyle.duration_months |
integer | null | Required length of the lifestyle program in months. |
Requirements — diagnosis & exclusions
| Field | Type | Description |
|---|---|---|
requirements.diagnosis.requires_diagnosis_code |
boolean | Whether a specific diagnosis code must accompany the submission. |
requirements.diagnosis.codes |
string[] | Accepted diagnosis codes (ICD-10), when the policy enumerates them. |
requirements.diagnosis.confirmation_methods |
string[] | How the diagnosis must be confirmed (e.g. clinical_diagnosis, lab_confirmation). |
requirements.diagnosis.requires_lab_verification |
boolean | Whether lab results documenting eligibility must be submitted. |
requirements.diagnosis.excludes_diabetes |
boolean | Whether a diabetes diagnosis disqualifies the patient under this indication (e.g. MACE-only criteria). |
requirements.comorbidities_accepted |
string[] | Weight-related comorbidities the payer accepts alongside the lower BMI threshold (e.g. HTN, dyslipidemia, T2DM). |
requirements.exclusions.other |
string[] | Policy-specific exclusions, verbatim from the source document. |
requirements.exclusions.pregnancy |
boolean | Whether pregnancy is a stated exclusion. |
requirements.exclusions.type_1_diabetes |
boolean | Whether type 1 diabetes is a stated exclusion. |
requirements.exclusions.bariatric_surgery |
boolean | Whether prior or planned bariatric surgery is a stated exclusion. |
Pathways, documentation & quantity limits
| Field | Type | Description |
|---|---|---|
qualification_pathways |
object[] | Distinct routes to approval. A patient qualifies via any single pathway by meeting all of its all_of conditions plus at least one any_of condition. |
qualification_pathways[].pathway_name |
string | Short label for the pathway (e.g. "Continuation of therapy"). |
qualification_pathways[].all_of |
string[] | Conditions that must ALL be met under this pathway. |
qualification_pathways[].any_of |
string[] | Conditions of which AT LEAST ONE must be met. Empty when the pathway has no alternative branch. |
required_documentation |
string[] | Documentation the payer requires with the prior-authorization submission. |
quantity_limits |
object[] | Dispensing limits per strength grouping. Empty when the policy sets none. |
quantity_limits[].strengths |
string[] | Drug strengths the limit applies to ("all strengths" when uniform). |
quantity_limits[].supply_28_day |
string | null | Maximum quantity per 28-day supply, verbatim from the policy. |
quantity_limits[].supply_84_day |
string | null | Maximum quantity per 84-day (90-day-class) supply, when defined. |
Approval durations
| Field | Type | Description |
|---|---|---|
approval.initial_months |
integer | null | Length of the initial authorization in months. |
approval.continuation_months |
integer | null | Length of each renewal authorization in months. |
approval.continuation_clinical_benefit |
string | null | What the payer requires as demonstrated clinical benefit at renewal, verbatim from the policy. |
approval.continuation_weight_loss_percent |
number | null | Minimum percent weight loss from baseline that must be maintained for renewal. |
approval.minimum_maintenance_dose_mg |
number | null | Minimum maintenance dose in mg the patient must be on (e.g. 2.4 for Wegovy MACE criteria). |
approval.minimum_therapy_weeks |
integer | null | Minimum weeks on therapy before a continuation request is considered. |
Provenance
| Field | Type | Description |
|---|---|---|
provenance.source_type |
string | How the record was produced. Criteria detail is only returned for reviewed_policy — records a human reviewer confirmed against the source policy. |
provenance.documented |
boolean | Whether a source policy document or URL is on file for this record. |
provenance.effective_date |
string | null | Date the source policy took effect (YYYY-MM-DD). |
provenance.expiration_date |
string | null | Stated expiration or review date of the source policy, when published. |
provenance.last_verified_at |
string | null | Timestamp of the most recent human verification against the source policy (ISO 8601, UTC). |
Null-valued fields in resolved.payer
(resolved_plan_type, resolves_to_state_medicaid)
are omitted from the JSON rather than sent as null.
Errors
Errors return a JSON body with a single human-readable error message.
| Status | Meaning |
|---|---|
| 200 | Success — including explicit no_data / no_match results. |
| 400 | Invalid request: unknown indication or plan_type, an unexpected body field (deny-by-default), or any query-string parameter. |
| 401 | Missing or invalid API key. |
| 404 | The payer or drug could not be resolved. |
| 409 | Requested plan_type contradicts the line of business pinned by the resolved payer alias. |
| 429 | Daily request limit reached for this API key. |
OpenAPI specification
The complete schema — both endpoints, every field, type, enum, and the three verbatim example responses — is published as an OpenAPI 3.0 document. Use it to generate clients or import into your tooling.
Get an API key
Access is provisioned per organization. Tell us what you're building and we'll follow up with credentials and a walkthrough of the data.
Request API access