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
Summary of changes to the API over time.
- 09/12/22 - Added new drug search capability Search for Drug by NDC.
- 06/03/22 - Introduced creating a
User
with anexternal_id
for claims data. - 05/25/22 - Introduced claims endpoints to get and set user data from claims.
- 04/25/22 - Introduced API Key based authentication. Auth token access pattern is now considered deprecated.
- 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 create and update requests now flag user NDCs that have since been remapped to different RxCUIs.
- 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.
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 by:
- Minimizing the amount of PHI collected from customers
- Leveraging machine generated, unique identifiers when possible
- Encryption of all data in-flight and at-rest.
- Firewalled access to Picwell data infrastructure.
Keep your keys safe
Your secret API key can be used to make any API call on behalf of your account, Use the following best practices to keep your keys safe:
- Grant access only to those who need it.
- Ensure the key is kept out of version control systems.
- Ensure the key is not kept in plain text.
- Don't embed your secret API key in mobile applications or other places from where the key could be extracted.
Sanitized User Input
If requested, Picwell will sanitize all user input returned by the API, making it safe to insert into an HTML page without modification. This is not a security feature (API client software is responsible for safely handling data), but is offered as a convenience for our customers.
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
Picwell's API offers two methods of authenticating a request. Each are described below.
API Keys
To begin using Picwell API, contact your Picwell representative for an API key. You will receive
one key per environment; most likely uat
and prod
. These URLs can be found below.
Environment | URL |
---|---|
uat |
https://uat-api.picwell.net/ |
prod |
https://api.picwell.net/ |
For all requests, you will specify the following headers:
Header | Value |
---|---|
Accept |
application/vnd.picwell.v1+json |
X-Api-Key |
Your provided API Key. |
Legacy API Credentials
To begin using Picwell API, contact your Picwell representative for your API credentials. You will receive
one set of credentials per environment; most likely uat
and prod
. These URLs can be found below.
Environment | URL |
---|---|
uat |
https://uat-medicare-api.picwell.net/ |
prod |
https://medicare-api.picwell.net/ |
Request Body
{
"username": "<username>",
"password": "<password>"
}
Response Body
{
"auth_token": "<temporary-auth-token>"
}
Endpoint
POST /auth
Response
An authentication token
For all other requests, you will specify the following headers:
Picwell-Auth-Token: <temporary-auth-token>
You should expect your auth token to last no longer than 24 hours. At any point, you may request a new one.
Reusing your auth token across requests allows for optimal performance.
When using this authentication method, omit the /medicare/
route prefix across all endpoints.
For example, GET /medicare/survey
becomes GET /survey
.
Rate Limits
The Picwell API employs a number of safeguards to help maximize its stability. Users who send many requests in quick
succession may see error responses. Requests rejected due to surpassing the rate limit receive an HTTP 429
response.
Common Causes
- Running a large volume of closely-spaced requests can lead to rate limiting. Often this is a typeahead search interface that makes a request for every user keystroke, or part of a batch operation.
- Issuing many long-lived requests that require excess resources.
Handling Limiting Gracefully
If you are receiving 429
status codes, you are exceeding the configured limit for a given API resource. One strategy
to handle this gracefully is to implement a retry mechanism with exponential backoff so that occasional limited requests can still eventually succeed.
This approach may not be applicable for all scenarios, and for some endpoints it is possible to experience higher latency without being limited. In these cases, you may:
- Ignore stale data to improve user experience ("debouncing"). We recommend this for typeahead search interfaces.
- Decrease the rate at which you make requests ("throttling"). We recommend this for batch operations.
For Picwell's own front-end applications, we rely on Lodash debounce for handling streams of user input to limit the number of unnecessary requests made to the API.
For more help with Throttle and Debounce, checkout this guide.
Survey
Get Survey Questions
When creating a user, their survey
must be completed. This endpoint exposes the set of questions and possible responses
allowed by the API. For convenience, this same data is displayed in the table below.
[
...
{
"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 /medicare/survey
Response
a List
of Survey Question
objects
List of Survey Questions
ID | Type | Question | Possible Answers | Answer Descriptors | Required | Usage |
---|---|---|---|---|---|---|
1 | physician | How important is it that your current doctor(s) are in the network of the health plan that you choose? |
|
|
true | If a user has a physician preference, have them select a level of importance. |
2 | physician | Think about the doctor who's most important to you. How long have you been with this doctor? |
|
|
true | |
3 | utilization | How many times did you visit a primary care physician in the last 12 months? |
|
|
true | |
4 | utilization | How many times did you visit a specialist in the last 12 months? |
|
|
true | |
5 | utilization | How many times were you admitted to a hospital in the last 12 months? |
|
|
true | |
6 | risk | Imagine that you have a 10% chance of being injured and needing surgery (which means you have a 90% chance you avoid injury and don't have unexpected surgery). Which plan would you choose? |
|
|
false Defaults to plan_a if unspecified. |
|
7 | risk | Imagine that you have a 50% chance of being injured and needing surgery (which means you have a 50% chance you avoid injury and don't have unexpected surgery). Which plan would you choose? |
|
|
false Defaults to plan_b if unspecified. |
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.
When creating a user, the following fields are required: state_code
, age
, and survey
.
survey
requires a minimum of 5 questions answered, with a maximum of 7.
external_id
is required if this user should be using claims data for their recommendation sets.
Request Body
{
"zip_code_3": "193",
"state_code": "PA",
"age": 66,
"external_id": "abc123",
"gender": "female",
"prescriptions": [],
"uses_tobacco": true,
"survey": [{
"answer": "important",
"question_id": "1"
},
{
"answer": "2_3",
"question_id": "2"
},
{
"answer": "not_applicable",
"question_id": "3"
},
{
"answer": "not_applicable",
"question_id": "4"
},
{
"answer": "not_applicable",
"question_id": "5"
},
{
"answer": "plan_a",
"question_id": "6"
},
{
"answer": "plan_a",
"question_id": "7"
}
],
"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 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 /medicare/user
Getting
This endpoint will retrieve details about a user object.
Endpoint
GET /medicare/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": [{
"answer": "important",
"question_id": "1"
},
{
"answer": "2_3",
"question_id": "2"
},
{
"answer": "not_applicable",
"question_id": "3"
},
{
"answer": "not_applicable",
"question_id": "4"
},
{
"answer": "not_applicable",
"question_id": "5"
},
{
"answer": "plan_a",
"question_id": "6"
},
{
"answer": "plan_a",
"question_id": "7"
}
],
"enrolled_in": []
}
Response Body
{
"id":"user-id",
"unknown_ndcs" : {
"2015" : ["ndc1"],
"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 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 /medicare/user/{{user-id}}
Drugs
Drugs are classified using NDCs and represent information about a specific packaging of a drug.
Drug Search by Partial Name
Example Request
GET /drugs?q=lipitor HTTP/1.1
Host: commercial-api.picwell.net
Content-Type: application/json
Picwell-Auth-Token: <your-auth-token>
Accept: application/vnd.picwell.v6+json
Response Body
{
"drugs": [
{
"form": "Oral Tablet",
"name": "LIPITOR",
"strengths": [
{
"full_name": "atorvastatin 80 MG Oral Tablet [Lipitor]",
"generic_name": "atorvastatin 80 MG Oral Tablet",
"generic_rxcui": "259255",
"ndc": "63629336603",
"rxcui": "262095",
"rxnorm_prescribable_name": "Lipitor 80 MG Oral Tablet",
"strength": "80 mg"
},
{
"full_name": "atorvastatin 10 MG Oral Tablet [Lipitor]",
"generic_name": "atorvastatin 10 MG Oral Tablet",
"generic_rxcui": "617312",
"ndc": "13411011301",
"rxcui": "617314",
"rxnorm_prescribable_name": "Lipitor 10 MG Oral Tablet",
"strength": "10 mg"
},
{
"full_name": "atorvastatin 20 MG Oral Tablet [Lipitor]",
"generic_name": "atorvastatin 20 MG Oral Tablet",
"generic_rxcui": "617310",
"ndc": "13411011415",
"rxcui": "617318",
"rxnorm_prescribable_name": "Lipitor 20 MG Oral Tablet",
"strength": "20 mg"
},
{
"full_name": "atorvastatin 40 MG Oral Tablet [Lipitor]",
"generic_name": "atorvastatin 40 MG Oral Tablet",
"generic_rxcui": "617311",
"ndc": "13411011501",
"rxcui": "617320",
"rxnorm_prescribable_name": "Lipitor 40 MG Oral Tablet",
"strength": "40 mg"
}
]
},
{
"brand": "LIPITOR",
"form": "Oral Tablet",
"name": "Atorvastatin",
"strengths": [
{
"full_name": "atorvastatin 80 MG Oral Tablet",
"ndc": "69844000402",
"rxcui": "259255",
"rxnorm_prescribable_name": "atorvastatin calcium 80 MG Oral Tablet",
"strength": "80 mg"
},
{
"full_name": "atorvastatin 20 MG Oral Tablet",
"ndc": "70377002813",
"rxcui": "617310",
"rxnorm_prescribable_name": "atorvastatin calcium 20 MG Oral Tablet",
"strength": "20 mg"
},
{
"full_name": "atorvastatin 40 MG Oral Tablet",
"ndc": "69844000304",
"rxcui": "617311",
"rxnorm_prescribable_name": "atorvastatin calcium 40 MG Oral Tablet",
"strength": "40 mg"
},
{
"full_name": "atorvastatin 10 MG Oral Tablet",
"ndc": "68788686201",
"rxcui": "617312",
"rxnorm_prescribable_name": "atorvastatin calcium 10 MG Oral Tablet",
"strength": "10 mg"
}
]
}
],
"search_term": "lipitor",
"version": "202009"
}
You may use this endpoint to retrieve all drugs matching a partial name.
A common use-case for this endpoint is to act as a search interface for front-end applications. When doing so, be sure to throttle or debounce requests to maximize responsiveness.
See Handling limiting gracefully for more information.
Endpoint
GET /drugs?q={partial-drug-name}
Query String Parameters
Field | Value |
---|---|
q |
Name of drug to search for. Partial and fuzzy matches are supported. |
Schema
See the Drug Search Reference.
Background
The
partial drug name
(input string) you submit in theGET /drugs
request will search Picwell's drug database. Response will include all drugs that match the input string on thename
field as well as drugs with similar names.The response includes branded and generic versions of drugs that match the input string. Generic drugs are indicated by a
brand
key and are included in case you would like to utilize this information in some way for additional UI. If you do not wish to see generics of branded drugs, you can simply filter out allPrescriptionDrug
objects with thebrand
key.Picwell has downstream APIs that require drugs a user takes regularly to be specified (see the
prescriptions
field in theUser
object). This drug information is specified by the NDC (National Drug Code) values; these are obtainable fromdrugs[].strengths[].ndc
inDrugSet
. An NDC is generally unique to a drug's name, form and strength. [1]
Suggestions for Use
Although there are many ways to render a drug search UI/UX using this API, we recommend the following:
With a type-ahead input, iterate through each
PrescriptionDrug
object in theDrugSet
and list thedrugs.name
anddrugs.form
fields for each.Once the
name
andform
for a drug has been selected by the user, prompt the user to select from the relevant strength options (fromdrugs[].strengths[].strength
field).Persist the value of
drugs[].strengths[].ndc
for user selected drugs to utilize in downstream API calls to Picwell.For certain drugs, it may be necessary to require the user to select from additional prescribable volumes to fully specify a drug. Enable this lookup by supporting selections against
drugs[].strengths[].rxnorm_prescribable_name
[1] For about 3% of drugs in our database, a name
, form
, and strength
combination is not enough to create a
unique identifier because there are duplicate strengths for certain forms. An example of this is the form Prefilled
Syringe in the drug Heparin. As you can see in the response below, the strength
fields are both 1 unt/ml
. This
is because the volumes are different but the drug proportions are the same. In this case, we recommend showing a
third input step after strength, containing the rxnorm_presribable_name
field of the duplicates. This field will
give the volume or any other information to distinguish the 2 drugs.
Drug Search by NDC
Example Request
GET /drug_details/57883040504
Response Body (Branded Drug)
{
"brands": null,
"form": "Topical Lotion",
"full_name": "sulfacetamide sodium 98 MG/ML / sulfur 48 MG/ML Topical Lotion [Plexion]",
"generic_name": "sulfacetamide sodium 98 MG/ML / sulfur 48 MG/ML Topical Lotion",
"generic_rxcui": "1494174",
"name": "PLEXION",
"ndc": "57883040504",
"rxcui": "1494824",
"rxnorm_prescribable_name": "PLEXION 9.8 % / 4.8 % Topical Lotion",
"strength": "9.8-4.8%"
}
Response Body (Generic Drug)
{
"brands": [
"PLEXION"
],
"form": "Topical Lotion",
"full_name": "sulfacetamide sodium 100 MG/ML / sulfur 50 MG/ML Topical Lotion",
"generic_name": null,
"generic_rxcui": null,
"name": "Sulfacetamide/Sulfur",
"ndc": "42792010702",
"rxcui": "1005856",
"rxnorm_prescribable_name": "sulfacetamide sodium 10 % / sulfur 5 % Topical Lotion",
"strength": "10-5%"
}
You may use this endpoint to retrieve the drug details matching the given NDC.
Endpoint
GET /drug_details/{ndc}
Schema
See the Drug Details Reference.
Discussion
- If no drug exists with the
ndc
, response code will beHTTP 404 Not Found
.
Recommendations
For A Single Medicare Product
Endpoint
POST /medicare/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 /medicare/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 /medicare/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 /medicare/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 /medicare/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 /medicare/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 /medicare/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 /medicare/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 /medicare/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 expressions to Result Sets generated by a recommendation request.
Endpoints:
POST /medicare/recommendation/results/{Result Set.id}/filter
GET /medicare/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 /medicare/recommendation/results/{Result Set.id}/page/<page number: int>?sort_by=<mail|retail>
POST /medicare/recommendation/results/{Result Set.id}/filter?sort_by=<mail|retail>
GET /medicare/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.
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 /medicare/recommendation/2017/c2392ff4-f7c0-4137-baf0-fa0448c1be1f?source=callcenter
Medicare Packages recommendation request from self-service website:
POST /medicare/recommendation/2017/c2392ff4-f7c0-4137-baf0-fa0448c1be1f?source=selfservice
Part D recommendation request from call-center:
POST /medicare/recommendation/pdp/2017/c2392ff4-f7c0-4137-baf0-fa0448c1be1f?source=callcenter
Claims (Experimental)
This set of endpoints is currently for internal purposes only. If you are interested in sending us detailed claims, please contact your Picwell representative.
Create or Update
This endpoint will persist the specified User Data From Claims.
If the given user_external_id
already exists then their claims will be updated with the latest values.
Request Body
{
"user_external_id": "abc123",
"detailed_costs": [
{
"cost": 100.00,
"date": "2022-01-01"
},
{
"cost": 50.00,
"date": "2022-02-01"
}
],
"diagnoses": [
{
"code": "F514",
"code_type": "ICD10"
},
{
"code": "Z9862",
"code_type": "ICD10"
}
],
"drugs": [
{
"ndc": "00169517510"
},
{
"ndc": "67296141508"
}
]
}
Response Body
{
"user_external_id": "abc123"
}
Endpoint
PUT /medicare/claims
Response
A message containing the user_external_id
that was created or updated.
Get Drugs from Claims
Get a user's set of prescribed drugs.
If a given user has no drug claims, expect an empty list of NDCs.
If we have no knowledge of a given user, this endpoint will respond with a 404 status code.
Response Body
{
"user_external_id": "abc123",
"ndcs": [
"00169517510",
"67296141508"
]
}
Endpoint
GET /medicare/claims/{{user_external_id}}/drugs
Response
A DrugsFromClaimsForUserResponse
object.
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 Search Reference
Drug Search Response
The response object of a Drug Search by Partial Name query.
Name | Type | Description | Example |
---|---|---|---|
drugs |
[Drug] | Drug results for the given query. | |
search_term |
string | The specified search query. | lipitor |
version |
string | Version of our drug data set. | 202009 |
Drug
Name | Type | Description | Example |
---|---|---|---|
brand |
string | The brand name of the drug. Only set for generic variants. | LIPITOR |
form |
string | The form of the drug. | Oral Tablet |
name |
string | The marketed name of the drug. | LIPITOR |
strengths |
[Drug Strength] | Available strengths of this given form. | Oral Tablet |
Drug Strength
Name | Type | Description | Example |
---|---|---|---|
full_name |
string | Full name of the drug including ingredient, strength, form, and brand name. | atorvastatin 80 MG Oral Tablet [Lipitor] |
generic_name |
string | Full name of the drug including ingredient, strength, and form. Will not be set for generic forms. | atorvastatin 80 MG Oral Tablet |
generic_rxcui |
string | The RxNorm Concept Unique Identifier of the corresponding generic, if it exists. Will not be set for generic forms. | 259255 |
ndc |
string | A (representative) National Drug Code corresponding to the RxCUI. | 63629336603 |
rxcui |
string | The RxNorm Concept Unique Identifier. | 262095 |
rxnorm_prescribable_name |
string | The RxNorm suggested full name of the drug for writing prescriptions. | Lipitor 80 MG Oral Tablet |
strength |
string | The strength of the drug. | 80 mg |
Drug Details Reference
The response object of a Drug Search by NDC query.
Name | Type | Description | Example |
---|---|---|---|
brands | List[string] | The brand names of the drug. Only set for generic variants. | ["PLEXION"] |
form | string | The form of the drug. | "Topical Lotion" |
name | string | The marketed name of the drug. | "PLEXION" |
full_name | string | Full name of drug including strength and form | "sulfacetamide sodium 98 MG/ML / sulfur 48 MG/ML Topical Lotion [Plexion]" |
generic_name | string | Full name of the drug including ingredient, strength, and form. Will not be set for generic forms. | "sulfacetamide sodium 98 MG/ML / sulfur 48 MG/ML Topical Lotion" |
generic_rxcui | string | The RxNorm Concept Unique Identifier of the corresponding generic, if it exists. Will not be set for generic forms. | "1494174" |
ndc | string | A (representative) National Drug Code corresponding to the RxCUI. | "57883040504" |
rxcui | string | The RxNorm Concept Unique Identifier | "1494824" |
rxnorm_prescribable_name | string | The RxNorm suggested full name of the drug for writing prescriptions. | "PLEXION 9.8 % / 4.8 % Topical Lotion" |
strength | string | The strength of the drug. | "9.8-4.8%" |
- The
generic_name
andgeneric_rxcui
fields only exist for objects of branded drugs. - The
brands
field only exist for objects of generic drugs.
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 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 |
string | an internally used identifier for a plan. |
external_id |
string | Unique 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'. |
external_id |
string | Unique identifier for the plan. If you have not provided us a mapping file between plan IDs and Medicare plans (most cases), provide medicare_id when requesting pdp, ma, or mapd plans and provide medigap_plan and optionally medigap_riders when requesting gap plans. If you have provided us a mapping file between plan IDs and Medicare plans, external_id should be an ID from the mapping file and medicare_id , medigap_plan , and medigap_riders should not be set. |
medicare_id |
string | Unique identifier for the plan for use when you have not provided an ID mapping file to Picwell. Use medicare_id when requesting an ma , mapd , or pdp plan, and medigap_plan /medigap_riders when requesting a gap plan. See valid medicare ids below for more info. |
medigap_plan |
string | Medigap plan identifier for use when you have not provided an ID mapping file to Picwell. For example, the following are valid: A (National A), F_S_I (Innovative F Select), and MA_SUPP1 (Massachusetts' Supplemental 1 plan). Use medicare_id when requesting an ma , mapd , or pdp plan, and medigap_plan /medigap_riders when requesting a gap plan. See valid medigap plans and riders below for more info. |
medigap_riders |
[string] | A list of Medigap plan rider identifiers for plans that support them, for use when you have not provided an ID mapping file to Picwell. For example, ["RAD", "MN_RBD", "MN_RBEC"] . Use medicare_id when requesting an ma , mapd , or pdp plan, and medigap_plan /medigap_riders when requesting a gap plan. See valid medigap plans and riders below for more info. |
monthly_premium |
float | The monthly premium for the plan (optional key). Premiums are only required for gap plans; do not include this field for ma , mapd or pdp plans as it will be ignored |
drug_costs |
[External Drug Costs] | A list of drug costs if you prefer use your own drug costs, as opposed to Picwell's Part D calculator. (optional) If the drug_costs key is provided for any pdp or mapd 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. |
health_provider_locations |
[Health Provider Location] | 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. {} ). |
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. |
Valid Medicare IDs
For convenience, we accept a few different variations of Part C (starting with H and R) and Part D (starting with S) plan IDs. The following examples are all acceptable in a given plan reference:
S4800:001:100
S4800:001-0
S4800-01-0
S4800:1-0
The recommendation response will return an internally normalized representation of what is given, typically of the form A0000-111-222
.
Valid Medigap Plans and Riders
We accept the following medigap_plan
and medigap_riders
identifiers.
The following national plans:
A
A_S
B
B_S
C
C_S
D
D_S
F
F_H
F_H_S
F_S
F_I
F_S_I
G
G_S
G_H
G_H_S
K
K_S
L
L_S
M
M_S
N
N_S
.. where S
represents select plan variants with narrower networks, I
represents innovative plan variants with enhanced benefits for vision and hearing aids, and H
represents high-deductible plan variants. F
, C
, and their variants were sold before 1/1/2020, and they are kept for grandfathered plans.
The following Minnesota base plans:
MN
: Basic planMN_EX
: Extended Basic planMN_EX_PBDU
: Extended Basic plan without Part-B deductible coverageMN_HDP
: High-deductible planMN_CP
: $20/$50 Copay planMN_K
: 50% Coverage planMN_L
: 75% Coverage plan
The following Minnesota riders:
RAD
: Part-A Deductible riderMN_RBD
: Part-B Deductible riderMN_RBEC
: Part-B Excess Charge riderRBNP
: Preventive Medical Care rider
MN_EX
and MN_RBD
were sold before 1/1/2020, and they are kept for grandfathered plans.
The following Wisconsin base plans:
WI
: Basic planWI_BC
: Basic with Copay planWI_K
: 50% Cost Sharing planWI_L
: 25% Cost Sharing plan
The following WI
riders:
R50AD
: 50% Part-A Deductible riderR75AD
: 75% Part-A Deductible riderR100AD
: Part-A Deductible riderRHHC
: Additional Home Health Care riderWI_RBD
: Part-B Deductible riderWI_RBEC
: Part-B Excess Charge riderRFT
: Foreign Travel Emergency riderRBC
: Part-B Copay rider where the beneficiary pays a 20% copay (up to a maximum of $20) per doctor's office visit or a 20% copay (up to $50 maximum) per an emergency room visit after Part-B deductible
WI_RBD
was sold before 1/1/2020, and it is kept for grandfathered plans.
The following Massachusetts base plans:
MA_CORE
: Core planMA_SUPP1A
: Supplement 1 plan without Part-B deductible coverageMA_SUPP1
: Supplement 1 plan
MA_SUPP1
was sold before 1/1/2020, and it is kept for grandfathered plans.
See CMS's How to compare Medigap policies page for more information.
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 |
external_id |
string | the user's external_id from claims data, used in recommendations (optional key) |
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}
User Data From Claims
A representation of user data from claims
keys | type | description | example |
---|---|---|---|
user_external_id |
string | unique identifier for user | user1234 |
detailed_costs |
[Detailed Cost] | list of detailed costs | |
diagonoses |
[Diagnosis] | list of diagnoses | |
drugs |
[Drugs From Claims] | list of drugs from claims |
Detailed Cost
A user's cost for a given claim.
keys | type | description | example |
---|---|---|---|
cost |
float | cost of claim | 4042 |
date |
string | date of the form YYYY-MM-DD |
2022-03-23 |
Diagnosis
A user's diagnosis code and its associated code type.
keys | type | description | example |
---|---|---|---|
code |
string | diagnosis code | I462 |
code_type |
string | diagnosis code type | ICD10 |
Drugs From Claims
A user's prescribed drug for a given claim.
keys | type | description | example |
---|---|---|---|
ndc |
string | 11 digit National Drug Code | 00071015510 |
Drugs From Claims For User Response
Drug information from claims for a user.
keys | type | description |
---|---|---|
user_external_id |
string | the user's external id |
ndcs |
[string] | list of NDCs from a given user's claims data |
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. |
429 | Too Many Requests | The HTTP 429 Too Many Requests response status code indicates the user has sent too many requests in a given amount of time ("rate limiting"). |
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, user edit, and recommendation requests. In the sidebar is a consolidation of these error 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", "..."]
},
// medigap plans that do not match via a client data file
"invalid_medigap_plans" : ["plan1", "plan2", "..."],
// medigap riders that do not match via a client data file
"invalid_medigap_riders" : ["rider1", "rider2", "..."]
}
}
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:
/medicare/recommendation/tm+gap+pdp,ma+pdp/2015/user123
are not comparable to Picwell Scores returned for a request seeking all packages:
/medicare/recommendation/2015/user123
How does Picwell handle recommendations for two plan years?
If a user is simultaneously 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.
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