Introduction
# .-------.... ....-------|
# /ssssssyyso++:. .:++osyyssssss:
# /ssssssyyyyo+++: `/+++syyyyssssss:
# /ssssssyyyyy++++: +++++yyyyyssssss:
# +++++oooooo++++++////////+++++ooooooo++++/
# +++++++++++++++++++++++++++++++++++++++++/
# +++++++++++++++++++++++++++++++++++++++++/
# +++++sydhhddhs++++++++++++++shdhhdhyo++++/
# +++odh/``.``:ydo++++++++++yms-`..`.+dh+++/
# ++oms :hmm/-: omo++++++++ym: odmm.:.`hd++/
# ++yN.`dmmmmmm`.mmddddddddmd -mmmmmms +mo+/
# ++omo /dmmmm+ +mo++++++++ym-`smmmmh.`hd++/
# +++smy-`-:-`-smo+++++++++/yd+.`::.`:hdo++/
# +++++shdhyhhhs///+++++++///+yhhyyhdyo++++/
# +++++///////:/:://++++++//::/:////:/+++++/
# +++++/:::::::::::/++++o+///::::::::/+++++/
# +++++/::::::::::://++os//::/:::::::/+++++/
# hmhs+//////////////+/++/:--:////////+oydm+
# hmmmmh+/////////////////:--:///////odmmmm/
# hmmmmmmh+::::://///:////::::::::/odmmmmmm/
# ymmmmmmmmy////::/:::://:://////+hmmmmmmmm/
# ymmmmmmmmmdo+++///++/:/:/+++++ommmmmmmmmm/
# smmmmmmmmmmmo+++++++++//+++++smmmmmmmmmmm+
# smmmmmmmmmmmmo++++++++++++++smmmmmmmmmmmm/
# +mmmmmmmmmmmmdoo++++++++++oommmmmmmmmmmmm:
# .mmmmmmmmmmmmmyoooooooooooohmmmmmmmmmmmmd
# :mmmmmmmmmmmmmooooooooooosmmmmmmmmmmmmm-
# /mmmmmmmmmmmmyoooooooooohmmmmmmmmmmmd.
# .hmmmmmmmmmmy+osssssso+dmmmmmmmmmms`
# /dmmmmmmmmh+++osso+++dmmmmmmmmh:
# `/dmmmmmmh++++++++++mmmmmmmy:
# :hmmmms-/++++++/:mmmmmy-
# :hmms -/++/. dmmy-
# :ho -. dy-
# `
Welcome!
Picwell's Medicare API primarily generates recommendations for packages of eligible Medicare plans based on a user's demographics, drug usage, and other information. All the packages considered offer coverage for both health and drug:
- Traditional Medicare + Medicare Part D plans (
tm+pdp
) - Traditional Medicare + Medigap plans + Medicare Part D plans (
tm+gap+pdp
) - Medicare Advantage plans + Medicare Part D plans (
ma+pdp
) - Medicare Advantage Prescription Drug plans (
mapd
)
The API also supports recommendations for specific Medicare plan types, as described here.
Changelog
API
- 04/12/16 - Allow clients to compare
gap
&ma
plans in a single recommendation request - 03/24/16 - Allow clients to provide one, both, or none of the
retail
andmail
keys per plan when providing their own drug costs - 02/16/16 - Updated Filter endpoint to allow filtering by package type(s) (
tm+pdp
,tm+gap+pdp
,ma+pdp
,mapd
) - 02/16/16 - Updated Filter endpoint to allow Picwell plan identifiers in requests using the
plans
Filter Expression - 01/19/16 - Updated Get Survey endpoint to return a list, rather than an object, of possible answers
- 01/19/16 - Get Survey endpoint now includes two additional questions for estimating an enrollee's level of risk aversion
- 12/01/15 - Errors for user creation/updation requests now flag user NDCs that have since been remapped to different RXCUIs
- 12/01/15 - Added
user_multiplier
andfill_costs
to Drug Cost Breakdown objects - 09/15/15 - Standardized use of
errors
in response keys across all endpoints (previously, some endpoints usederror
) - 09/01/15 - Survey answers for "utilization" questions are now optional through "not_applicable" response
- 08/10/15 - Standardized use of "lte" and "gte" in survey answer options
- 08/10/15 - Upon user creation, user NDCs not recognized in Picwell's drug database are now flagged as errors
- 07/27/15 - Added endpoint for retrieving User objects
- 07/15/15 - Added endpoint for retrieving a list of Survey Question objects
Documentation
- 04/12/16 - Allow clients to compare
gap
&ma
plans in a single recommendation request - 03/30/16 - Changed "optional" to "optional key" to clarify that the key should not be provided from either the client or Picwell if not relevant. Information concerning client provided drug costs are more explicitely stated.
- 03/24/16 - Added a new "Client Provided Drug Costs" section for clients to easily see all relevant information when they want to provide their own drug costs. This information is scattered throughout the doc otherwise.
- 03/03/16 - Updated documentation to reflect coming API changed for Medicare version 3
- 02/16/16 - Updated Filtering & added Filter Expression documentation to reflect results filtering based on package type(s)
- 01/19/16 - Updated Get Survey Questions documentation to reflect use of a list of answers in responses
- 12/12/15 - Updated Drug Cost Breakdown documentation to include
user_multiplier
andfill_costs
fields - 12/12/15 - Updated Creating & Updating documentation (Users) to include
unkown_ndcs
andremapped_ndcs
error key values - 08/25/15 - Updated Get Survey Questions documentation to reflect optionality of "utilization" survey questions
- 08/10/15 - Updated Get Survey Questions documentation to reflect use of "lte" and "gte" in survey answers
- 08/05/15 - Corrected Get Survey Questions documentation for misprints in survey answers
- 08/04/15 - Added Plan Reference documentation under Object References
- 07/31/15 - Added Getting documentation under Users
- 07/15/15 - Added Survey Question documentation under Object References
Environments
Picwell operates two distinct and isolated environments on behalf of its clients.
UAT
Our User Acceptance Testing environment is a shared testing environment between Picwell and a client. New features and functionality are regularly released into UAT for preview by our clients. Pending their validation, they are released into Production.
Production
Our Production environment is our live environment, geared for serving live traffic from our clients. New features and functionality are only deployed here after clearing UAT preview.
Change Management
Changes to Picwell's APIs are first previewed in our UAT environment. Changes to UAT can occur as frequently as every 2 weeks, synchronized with our agile development process. Pending client validation, new features are eligible to pushed into production.
Security
Picwell is committed to securely managing data collected through our clients. Our broad security posture includes:
- Reduction of user data surface area
- Reducing the amount of personal information collected from customers
- Formulating our algorithms are designed to operate on machine generated, unique identifiers (e.g. GUIDs)
- Encryption of data inflight
- Picwell services operate over HTTPS (Strict HTTPS)
- Firewalled access to Picwell data infrastructure
- Extensive use of IP-based ingress+outgress firewalls, NATs, ACLs
- Per-client access credentials
To this end, Picwell will require from its clients:
- List of IP addresses to be white-listed for access to UAT and Production environments.
Formats
Encoding
All POST and PUT requests made to the Medicare API must specify a Content-Type
header of application/json
.
All API responses will contain a Content-Type
of application/json
by default.
Authentication
The Medicare service uses authentication tokens to allow access to the API. Once acquired, the authentication token must be included in the header of all requests to the server.
Once a session token is created, it is valid for one day. This token should be used for every subsequent request until the token expires.
Reusing session tokens across requests allows for optimal performance while using Picwell's API.
Get Authorized
Request Body
{
"username":"your-username",
"password":"your-password"
}
Response Body
{
"auth_token":"your-picwell-auth-token"
}
This endpoint will retrieve an authentication token to be used in subsequent requests.
Endpoint
POST http://{{medicare-api-host}}/auth/
Stay Authorized
Since we need to authorize every request you make, we expect the authentication token to be included in the headers of every subsequent request. The header should look like this:
Picwell-Auth-Token: your-picwell-auth-token
Surveys
Get Survey Questions
# The survey questions are returned as a list with a consistent structure.
# They may change at any time, so staging this data is unwise and incorrect.
[
...
{
"question": "How many times were you admitted to a hospital in the last 12 months?",
"type": "utilization",
"id": "5",
"answers": [
{
"answer": "not_applicable",
"display": false,
"label": "This input variable is not available"
},
{
"answer": "0",
"label": "I was not admitted to a hospital last year"
},
{
"answer": "1",
"label": "1 time"
},
{
"answer": "gte_2",
"label": "2 or more times"
}
]
}
...
]
Endpoint
GET /survey/
Response
a List
of Survey Question
objects
Notes
The presentation of survey questions where id == 1 || id == 2 is optional depending on whether the user indicates any preferred healthcare providers (if the client UI requires the input of preferred healthcare providers before survey questions are presented). The optionality is in regards to whether these questions are presented to a given user via client UI, not whether the user can opt to answer them. An appropriate response should still be provided in the Survey Answer object for each question (e.g. "not_applicable" for question 1 and "0" for question 2 should the user have no preferred heathcare providers).
The presentation of survey questions where id == 3 || id == 4 || id == 5 is optional depending on whether the client UI is allowed/approved to present users questions about their historical utilization of medical services. The optionality is in regards to whether these questions are presented to users via client UI, not whether users can opt to answer them. An appropriate response should still be provided in the Survey Answer object for each question (e.g. "not_applicable" for questions 3, 4, and 5 should the client UI not be allowed/approved to ask users about medical services utilization).
Users
A User object provides valuable context required for recommendations.
Creating
This endpoint will create a user object based on information provided in the request body.
Request Body
{
"zip_code_3": "193",
"state_code": "PA",
"age": 66,
"gender": "female",
"prescriptions": [],
"uses_tobacco": true,
"survey": [],
"enrolled_in": []
}
Response Body
{
"id":"user reference id"
"unknown_ndcs" : {
"2015" : ["ndc", ...],
"2016" : ["ndc2", ...]
},
"remapped_ndcs": {
"2015' : ["ndc", ...],
"2016' : ["ndc2", ...]
}
}
Optionally, this may include three 'errors'
sub-keys: unknown_ndcs
, remapped_ndcs
, nonpuf_ndcs
.
If the NDC is not present in Picwell's drug database, it will be be staged in the user object on creation/edit. All subsequent requests, though, will remove that NDC from the object to provide valid responses for known NDCs.
Remapped NDCs are a result of an inconsistency between the RxCUIs within CMS public use files and the NDCs that are current as provided by the NLM RxNorm database. Whenever issues like these occur, the Picwell API will attempt to remap the underlying data appropriately. This error key is provided to be able to identify the occurrence of the underlying remapping.
When an NDC is mapped to an RXCUI, but that RXCUI is not present in the CMS public use files, the nonpuf_ndcs
error key will be provided. It will contain all NDCs meeting that criteria. We denote these NDCs because we are unable to map those NDCs to the underlying coverage or cost data. Those NDCs will be reported as uncovered drugs in our recommendation responses for the user.
Endpoint
POST http://{{medicare-api-host}}/user/
Getting
This endpoint will retrieve details about a user object.
Endpoint
GET http://{{medicare-api-host}}/user/{User.id}/
Response
a user
object
Notes
- Errors: when
{User.id}
is invalid (not found), an HTTP 404 error
Updating
This endpoint will update a user object based on information provided in the request body.
Request Body
{
"zip_code_3": "193",
"state_code": "PA",
"age": 76,
"gender": "female",
"prescriptions": [],
"uses_tobacco": false,
"survey": [],
"enrolled_in": []
}
Response Body
{
"id":"user-id",
"unknown_ndcs" : {
"2015" : ["ndc", ...],
"2016" : ["ndc2", ...]
},
"remapped_ndcs": {
"2015' : ["ndc", ...],
"2016' : ["ndc2", ...]
}
}
Optionally, this may include three 'errors'
sub-keys: unknown_ndcs
, remapped_ndcs
, nonpuf_ndcs
.
If the NDC is not present in Picwell's drug database, it will be be staged in the user object on creation/edit. All subsequent requests, though, will remove that NDC from the object to provide valid responses for known NDCs.
Remapped NDCs are a result of an inconsistency between the RxCUIs within CMS public use files and the NDCs that are current as provided by the NLM RxNorm database. Whenever issues like these occur, the Picwell API will attempt to remap the underlying data appropriately. This error key is provided to be able to identify the occurrence of the underlying remapping.
When an NDC is mapped to an RXCUI, but that RXCUI is not present in the CMS public use files, the nonpuf_ndcs error key will be provided. It will contain all NDCs meeting that criteria. We denote these NDCs because we are unable to map those NDCs to the underlying coverage or cost data. Those NDCs will be reported as uncovered drugs in our recommendation responses for the user.
Endpoint
PUT http://{{medicare-api-host}}/user/{{user-id}}/
Drug Search
Drugs are classified using NDCs and represent information about a specific packaging of a drug.
Resolving Names
You may use this endpoint to retrieve all drugs matching a (partial) name
Response Body
[
{"generic_name": "Clonazepam",
"default_quantity": 30,
"ndc": "00093083201",
"default_period": 30,
"brand_name": "Clonazepam",
"description": "Clonazepam, 100 TABLET in 1 BOTTLE "},
# { drug object 2},
...
]
Endpoint
GET http://{{medicare-api-host}}/drugs/
Query Parameters
key | value |
---|---|
query |
a partial drug name |
Response Fields
keys | type | description |
---|---|---|
ndc |
string | the Medicare 11-digit ndc |
brand_name |
string | the (potentially) branded name of the drug (optional) |
generic_name |
string | the generic drug name |
description |
string | the display name of drug inclusive of dosage and format |
default_quantity |
int | most commonly prescribed quantity of this medication |
default_period |
int | most commonly prescribed refill period of this medication |
Recommendations
For A Single Medicare Product
Endpoint
POST /recommendation/<string: product>/<int: year>/{User.id}/{params}
Post Body
list of Plan Reference
Response
a Result Set
object (with N recommendations)
Notes
Allowed product codes include:
pdp
: Medicare Prescription Drug plansgap
: Medicare Supplement plans (Medigap)mapd
: Medicare Advantage with Drug coverage plansma
: Medicare Advantage plans without Drug coverage
Because of the unique nature of
mapd
(plan and package), we use the following disambiguation rule to guide our responses:mapd
is always treated as a plan when not accompanied by other packages (i.e. in this instance, it would be treated as a plan)
Optionally, analytics-related information may be specified as valid key-value pairs at the end of a recommendation request (
{params}
). When formatted as valid query string parameters, this data can be utilized for downstream analytics by Picwell. See section on Analytics Parameters for important details.
For Multiple Medicare Products
Endpoint
POST /recommendation/<string: comma-separated product codes>/<int: year>/{User.id}/{params}
Post Body
list of Plan Reference
Response
a Result Set
object (with N recommendations)
Notes
Only
ma,gap
is allowed as the product code list for comparing multiple product types. The only valid use case for comparing different Medicare products is when shopping for just medical services coverage.Optionally, analytics-related information may be specified as valid key-value pairs at the end of a recommendation request (
{params}
). When formatted as valid query string parameters, this data can be utilized for downstream analytics by Picwell. See section on Analytics Parameters for important details.
For A Single Medicare Package
Endpoint
POST /recommendation/<string: package code>/<int: year>/{User.id}/{params}
Post Body
list of Plan Reference
Response
a Result Set
object (with N recommendations)
Notes
Allowed package combination codes include:
tm+pdp
: Traditional Medicare and Medicare Prescription Drug planstm+gap+pdp
: Medigap and Medicare Prescription Drug plans (and Traditional Medicare)mapd
: Medicare Advantage Prescription Drug plansma+pdp
: Medicare Advantage and Medicare Prescription Drug plans
Optionally, analytics-related information may be specified as valid key-value pairs at the end of a recommendation request (
{params}
). When formatted as valid query string parameters, this data can be utilized for downstream analytics by Picwell. See section on Analytics Parameters for important details.
For Several Medicare Packages
Endpoint
POST /recommendation/<string: comma-separated package codes>/<int: year>/{User.id}/{params}
Post Body
a list of Plan Reference
Response
a Result Set
object (with N recommendations)
Notes
Request
POST /recommendation/tm+gap+pdp,ma+pdp/2015/user123/
Response Body
# Response will only contain tm+gap+pdp, ma+pdp combinations
# (not mapd, or tm+pdp, due to constraint in request)
{ gap1, gap2, mapd1, mapd2, pdp1, ma1, ma2 }
# If no ma plans are provided, ma+pdp combinations will be missing from the response, which will only contain tm+gap+pdp combinations.
{ gap1, gap2, pdp1 }
Unmatchable plans will be listed in the errors field
If a
Plan Reference
indicated in the Post Body does not match thepackage code
provided in the Endpoint query string, they will not be included in theResult Set
If component plans are missing for a package type, we will make best efforts to construct meaningful packages and report errors.
Because of the unique nature of
mapd
(plan and package), we use the following disambiguation rule to guide our responses:mapd
is always treated as a solo plan when not accompanied by other packages- When provided alongside another package, it is treated as a single plan package, rather than a solo plan.
Optionally, analytics-related information may be specified as valid key-value pairs at the end of a recommendation request (
{params}
). When formatted as valid query string parameters, this data can be utilized for downstream analytics by Picwell. See section on Analytics Parameters for important details.
Proration
# To request prorated cost estimates for Medicare Packages
# of types `mapd,ma+pdp,gap+pdp`, for user `abcde`, for
# the period of Oct 2015 to Dec 2015:
POST /recommendation/mapd,ma+pdp,tm+gap+pdp/2015/abcde/?start_date=2015-10-01
Recommendation responses can include prorated cost estimates (for individuals signing up for coverage less than 1 year). This may be of value to individuals becoming Medicare eligible outside of the October-December annual enrollment period (e.g. someone turning 65 years of age in March). In such a situation, the enrollee might be interested in viewing prorated cost estimates.
Syntax for prorated requests is consistent across recommendation requests:
POST /recommendation/.../.../?start_date={date}
- The
start_date
fields allows us to prorate results for less than 12 months of coverage - The
start_date
value is expected to be a ISO 8601 formatted string indicating the first date of the month for which coverage is assumed to begin
Pagination
ResultSets provided by the Picwell API may include several hundred package combinations. To simplify, access and use, results are provided in a form that allows pagination.
Use the pagination methods to navigate the pages of a Result Set.
{Result Set.pages}
indicates the number of pages generated by a recommendation request.
Endpoint
GET /recommendation/results/{Result Set.id}/page/<page number: int>/
Response
a Result Set
object with the next page for recommendations
The number of results presented per page can be controlled by the num
parameter.
If excluded (as illustrated above), the default value of num
is set to 100.
If num
is set to all
, all the results are returned in a single page.
Endpoint
GET /recommendation/results/{Result Set.id}/page/<page number: int>/?num={n}
Response
a Result Set
object with the next page for recommendations, with the
number of results per page set to n
Filtering
Use the filtering methods to apply filter predicates (expressions) to Result Sets generated by a recommendation request.
Endpoints:
POST /recommendation/results/{Result Set.id}/filter/
GET /recommendation/results/{Result Set.id}/filter/page/<page number: int>/
Post Body
a Filter Expression
object
Response Body
a Result Set
object with paginated filtered recommendations. To be included in the response, a Recommendation must meet every rule in the provided Filter Expression
.
Sorting
Generally, ResultSets provided by the Picwell API are sorted using the picwell_score
that is calculated
using the retail pharmacy costs
. In cases where the user is more interested
in the picwell_score
calculated using the mail pharmacy costs
, we have provided a way to
change the sort order of a recommendation request.
While the original recommendation request will continue to be served and sorted by the
retail pharmacy score, you can now make subsequent requests to the filtering and pagination
endpoints with a sort_by
parameter.
The sort_by
query parameter can be : mail
, retail
.
note: when a score doesn't exist for a package, it will be sorted by a consistent hash of the picwell_id to maintain stability.
Endpoint
GET /recommendation/results/{Result Set.id}/page/<page number: int>/?sort_by=<mail|retail>
POST /recommendation/results/{Result Set.id}/filter/?sort_by=<mail|retail>
GET /recommendation/results/{Result Set.id}/filter/page/<page number: int>/?sort_by=<mail|retail>
Response
a Result Set
object with the next page for recommendations sorted with the
appropriate sort_by
ordering.
Prescription Drug Plan Costs
Endpoint
POST /recommendation/breakdown/{User.id}/
Post Body
a single Plan Reference
Response
list of Drug Cost Breakdown
objects
Notes
- The
Plan Reference
object that is required for the POST body should include eitherpicwell_id
ORexternal_id
to identify the plan. Using both (or neither) will cause an error to be reported back. - In situations where a drug is not covered by a plan, the breakdown fields marked optional will be set to
null
(i.e.tier
,step_therapy
,prior_authorization
,quantity_limit
) - In situations where a drug is not covered by a plan, the
costs
rendered incosts.retail
andcosts.mail
utilize retail pricing and will represent expected costs paid by a user without insurance coverage. - The
covered
field will indicate whether the drug is covered by this plan. Ifcovered
isfalse
, the drug is uncovered, and thecosts.retail
andcosts.mail
field will represent uncovered drug costs.
Analytics Parameters
Recommendation requests can be supplemented with analytics-related information that can aid with downstream analytics provided by Picwell. Data must be specified as valid key-value pairs, formatted as a valid query string. At this time, Picwell supports the following parameters:
source
: Indicates the end-purpose for the recommendation request. Valid values are as follows:callcenter
: A broker seeks recommendations for the purpose of providing call center supportselfservice
: A consumer seeks recommendations via client's self-service websitemarketing
: A client seeks recommendations for inclusion in personalized member outreach / marketing collateral
Personal information prohibited
Picwell does not permit the transmission of user personal information (including Personal Health Information) via Analytics Parameters. As such, any information supplied to Picwell must comply with HIPAA Safe Harbor standards of de-identification of PHI.
Example usage:
Medicare Packages recommendation request from call-center:
POST /recommendation/2017/c2392ff4-f7c0-4137-baf0-fa0448c1be1f/?source=callcenter
Medicare Packages recommendation request from self-service website:
POST /recommendation/2017/c2392ff4-f7c0-4137-baf0-fa0448c1be1f/?source=selfservice
Part D recommendation request from call-center:
POST /recommendation/pdp/2017/c2392ff4-f7c0-4137-baf0-fa0448c1be1f/?source=callcenter
Object Reference
All objects are serialized as JSON.
Costs
keys | type | description |
---|---|---|
real_cost{mean} |
float | The mean of costs incurred by people like the user for this package of plans (optional key) |
real_cost{deciles} |
[float] | The costs incurred by people like the user, sampled at each decile of RealCost(tm), for this package of plans (optional key) |
monthly_premium |
float | dollar value for monthly premium |
part_b{monthly_premium} |
float | dollar value for monthly Part B premium (optional key) |
part_b{monthly_premium_reduction} |
float | dollar value for monthly Part B premium reduction (optional key) |
services{in_network{mean}} |
float | The mean dollar value for services in network (optional key) |
services{in_network{deciles}} |
[float] | The dollar value for services in network, sampled at each decile, for this package of plans (optional key) |
services{out_network{mean}} |
float | The mean dollar value for services out of network (optional key) |
drugs{mail{total}} |
float | cost of drugs covered by plan when using mail when provided by client (optional key) |
drugs{mail{covered}} |
float | cost of drugs covered by plan, at mail order pharmacies (optional key) |
drugs{mail{uncovered}} |
float | cost of drugs not covered by plan, at mail order pharmacies (optional key) |
drugs{retail{total}} |
float | cost of drugs covered by plan at retail pharmacies when provided by client (optional key) |
drugs{retail{covered}} |
float | cost of drugs covered by plan, at retail pharmacies (optional key) |
drugs{retail{uncovered}} |
float | cost of drugs not covered by plan, at retail pharmacies (optional key) |
real_cost
values are computed using Picwell's formula. See Usage FAQs for details.part_b{monthly_premium}
assumes the standard monthly premium amount determined by CMS and is only applicable forma
,mapd
, andgap
plans; for plan types where inapplicable (pdp
), the field will be absentpart_b{monthly_premium_reduction}
is only applicable forma
andmapd
plans; for plan types where inapplicable (gap
andpdp
), the field will be absent- Following the above rules regarding
part_b{monthly_premium}
andpart_b{monthly_premium_reduction}
,part_b
will be absent forpdp
plans services
is also not provided forpdp
plans- When a client provides their own drug costs, the
uncovered
/covered
keys will not exist. If the retail costs for a plan is not specified, then therealcost{mean}
andrealcost{deciles}
will not be provided because these are based on retail costs. total
is not provided when the client is not providing their own drug costs.- When requesting a partial year and the client has provided their own drug costs in their consideration set, all drug cost fields will be empty in the partial year.
Drug
A representation of a specific packaging of a drug
keys | type | description |
---|---|---|
ndc |
string | the Medicare 11-digit ndc |
brand_name |
string | the (potentially) branded name of the drug (optional key) |
generic_name |
string | the generic drug name |
description |
string | the display name of drug inclusive of dosage and format |
default_quantity |
int | most commonly prescribed quantity of this medication |
default_period |
int | most commonly prescribed refill period of this medication |
Drug Cost Breakdown
keys | type | description |
---|---|---|
ndc |
string | the Medicare 11-digit ndc |
period |
int | period of drug refill (as specified in User object) |
quantity |
int | numeric quantity of the drug` |
covered |
boolean | drug covered by plan |
tier |
int | tier of drug on plan formulary (optional key) |
step_therapy |
boolean | formulary requires step therapy for drug (optional key) |
prior_authorization |
boolean | formulary requires prior authorization for drug (optional key) |
quantity_limit |
boolean | formulary enforces quantity limit for drug |
retail_price |
float | retail unit price of the drug for specified refill period and quantity |
user_multiplier |
float | ratio of the user's rate of consumption to the default rate of consumption |
costs{retail} |
float | cost of drug at retail pharmacy |
costs{mail} |
float | cost of drug at mail order pharmacy |
fill_costs{retail}{initial_coverage} |
float | cost of retail pharmacy fill for drug in initial coverage phase |
fill_costs{mail}{initial_coverage} |
float | cost of mail order pharmacy fill for drug in initial coverage phase |
Drug Coverage
keys | type | description |
---|---|---|
covered |
[string] | a list of 11-digit NDCs covered by the plan |
uncovered |
[string] | a list of 11-digit NDCs not covered by the plan |
partial |
[string] | a list of 11-digit NDCs partially covered by the plan |
donut_hole |
boolean | indicator of whether drug expenses move user into coverage gap |
catastrophic |
boolean | indicator of whether drug expenses move user into catastrophic phase |
External Drug Costs
Rather than using drug cost estimates determined by Picwell's Part D calculator, the client can provide their own estimates for inclusion in Picwell's plan/package scoring. This is an optional part of a [Plan Reference] object.
- If the client would like to provide their own drug cost estimates, every MAPD or PDP plan should have the
drug_costs
key. - For each MAPD or PDP plan, the client can provide one, both, or neither of the
retail
andmail
keys. Picwell will consider just the plans/packages that have one or both of these keys for scoring purposes. - If the client provided their own cost estimates,
retail
scores generated are relative to just the plans for whichretail
drug costs are provided, andmail
scores are relative to just the plans for whichmail
drug costs provided. - If the client does not want to provide either
retail
ormail
costs for a particular plan, the value ofdrug_costs
must be an empty dictionary.
keys | type | description |
---|---|---|
retail |
float | The drug costs associated for the drugs the user is seeking coverage for, when they are receiving all their drugs from a retail pharmacy |
mail |
float | The drug costs associated for the drugs the user is seeking coverage for, when they are receiving all their drugs from a mail order pharmacy |
Health Provider Location
A representation of a user's healthcare provider (doctor, nurse practioner, clinic etc) at a specific location. Health Provider Locations combine the concept of healthcare providers and the locations a provider practices at. This is necessary because a given health provider practicing at one location may be covered by a plan, but the same health provider practicing at another may not be covered by the same plan.
Health Provider Locations also encompass the concept of health facilities that a user might express a preference towards (clinics, general hospitals etc).
keys | type | description |
---|---|---|
external_id |
string | unique identifier for health provider location |
type |
string | one of {specialist, pcp, facility} |
specialty |
[string] | the provider's or facility's specialty |
Filter Expression
keys | type | description |
---|---|---|
plans |
[string] | a list of external or Picwell identifiers for plans |
health_provider_locations |
[string] | a list of health provider location identifiers |
package_types |
[string] | a list of package types, can be any of mapd , tm+gap+pdp , ma+pdp , tm+pdp |
Plan
A representation of a specific insurance plan
keys | type | description |
---|---|---|
id |
bigint | an internally used identifier for a plan |
external_id |
string | unique, mutually bound, identifier for the plan |
type |
enum | one of "pdp", "ma", "mapd", "gap" |
carrier |
string | a human readable plan carrier name |
name |
string | a human readable plan name |
detail |
string | additional plan information for medigap plans |
letter |
string | medigap plan letter in Picwell schema (optional key) |
medicare_id |
string | in the form H0000-000-000 |
Plan Reference
A reference to plans that a client would like to consider for a request
keys | type | description |
---|---|---|
type |
string | enum of 'ma', 'pdp', 'mapd', 'gap' |
picwell_id |
string | unique internal identifier for plan and offering year (optional key) |
external_id |
string | unique, mutually bound, identifier for plan and offering year (optional key) |
monthly_premium |
float | the monthly premium for the plan (optional key) |
drug_costs |
[External Drug Costs] | Rather than using our Part D calculator, the client can provide their own calculated value, which we will then use to compute a plan or packages score (optional key) |
health_provider_locations{in_network} |
[Health Provider Location] | list of provider-locations in-network |
health_provider_locations{extended_network} |
[Health Provider Location] | list of provider-locations in-network |
health_provider_locations{out_of_network} |
[Health Provider Location] | list of provider-locations out-of-network |
- Either a
picwell_id
orexternal_id
should be provided. The usage must be consistent across all plan references **external_id
should be used if you've provided us with a mapping file between your plan identifiers and Medicare plans **picwell_id
is used for cases where we have no such mapping - It is assumed that
external_id
is unique at the plan and plan year level - Semantics for
monthly_premium
field: ** Premiums are only required forgap
plans; do not include this field forma
,mapd
orpdp
plans as it will be ignored - If you do not want to provide your own drug costs, do not include the
drug_costs
key in any plan. If thedrug_costs
key is provided for anypdp
ormapd
plan, then the "Client Provided Drug Costs" option is triggered. Refer to that section for more information if you would indeed like to provide your own drug costs. plan_year
is requested for triage purposes and for edge-case handlinghealth_provider_locations
are capped to maximum of 100 provider-location entities- If
health_provider_locations
are not applicable to a plan (e.g.pdp
plans), set the field to an empty dictionary (i.e. {}).
Prescription
A prescription of a given drug
key | type | description |
---|---|---|
ndc |
string | 11 digit ndc |
quantity |
int | numeric quantity of the drug |
period |
int | days between refills |
Recommendation
A recommendation for a package of plans
key | type | description |
---|---|---|
components |
enum | one of "pdp", "ma", "mapd", "gap", "ma+pdp", "tm+pdp", "tm+gap+pdp" |
type |
enum | one of "package", "standalone"; distinguish result type |
plans |
[Plan] | list of plans constituting this package |
score |
[Score] | Picwell Score values for this package |
costs{full} |
Costs | costs of premiums, services, and drugs for the full year |
costs{partial} |
Costs | costs of premiums, services, and drugs for the partial year, if making a partial year request (optional key) |
drug_coverage |
Drug Coverage | breakdown of covered and uncovered drugs, won't be provided in the presence of client-provided drug costs (optional key) |
health_provider_locations |
[Health Provider Location] | the providers in network for the plan |
type
takes on values ofstandalone
orpackage
to disambiguate between results of packages or product typesplans
will contain only a single element in case of product recommendationshealth_provider_locations
will contain the same information provided in {Plan Reference.health_provider_locations}; it is repeated in the response for convenience
Result Set
key | type | description |
---|---|---|
id |
string | identifier for this result set (optional key) |
results |
[Recommendation] | list of package recommendations |
current_page |
int | current page number of result set |
total_results |
int | number of recommendations associated with entire result set |
total_pages |
int | number of pages associated with entire result set |
errors{unmatched} |
[string] | list of external plan IDs that were not matched (optional key) |
errors{parameter} |
string | indication of query string argument error (optional key) |
- By default, a single page in a Result Set will contain 25 Recommendation objects
- Result Sets will be periodically expired to prevent returning stale data back to users; requests against an expired Result Set will result in an HTTP 404 error.
- The
errors
field will be absent if no errors were generated in fulfilling the result set. - The
errors
field may contain one or more of the listed keys if an error was generated - In the case that the result set contains no results, the
id
field will be absent andtotal_results
will be0
Score
The relative Picwell Score for this package amongst all packages in the ResultSet
key | type | description |
---|---|---|
retail{picwell_score} |
float (0-100) | The relative Picwell Score value when comparing this package against other packages when receiving all drugs from a retail pharmacy (optional key) |
retail{tier} |
enum | Picwell color tier, one of "red", "green", "yellow" (optional key) |
retail{dimensions{real_cost}}} |
float (0-100) | The relative Real Cost value when comparing this package against other packages when receiving all drugs from a retail pharmacy (optional key) |
retail{dimensions{risk_protection}} |
float (0-100) | The relative risk protection this package provides when comparing this package against other packages when receiving all drugs from a retail pharmacy (optional key) |
retail{dimensions{health_provider_locations}} |
float (0-100) | Compared to other plans in the result set, how well this plan covers your preferred health providers (optional key) |
retail{dimensions{medicare_star_ratings}} |
float (0-100) | The relative Medicare star rating value when comparing this package against other packages when receiving all drugs from a retail pharmacy (optional key) |
mail{picwell_score} |
float (0-100) | The relative Picwell Score value when comparing this package against other packages when receiving all drugs from a mail order pharmacy (optional key) |
mail{tier} |
enum | Picwell color tier, one of "red", "green", "yellow" (optional key) |
mail{dimensions{real_cost}} |
float (0-100) | The relative Real Cost value when comparing this package against other packages when receiving all drugs from a mail order pharmacy (optional key) |
mail{dimensions{risk_protection}} |
float (0-100) | The relative risk protection this package provides when comparing this package against other packages when receiving all drugs from a mail order pharmacy (optional key) |
mail{dimensions{health_provider_locations}} |
float (0-100) | Compared to other plans in the result set, how well this plan covers your preferred health providers (optional key) |
mail{dimensions{medicare_star_ratings}} |
float (0-100) | The relative Medicare star rating value when comparing this package against other packages when receiving all drugs from a mail order pharmacy (optional key) |
- Score dimensions that are irrelevant in the context of the API call are not returned. For example, if a user does not specify any preferred health providers, then the 'health_provider_locations' dimension will not be returned. Another example is a call that only involves
pdp
plans, where the 'risk_protection' dimension is not returned. The 'risk_protection' dimension is irrelevant in this instance because Picwell's risk protection assessment evaluates a distribution of predicted cost outcomes, while Picwell's drug cost estimates are single point estimates. The following table indicates, for each Medicare plan type, which scoring dimensions are by default returned/relevant.
score dimension | mapd | ma | gap | pdp |
---|---|---|---|---|
real_cost |
yes | yes | yes | yes |
risk_protection |
yes | yes | yes | no |
health_provider_locations |
yes | yes | yes | no |
medicare_star_ratings |
yes | yes | no | yes |
- In the case that the client chooses to provide their own drug costs, a plan/package will have no
retail
scores if theretail
drug_costs are not provided for that plan/package. The same is true formail
scores. If neither of these costs is provided for a plan/package, then the Score object will be an empty dictionary.
Survey Question
A health services or personality survey question
key | type | description |
---|---|---|
id |
string | unique identifier for the survey question |
type |
string | one of {risk, physician, utilization} |
question |
string | UI-friendly prompt for the survey question |
answers |
list | a list of Presented Survey Answer objects |
Note: the list of answers
is ordered as they should appear when visually represented.
Presented Survey Answer
An answer and the presentation for the given answer.
key | type | description |
---|---|---|
answer |
string | the answer key as is used in User edit/create structure |
label |
string | the presentable label for the answer |
display |
bool | optional. If false , then do not show this answer/label to the user. |
*These answers are used either internally or for alternative user flows.
Survey Response Answer
A health services or personality survey response
key | type | description |
---|---|---|
question_id |
string | unique identifier for the survey question |
answer |
enum | selection from {Survey Question.answers} |
User
A representation of a user
keys | type | description |
---|---|---|
zip_code_3 |
string | the user's 3-digit ZIP code |
state_code |
string | the user's two-character U.S. state code |
age |
int | the user's age, in years |
gender |
enum | either "male" or "female" |
prescriptions |
[Prescription] | list of the user's prescriptions |
uses_tobacco |
boolean | does the user use tobacco products? |
survey |
[Survey Answer] | responses to survey questions |
enrolled_in |
[string] | list of identifiers for the plan(s) the user is enrolled in (optional key) |
Semantics for enrolled_in
field:
- If the user has not made a plan election at the time this object is created, set to
null
- When the user eventually makes an election, set
enrolled_in
to appropriate set of{Plan Reference.external_id}
Client Provided Drug Costs
Here is a quick summary of what a client should know if they would like to provide their own calculated values for drug costs rather than use our Part D calculator. The following information is also scattered throughout the API documentation for contextual reference.
How to Invoke Functionality
Functionality is invoked if the drug_costs
key in the Plan Reference object is provided for either pdp
or mapd
plans. drug_costs
is of the type [External Drug Costs]. Read the section about the External Drug Costs object carefully to see how to appropriately format this object for the request you would like to make.
Changes in the Cost Object
The uncovered
/covered
keys will not exist. If the retail costs for a plan is not specified, then the realcost{mean}
and realcost{deciles}
will not be provided because these are based on retail costs.
Changes in the Recommendation Object
The drug_coverage
key will not be provided.
Changes in the Score Object
A plan/package will have no retail
scores if the retail
drug_costs are not provided for that plan/package. The same is true for mail
scores. If neither of these costs is provided for a plan/package, then the Score object will be an empty dictionary.
Errors
While the Picwell API uses standard HTTP status codes, many times body data is also provided to help consumers correct any issues after the fact. Following is a table of error codes used, their context, and some expectation of how to handle them.
Status | Meaning | Handling |
---|---|---|
400 | Bad request | Any request that is missing a required field. Review the response body for further handling. |
401 | Unauthorized | Authentication token has expired. Create a new authentication token and retry the operation. |
404 | Object not found | A request for an object which does not exist. Consider recreating the missing object (user profile, result set, etc), if necessary. |
405 | Method Not Allowed | A request was made with an invalid HTTP action. Check the verb of your request and try again. |
500 | Server Error | Picwell encountered an internal error. While you may retry the request as the error may have been temporary, persisting failures may indicate service downtime. |
503 | Temporary Server Error | Picwell encountered an internal error. Retry the request as the error may have been temporary. |
Error Objects within Responses
Throughout this API we have used a few error
json objects that are within the overarching result of user creation/edit, recommendation, and breakdown requests. In the sidebar is a consolidation of these errror bodies. The explanation for them can be found in the related request sections.
{
"errors": {
// plans that don't match via a client data file
"unmatched" : ["client-plan-id1", "client-plan-id2", ...],
// plans we were not able to model
"unmodelled" : ["id1", "id2", ...],
// ndcs that were unknown within the years that are valid
"unknown_ndcs" : {
"2015" : ["ndc1", "ndc2", ...],
"2016" : ["ndc2", "ndc3", ...]
},
// ndcs for drugs that had their underlying RxCUIs remapped
"remapped_ndcs" : {
"2015" : ["ndc5", "ndc6", ...],
"2016" : ["ndc7", "ndc8", ...]
},
// ndcs for drugs that have no available cost/coverage info from CMS
"nonpuf_ndcs": {
"2015" : ["ndc9", "ndc10", ...],
"2016" : ["ndc11", ...],
}
}
}
Versioning
As the medicare-api
evolves, API versioning is required in order to accommodate the need for stable
APIs while new features are being developed. Clients are able to make requests to a specific version
of the API using HTTP Accept
headers.
Picwell's method of Accept
header versioning is a widely accepted standard for versioning RESTful
APIs. Under v2 APIs, themedicare-api
does not care about what is sent in the HTTP Accept
header of
a request. If you choose to send an Accept
header, there are forms and associated interpretations of
version that are associated as follows:
Accept value |
version requested | description |
---|---|---|
null or empty |
v2 | when not provided, the oldest version is assumed |
*/* |
v2 | when wildcarded, the oldest version is assumed |
application/json |
v2 | when not provided, the oldest version is assumed |
`application/vnd.picwell+json | v2 | when not provided, the oldest version is assumed |
application/vnd.picwell.v2 |
v2 | this explicitly selects v2 |
application/vnd.picwell.v3+json |
v3 | this explicitly selects v3 |
application/vnd.picwell.v9+json |
v2 | this selects v9 , which doesn't exist, so v2 is selected |
It is NOT safe to mix versions of the API within a session (e.g. creating a user under v2 and
subsequently requesting a recommendation under v3). Usage of Accept
headers should be consistent
across all requests within a session, including authentication (e.g. if a v3 recommendation request
will be made, the v3 Accept
header should be provided during authentication).
Frequently Asked Questions
How does Picwell handle drug costs and coverage for plans that don't have drug components?
When responding to a Medigap or Medicare Advantage request, the drugs
and
drug_coverage
fields will both be {}
, to represent the fact that drug coverage
is absent from these plan types.
Example:
..
"drugs": {}
},
"drug_coverage": {}
}
How is the Picwell RealCost(tm) calculated?
The Picwell RealCost(tm) represents our best estimate of the user's expected annual (or prorated) out-of-pocket cost under that plan package.
The costs.real_cost.mean is computed as follows:
costs.real_cost.mean = MONTHS_COVERED * (costs.monthly_premium + costs.part_b.monthly_premium - costs.part_b.monthly_premium_reduction)
+ costs.services.in_network
+ costs.drugs.pharmacy + costs.drugs.uncovered
Our recommendation responses include the constituent elements of RealCost to help clients better explain a plan's cost drivers.
How does Picwell recommend rendering the Picwell Score in Package and Plan settings?
If your implementation uses our Plan Package functionality, the Picwell Scores should only be rendered at a Package level. While it is returned for standalone Plan recommendations, it is done so only for the ability to sort plans in an appropriate order. Picwell Scores cannot be compared "apples-to-apples" between Package and Plan settings, and rendering it as such is a violation of our Branding Guidelines. We do permit the use of our color tiers as a selection aid to end users.
Are there other situations where Picwell Scores may not be directly comparable?
Picwell Scores are not comparable if they originate from recommendation requests with different Plan or Package combinations. This is because Picwell Scores are relative values, sensitive to the package or options being considered.
As an example, Picwell Scores returned for a request seeking PDP & Gap or
MA & PDP packages:
/recommendation/tm+gap+pdp,ma+pdp/2015/user123/
are not comparable to Picwell Scores returned for a request seeking all packages:
/recommendation/2015/user123/
How does Picwell handle recommendations for two plan years?
If a user is simultaneoulsy electing partial year's worth of coverage in the current year along with a full year's coverage for the next year, two API calls to our recommendation endpoints are required. The first is a request for prorated recommendations with a list of Plan References for the current years' eligible plans. The second is a request for full year recommendations with a list of Plan References for the next years' eligible plans.
What happens when a recommendation request contains no plans?
Sending an empty list (i.e. []
) of Plan References in a recommendation
request is an erroneous condition. Picwell will accept the request, but will
return a Result Set with no values.
Omitting any payload in the recommendation request (i.e. sending no POST body), will trigger Picwell's own eligibility logic into action - using the provided geographical and other variables, Picwell makes its own determination of plan eligibility for a user. These determinations include ALL available Medicare plans, and are generally not of interest to our clients. Therefore, omitting a payload in the recommendation request is to be generally avoided.
Migrating from v2 to v3
For a detailed guide to the changes between version 2 and 3 of the Medicare API, please reference https://gist.github.com/picwell-allie/c9f161a4a7c00eda61c5.
Support
Suggested Tooling
It is strongly suggested that a client's developers adopt a simple HTTP transaction tool to facilitate debugging against Picwell's APIs. These tools help isolate client platform-specific issues from possible Picwell API issues. In our experience, any of these tools provide excellent HTTP transaction logging and instrumentation, ideal of debugging:
- Postman for Windows or Mac or Linux,
- cURL for Windows or Mac or Linux
- Fiddler on Windows for Windows
Reporting Issues
If an API request fails in your development environment or platform, please attempt a clean HTTP request (using the tools listed above) to create a clean HTTP trasanction trace. An HTTP transaction trace includes the data points listed below. When reporting Picwell API errors, it is important to provide us with these critical elements of data in order for us to troubleshoot quickly and effectively:
- Environment being used
- HTTP transaction trace (i.e. for every API call to our service, in a transaction)
- Full URL (including query strings)
- Full HTTP Body (for POSTs and PUTs)
- All HTTP request headers
- Full HTTP response
- All HTTP response headers
- Expected results