NAV

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:

The API also supports recommendations for specific Medicare plan types, as described here.

Changelog

Summary of changes to the API over time.

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:

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

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:

  1. Ignore stale data to improve user experience ("debouncing"). We recommend this for typeahead search interfaces.
  2. 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?
  • not_applicable
  • not_important
  • not_very_important
  • important
  • very_important
  • Not applicable; I do not have doctor(s)
  • Not Important at all
  • Not Very Important
  • Important
  • Very Important
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?
  • 0
  • lte_1
  • 2_3
  • 4_5
  • gte_5
  • I do not have a current physician
  • One year or less
  • 2 to 3 years
  • 4 to 5 years
  • 5 or more years
true
3 utilization How many times did you visit a primary care physician in the last 12 months?
  • not_applicable
  • 0
  • 1_3
  • gte_4
  • This input variable is not available
  • I did not visit a primary care physician last year
  • 1 to 3 times
  • 4 or more times
true
4 utilization How many times did you visit a specialist in the last 12 months?
  • not_applicable
  • 0
  • 1_4
  • 5_9
  • gte_10
  • This input variable is not available
  • I did not visit a specialist last year
  • 1 to 4 times
  • 5 to 9 times
  • 10 or more times
true
5 utilization How many times were you admitted to a hospital in the last 12 months?
  • not_applicable
  • 0
  • 1
  • gte_2
  • This input variable is not available
  • I was not admitted to a hospital last year
  • 1 time
  • 2 or more times
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?
  • plan_a
  • plan_b
  • Plan A: where your annual plan costs (premiums) are $3000 higher and you pay $0 out-of-pocket for the surgery.
  • Plan B: where your annual plan costs (premiums) are $3000 lower, but you have to pay $5000 out-of-pocket for the surgery.
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?
  • plan_a
  • plan_b
  • Plan A: where your annual plan costs (premiums) are $3000 higher and you pay $0 out-of-pocket for the surgery.
  • Plan B: where your annual plan costs (premiums) are $3000 lower, but you have to pay $5000 out-of-pocket for the surgery.
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

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

Suggestions for Use

Although there are many ways to render a drug search UI/UX using this API, we recommend the following:

  1. With a type-ahead input, iterate through each PrescriptionDrug object in the DrugSet and list the drugs.name and drugs.form fields for each.

  2. Once the name and form for a drug has been selected by the user, prompt the user to select from the relevant strength options (from drugs[].strengths[].strength field).

  3. Persist the value of drugs[].strengths[].ndc for user selected drugs to utilize in downstream API calls to Picwell.

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

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

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

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

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 }

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}

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:

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)

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%"

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.

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:

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:

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

The following Minnesota riders:

MN_EX and MN_RBD were sold before 1/1/2020, and they are kept for grandfathered plans.

The following Wisconsin base plans:

The following WI riders:

WI_RBD was sold before 1/1/2020, and it is kept for grandfathered plans.

The following Massachusetts base plans:

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

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)

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

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:

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:

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: